1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2 // Copyright(c) 2015-17 Intel Corporation.
5 * MIPI Discovery And Configuration (DisCo) Specification for SoundWire
6 * specifies properties to be implemented for SoundWire Masters and Slaves.
7 * The DisCo spec doesn't mandate these properties. However, SDW bus cannot
8 * work without knowing these values.
10 * The helper functions read the Master and Slave properties. Implementers
11 * of Master or Slave drivers can use any of the below three mechanisms:
12 * a) Use these APIs here as .read_prop() callback for Master and Slave
13 * b) Implement own methods and set those as .read_prop(), but invoke
14 * APIs in this file for generic read and override the values with
15 * platform specific data
16 * c) Implement ones own methods which do not use anything provided
20 #include <linux/device.h>
21 #include <linux/property.h>
22 #include <linux/mod_devicetable.h>
23 #include <linux/soundwire/sdw.h>
27 * sdw_master_read_prop() - Read Master properties
28 * @bus: SDW bus instance
30 int sdw_master_read_prop(struct sdw_bus
*bus
)
32 struct sdw_master_prop
*prop
= &bus
->prop
;
33 struct fwnode_handle
*link
;
37 device_property_read_u32(bus
->dev
,
38 "mipi-sdw-sw-interface-revision",
41 /* Find master handle */
42 snprintf(name
, sizeof(name
),
43 "mipi-sdw-link-%d-subproperties", bus
->link_id
);
45 link
= device_get_named_child_node(bus
->dev
, name
);
47 dev_err(bus
->dev
, "Master node %s not found\n", name
);
51 if (fwnode_property_read_bool(link
,
52 "mipi-sdw-clock-stop-mode0-supported"))
53 prop
->clk_stop_modes
|= BIT(SDW_CLK_STOP_MODE0
);
55 if (fwnode_property_read_bool(link
,
56 "mipi-sdw-clock-stop-mode1-supported"))
57 prop
->clk_stop_modes
|= BIT(SDW_CLK_STOP_MODE1
);
59 fwnode_property_read_u32(link
,
60 "mipi-sdw-max-clock-frequency",
63 nval
= fwnode_property_count_u32(link
, "mipi-sdw-clock-frequencies-supported");
65 prop
->num_clk_freq
= nval
;
66 prop
->clk_freq
= devm_kcalloc(bus
->dev
, prop
->num_clk_freq
,
67 sizeof(*prop
->clk_freq
),
69 if (!prop
->clk_freq
) {
70 fwnode_handle_put(link
);
74 fwnode_property_read_u32_array(link
,
75 "mipi-sdw-clock-frequencies-supported",
76 prop
->clk_freq
, prop
->num_clk_freq
);
80 * Check the frequencies supported. If FW doesn't provide max
81 * freq, then populate here by checking values.
83 if (!prop
->max_clk_freq
&& prop
->clk_freq
) {
84 prop
->max_clk_freq
= prop
->clk_freq
[0];
85 for (i
= 1; i
< prop
->num_clk_freq
; i
++) {
86 if (prop
->clk_freq
[i
] > prop
->max_clk_freq
)
87 prop
->max_clk_freq
= prop
->clk_freq
[i
];
91 nval
= fwnode_property_count_u32(link
, "mipi-sdw-supported-clock-gears");
93 prop
->num_clk_gears
= nval
;
94 prop
->clk_gears
= devm_kcalloc(bus
->dev
, prop
->num_clk_gears
,
95 sizeof(*prop
->clk_gears
),
97 if (!prop
->clk_gears
) {
98 fwnode_handle_put(link
);
102 fwnode_property_read_u32_array(link
,
103 "mipi-sdw-supported-clock-gears",
105 prop
->num_clk_gears
);
108 fwnode_property_read_u32(link
, "mipi-sdw-default-frame-rate",
109 &prop
->default_frame_rate
);
111 fwnode_property_read_u32(link
, "mipi-sdw-default-frame-row-size",
114 fwnode_property_read_u32(link
, "mipi-sdw-default-frame-col-size",
117 prop
->dynamic_frame
= fwnode_property_read_bool(link
,
118 "mipi-sdw-dynamic-frame-shape");
120 fwnode_property_read_u32(link
, "mipi-sdw-command-error-threshold",
121 &prop
->err_threshold
);
123 fwnode_handle_put(link
);
127 EXPORT_SYMBOL(sdw_master_read_prop
);
129 static int sdw_slave_read_dp0(struct sdw_slave
*slave
,
130 struct fwnode_handle
*port
,
131 struct sdw_dp0_prop
*dp0
)
135 fwnode_property_read_u32(port
, "mipi-sdw-port-max-wordlength",
138 fwnode_property_read_u32(port
, "mipi-sdw-port-min-wordlength",
141 nval
= fwnode_property_count_u32(port
, "mipi-sdw-port-wordlength-configs");
144 dp0
->num_words
= nval
;
145 dp0
->words
= devm_kcalloc(&slave
->dev
,
146 dp0
->num_words
, sizeof(*dp0
->words
),
151 fwnode_property_read_u32_array(port
,
152 "mipi-sdw-port-wordlength-configs",
153 dp0
->words
, dp0
->num_words
);
156 dp0
->BRA_flow_controlled
= fwnode_property_read_bool(port
,
157 "mipi-sdw-bra-flow-controlled");
159 dp0
->simple_ch_prep_sm
= fwnode_property_read_bool(port
,
160 "mipi-sdw-simplified-channel-prepare-sm");
162 dp0
->imp_def_interrupts
= fwnode_property_read_bool(port
,
163 "mipi-sdw-imp-def-dp0-interrupts-supported");
168 static int sdw_slave_read_dpn(struct sdw_slave
*slave
,
169 struct sdw_dpn_prop
*dpn
, int count
, int ports
,
172 struct fwnode_handle
*node
;
179 /* valid ports are 1 to 14 so apply mask */
180 addr
&= GENMASK(14, 1);
182 for_each_set_bit(bit
, &addr
, 32) {
183 snprintf(name
, sizeof(name
),
184 "mipi-sdw-dp-%d-%s-subproperties", bit
, type
);
188 node
= device_get_named_child_node(&slave
->dev
, name
);
190 dev_err(&slave
->dev
, "%s dpN not found\n", name
);
194 fwnode_property_read_u32(node
, "mipi-sdw-port-max-wordlength",
196 fwnode_property_read_u32(node
, "mipi-sdw-port-min-wordlength",
199 nval
= fwnode_property_count_u32(node
, "mipi-sdw-port-wordlength-configs");
201 dpn
[i
].num_words
= nval
;
202 dpn
[i
].words
= devm_kcalloc(&slave
->dev
,
204 sizeof(*dpn
[i
].words
),
207 fwnode_handle_put(node
);
211 fwnode_property_read_u32_array(node
,
212 "mipi-sdw-port-wordlength-configs",
213 dpn
[i
].words
, dpn
[i
].num_words
);
216 fwnode_property_read_u32(node
, "mipi-sdw-data-port-type",
219 fwnode_property_read_u32(node
,
220 "mipi-sdw-max-grouping-supported",
221 &dpn
[i
].max_grouping
);
223 dpn
[i
].simple_ch_prep_sm
= fwnode_property_read_bool(node
,
224 "mipi-sdw-simplified-channelprepare-sm");
226 fwnode_property_read_u32(node
,
227 "mipi-sdw-port-channelprepare-timeout",
228 &dpn
[i
].ch_prep_timeout
);
230 fwnode_property_read_u32(node
,
231 "mipi-sdw-imp-def-dpn-interrupts-supported",
232 &dpn
[i
].imp_def_interrupts
);
234 fwnode_property_read_u32(node
, "mipi-sdw-min-channel-number",
237 fwnode_property_read_u32(node
, "mipi-sdw-max-channel-number",
240 nval
= fwnode_property_count_u32(node
, "mipi-sdw-channel-number-list");
242 dpn
[i
].num_channels
= nval
;
243 dpn
[i
].channels
= devm_kcalloc(&slave
->dev
,
245 sizeof(*dpn
[i
].channels
),
247 if (!dpn
[i
].channels
) {
248 fwnode_handle_put(node
);
252 fwnode_property_read_u32_array(node
,
253 "mipi-sdw-channel-number-list",
254 dpn
[i
].channels
, dpn
[i
].num_channels
);
257 nval
= fwnode_property_count_u32(node
, "mipi-sdw-channel-combination-list");
259 dpn
[i
].num_ch_combinations
= nval
;
260 dpn
[i
].ch_combinations
= devm_kcalloc(&slave
->dev
,
261 dpn
[i
].num_ch_combinations
,
262 sizeof(*dpn
[i
].ch_combinations
),
264 if (!dpn
[i
].ch_combinations
) {
265 fwnode_handle_put(node
);
269 fwnode_property_read_u32_array(node
,
270 "mipi-sdw-channel-combination-list",
271 dpn
[i
].ch_combinations
,
272 dpn
[i
].num_ch_combinations
);
275 fwnode_property_read_u32(node
,
276 "mipi-sdw-modes-supported", &dpn
[i
].modes
);
278 fwnode_property_read_u32(node
, "mipi-sdw-max-async-buffer",
279 &dpn
[i
].max_async_buffer
);
281 dpn
[i
].block_pack_mode
= fwnode_property_read_bool(node
,
282 "mipi-sdw-block-packing-mode");
284 fwnode_property_read_u32(node
, "mipi-sdw-port-encoding-type",
285 &dpn
[i
].port_encoding
);
287 /* TODO: Read audio mode */
289 fwnode_handle_put(node
);
298 * sdw_slave_read_prop() - Read Slave properties
301 int sdw_slave_read_prop(struct sdw_slave
*slave
)
303 struct sdw_slave_prop
*prop
= &slave
->prop
;
304 struct device
*dev
= &slave
->dev
;
305 struct fwnode_handle
*port
;
308 device_property_read_u32(dev
, "mipi-sdw-sw-interface-revision",
309 &prop
->mipi_revision
);
311 prop
->wake_capable
= device_property_read_bool(dev
,
312 "mipi-sdw-wake-up-unavailable");
313 prop
->wake_capable
= !prop
->wake_capable
;
315 prop
->test_mode_capable
= device_property_read_bool(dev
,
316 "mipi-sdw-test-mode-supported");
318 prop
->clk_stop_mode1
= false;
319 if (device_property_read_bool(dev
,
320 "mipi-sdw-clock-stop-mode1-supported"))
321 prop
->clk_stop_mode1
= true;
323 prop
->simple_clk_stop_capable
= device_property_read_bool(dev
,
324 "mipi-sdw-simplified-clockstopprepare-sm-supported");
326 device_property_read_u32(dev
, "mipi-sdw-clockstopprepare-timeout",
327 &prop
->clk_stop_timeout
);
329 device_property_read_u32(dev
, "mipi-sdw-slave-channelprepare-timeout",
330 &prop
->ch_prep_timeout
);
332 device_property_read_u32(dev
,
333 "mipi-sdw-clockstopprepare-hard-reset-behavior",
334 &prop
->reset_behave
);
336 prop
->high_PHY_capable
= device_property_read_bool(dev
,
337 "mipi-sdw-highPHY-capable");
339 prop
->paging_support
= device_property_read_bool(dev
,
340 "mipi-sdw-paging-support");
342 prop
->bank_delay_support
= device_property_read_bool(dev
,
343 "mipi-sdw-bank-delay-support");
345 device_property_read_u32(dev
,
346 "mipi-sdw-port15-read-behavior", &prop
->p15_behave
);
348 device_property_read_u32(dev
, "mipi-sdw-master-count",
349 &prop
->master_count
);
351 device_property_read_u32(dev
, "mipi-sdw-source-port-list",
352 &prop
->source_ports
);
354 device_property_read_u32(dev
, "mipi-sdw-sink-port-list",
357 /* Read dp0 properties */
358 port
= device_get_named_child_node(dev
, "mipi-sdw-dp-0-subproperties");
360 dev_dbg(dev
, "DP0 node not found!!\n");
362 prop
->dp0_prop
= devm_kzalloc(&slave
->dev
,
363 sizeof(*prop
->dp0_prop
),
365 if (!prop
->dp0_prop
) {
366 fwnode_handle_put(port
);
370 sdw_slave_read_dp0(slave
, port
, prop
->dp0_prop
);
372 fwnode_handle_put(port
);
376 * Based on each DPn port, get source and sink dpn properties.
377 * Also, some ports can operate as both source or sink.
380 /* Allocate memory for set bits in port lists */
381 nval
= hweight32(prop
->source_ports
);
382 prop
->src_dpn_prop
= devm_kcalloc(&slave
->dev
, nval
,
383 sizeof(*prop
->src_dpn_prop
),
385 if (!prop
->src_dpn_prop
)
388 /* Read dpn properties for source port(s) */
389 sdw_slave_read_dpn(slave
, prop
->src_dpn_prop
, nval
,
390 prop
->source_ports
, "source");
392 nval
= hweight32(prop
->sink_ports
);
393 prop
->sink_dpn_prop
= devm_kcalloc(&slave
->dev
, nval
,
394 sizeof(*prop
->sink_dpn_prop
),
396 if (!prop
->sink_dpn_prop
)
399 /* Read dpn properties for sink port(s) */
400 sdw_slave_read_dpn(slave
, prop
->sink_dpn_prop
, nval
,
401 prop
->sink_ports
, "sink");
405 EXPORT_SYMBOL(sdw_slave_read_prop
);