18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) 28c2ecf20Sopenharmony_ci// Copyright(c) 2015-17 Intel Corporation. 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci/* 58c2ecf20Sopenharmony_ci * MIPI Discovery And Configuration (DisCo) Specification for SoundWire 68c2ecf20Sopenharmony_ci * specifies properties to be implemented for SoundWire Masters and Slaves. 78c2ecf20Sopenharmony_ci * The DisCo spec doesn't mandate these properties. However, SDW bus cannot 88c2ecf20Sopenharmony_ci * work without knowing these values. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * The helper functions read the Master and Slave properties. Implementers 118c2ecf20Sopenharmony_ci * of Master or Slave drivers can use any of the below three mechanisms: 128c2ecf20Sopenharmony_ci * a) Use these APIs here as .read_prop() callback for Master and Slave 138c2ecf20Sopenharmony_ci * b) Implement own methods and set those as .read_prop(), but invoke 148c2ecf20Sopenharmony_ci * APIs in this file for generic read and override the values with 158c2ecf20Sopenharmony_ci * platform specific data 168c2ecf20Sopenharmony_ci * c) Implement ones own methods which do not use anything provided 178c2ecf20Sopenharmony_ci * here 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include <linux/device.h> 218c2ecf20Sopenharmony_ci#include <linux/property.h> 228c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h> 238c2ecf20Sopenharmony_ci#include <linux/soundwire/sdw.h> 248c2ecf20Sopenharmony_ci#include "bus.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci/** 278c2ecf20Sopenharmony_ci * sdw_master_read_prop() - Read Master properties 288c2ecf20Sopenharmony_ci * @bus: SDW bus instance 298c2ecf20Sopenharmony_ci */ 308c2ecf20Sopenharmony_ciint sdw_master_read_prop(struct sdw_bus *bus) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci struct sdw_master_prop *prop = &bus->prop; 338c2ecf20Sopenharmony_ci struct fwnode_handle *link; 348c2ecf20Sopenharmony_ci char name[32]; 358c2ecf20Sopenharmony_ci int nval, i; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci device_property_read_u32(bus->dev, 388c2ecf20Sopenharmony_ci "mipi-sdw-sw-interface-revision", 398c2ecf20Sopenharmony_ci &prop->revision); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci /* Find master handle */ 428c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), 438c2ecf20Sopenharmony_ci "mipi-sdw-link-%d-subproperties", bus->link_id); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci link = device_get_named_child_node(bus->dev, name); 468c2ecf20Sopenharmony_ci if (!link) { 478c2ecf20Sopenharmony_ci dev_err(bus->dev, "Master node %s not found\n", name); 488c2ecf20Sopenharmony_ci return -EIO; 498c2ecf20Sopenharmony_ci } 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci if (fwnode_property_read_bool(link, 528c2ecf20Sopenharmony_ci "mipi-sdw-clock-stop-mode0-supported")) 538c2ecf20Sopenharmony_ci prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE0); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (fwnode_property_read_bool(link, 568c2ecf20Sopenharmony_ci "mipi-sdw-clock-stop-mode1-supported")) 578c2ecf20Sopenharmony_ci prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE1); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci fwnode_property_read_u32(link, 608c2ecf20Sopenharmony_ci "mipi-sdw-max-clock-frequency", 618c2ecf20Sopenharmony_ci &prop->max_clk_freq); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci nval = fwnode_property_count_u32(link, "mipi-sdw-clock-frequencies-supported"); 648c2ecf20Sopenharmony_ci if (nval > 0) { 658c2ecf20Sopenharmony_ci prop->num_clk_freq = nval; 668c2ecf20Sopenharmony_ci prop->clk_freq = devm_kcalloc(bus->dev, prop->num_clk_freq, 678c2ecf20Sopenharmony_ci sizeof(*prop->clk_freq), 688c2ecf20Sopenharmony_ci GFP_KERNEL); 698c2ecf20Sopenharmony_ci if (!prop->clk_freq) 708c2ecf20Sopenharmony_ci return -ENOMEM; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci fwnode_property_read_u32_array(link, 738c2ecf20Sopenharmony_ci "mipi-sdw-clock-frequencies-supported", 748c2ecf20Sopenharmony_ci prop->clk_freq, prop->num_clk_freq); 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci /* 788c2ecf20Sopenharmony_ci * Check the frequencies supported. If FW doesn't provide max 798c2ecf20Sopenharmony_ci * freq, then populate here by checking values. 808c2ecf20Sopenharmony_ci */ 818c2ecf20Sopenharmony_ci if (!prop->max_clk_freq && prop->clk_freq) { 828c2ecf20Sopenharmony_ci prop->max_clk_freq = prop->clk_freq[0]; 838c2ecf20Sopenharmony_ci for (i = 1; i < prop->num_clk_freq; i++) { 848c2ecf20Sopenharmony_ci if (prop->clk_freq[i] > prop->max_clk_freq) 858c2ecf20Sopenharmony_ci prop->max_clk_freq = prop->clk_freq[i]; 868c2ecf20Sopenharmony_ci } 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci nval = fwnode_property_count_u32(link, "mipi-sdw-supported-clock-gears"); 908c2ecf20Sopenharmony_ci if (nval > 0) { 918c2ecf20Sopenharmony_ci prop->num_clk_gears = nval; 928c2ecf20Sopenharmony_ci prop->clk_gears = devm_kcalloc(bus->dev, prop->num_clk_gears, 938c2ecf20Sopenharmony_ci sizeof(*prop->clk_gears), 948c2ecf20Sopenharmony_ci GFP_KERNEL); 958c2ecf20Sopenharmony_ci if (!prop->clk_gears) 968c2ecf20Sopenharmony_ci return -ENOMEM; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci fwnode_property_read_u32_array(link, 998c2ecf20Sopenharmony_ci "mipi-sdw-supported-clock-gears", 1008c2ecf20Sopenharmony_ci prop->clk_gears, 1018c2ecf20Sopenharmony_ci prop->num_clk_gears); 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci fwnode_property_read_u32(link, "mipi-sdw-default-frame-rate", 1058c2ecf20Sopenharmony_ci &prop->default_frame_rate); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci fwnode_property_read_u32(link, "mipi-sdw-default-frame-row-size", 1088c2ecf20Sopenharmony_ci &prop->default_row); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci fwnode_property_read_u32(link, "mipi-sdw-default-frame-col-size", 1118c2ecf20Sopenharmony_ci &prop->default_col); 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci prop->dynamic_frame = fwnode_property_read_bool(link, 1148c2ecf20Sopenharmony_ci "mipi-sdw-dynamic-frame-shape"); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci fwnode_property_read_u32(link, "mipi-sdw-command-error-threshold", 1178c2ecf20Sopenharmony_ci &prop->err_threshold); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci return 0; 1208c2ecf20Sopenharmony_ci} 1218c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sdw_master_read_prop); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic int sdw_slave_read_dp0(struct sdw_slave *slave, 1248c2ecf20Sopenharmony_ci struct fwnode_handle *port, 1258c2ecf20Sopenharmony_ci struct sdw_dp0_prop *dp0) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci int nval; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci fwnode_property_read_u32(port, "mipi-sdw-port-max-wordlength", 1308c2ecf20Sopenharmony_ci &dp0->max_word); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci fwnode_property_read_u32(port, "mipi-sdw-port-min-wordlength", 1338c2ecf20Sopenharmony_ci &dp0->min_word); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci nval = fwnode_property_count_u32(port, "mipi-sdw-port-wordlength-configs"); 1368c2ecf20Sopenharmony_ci if (nval > 0) { 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci dp0->num_words = nval; 1398c2ecf20Sopenharmony_ci dp0->words = devm_kcalloc(&slave->dev, 1408c2ecf20Sopenharmony_ci dp0->num_words, sizeof(*dp0->words), 1418c2ecf20Sopenharmony_ci GFP_KERNEL); 1428c2ecf20Sopenharmony_ci if (!dp0->words) 1438c2ecf20Sopenharmony_ci return -ENOMEM; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci fwnode_property_read_u32_array(port, 1468c2ecf20Sopenharmony_ci "mipi-sdw-port-wordlength-configs", 1478c2ecf20Sopenharmony_ci dp0->words, dp0->num_words); 1488c2ecf20Sopenharmony_ci } 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci dp0->BRA_flow_controlled = fwnode_property_read_bool(port, 1518c2ecf20Sopenharmony_ci "mipi-sdw-bra-flow-controlled"); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci dp0->simple_ch_prep_sm = fwnode_property_read_bool(port, 1548c2ecf20Sopenharmony_ci "mipi-sdw-simplified-channel-prepare-sm"); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci dp0->imp_def_interrupts = fwnode_property_read_bool(port, 1578c2ecf20Sopenharmony_ci "mipi-sdw-imp-def-dp0-interrupts-supported"); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci return 0; 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistatic int sdw_slave_read_dpn(struct sdw_slave *slave, 1638c2ecf20Sopenharmony_ci struct sdw_dpn_prop *dpn, int count, int ports, 1648c2ecf20Sopenharmony_ci char *type) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci struct fwnode_handle *node; 1678c2ecf20Sopenharmony_ci u32 bit, i = 0; 1688c2ecf20Sopenharmony_ci int nval; 1698c2ecf20Sopenharmony_ci unsigned long addr; 1708c2ecf20Sopenharmony_ci char name[40]; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci addr = ports; 1738c2ecf20Sopenharmony_ci /* valid ports are 1 to 14 so apply mask */ 1748c2ecf20Sopenharmony_ci addr &= GENMASK(14, 1); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci for_each_set_bit(bit, &addr, 32) { 1778c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), 1788c2ecf20Sopenharmony_ci "mipi-sdw-dp-%d-%s-subproperties", bit, type); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci dpn[i].num = bit; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci node = device_get_named_child_node(&slave->dev, name); 1838c2ecf20Sopenharmony_ci if (!node) { 1848c2ecf20Sopenharmony_ci dev_err(&slave->dev, "%s dpN not found\n", name); 1858c2ecf20Sopenharmony_ci return -EIO; 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci fwnode_property_read_u32(node, "mipi-sdw-port-max-wordlength", 1898c2ecf20Sopenharmony_ci &dpn[i].max_word); 1908c2ecf20Sopenharmony_ci fwnode_property_read_u32(node, "mipi-sdw-port-min-wordlength", 1918c2ecf20Sopenharmony_ci &dpn[i].min_word); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci nval = fwnode_property_count_u32(node, "mipi-sdw-port-wordlength-configs"); 1948c2ecf20Sopenharmony_ci if (nval > 0) { 1958c2ecf20Sopenharmony_ci dpn[i].num_words = nval; 1968c2ecf20Sopenharmony_ci dpn[i].words = devm_kcalloc(&slave->dev, 1978c2ecf20Sopenharmony_ci dpn[i].num_words, 1988c2ecf20Sopenharmony_ci sizeof(*dpn[i].words), 1998c2ecf20Sopenharmony_ci GFP_KERNEL); 2008c2ecf20Sopenharmony_ci if (!dpn[i].words) 2018c2ecf20Sopenharmony_ci return -ENOMEM; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci fwnode_property_read_u32_array(node, 2048c2ecf20Sopenharmony_ci "mipi-sdw-port-wordlength-configs", 2058c2ecf20Sopenharmony_ci dpn[i].words, dpn[i].num_words); 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci fwnode_property_read_u32(node, "mipi-sdw-data-port-type", 2098c2ecf20Sopenharmony_ci &dpn[i].type); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci fwnode_property_read_u32(node, 2128c2ecf20Sopenharmony_ci "mipi-sdw-max-grouping-supported", 2138c2ecf20Sopenharmony_ci &dpn[i].max_grouping); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci dpn[i].simple_ch_prep_sm = fwnode_property_read_bool(node, 2168c2ecf20Sopenharmony_ci "mipi-sdw-simplified-channelprepare-sm"); 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci fwnode_property_read_u32(node, 2198c2ecf20Sopenharmony_ci "mipi-sdw-port-channelprepare-timeout", 2208c2ecf20Sopenharmony_ci &dpn[i].ch_prep_timeout); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci fwnode_property_read_u32(node, 2238c2ecf20Sopenharmony_ci "mipi-sdw-imp-def-dpn-interrupts-supported", 2248c2ecf20Sopenharmony_ci &dpn[i].imp_def_interrupts); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci fwnode_property_read_u32(node, "mipi-sdw-min-channel-number", 2278c2ecf20Sopenharmony_ci &dpn[i].min_ch); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci fwnode_property_read_u32(node, "mipi-sdw-max-channel-number", 2308c2ecf20Sopenharmony_ci &dpn[i].max_ch); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci nval = fwnode_property_count_u32(node, "mipi-sdw-channel-number-list"); 2338c2ecf20Sopenharmony_ci if (nval > 0) { 2348c2ecf20Sopenharmony_ci dpn[i].num_channels = nval; 2358c2ecf20Sopenharmony_ci dpn[i].channels = devm_kcalloc(&slave->dev, 2368c2ecf20Sopenharmony_ci dpn[i].num_channels, 2378c2ecf20Sopenharmony_ci sizeof(*dpn[i].channels), 2388c2ecf20Sopenharmony_ci GFP_KERNEL); 2398c2ecf20Sopenharmony_ci if (!dpn[i].channels) 2408c2ecf20Sopenharmony_ci return -ENOMEM; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci fwnode_property_read_u32_array(node, 2438c2ecf20Sopenharmony_ci "mipi-sdw-channel-number-list", 2448c2ecf20Sopenharmony_ci dpn[i].channels, dpn[i].num_channels); 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci nval = fwnode_property_count_u32(node, "mipi-sdw-channel-combination-list"); 2488c2ecf20Sopenharmony_ci if (nval > 0) { 2498c2ecf20Sopenharmony_ci dpn[i].num_ch_combinations = nval; 2508c2ecf20Sopenharmony_ci dpn[i].ch_combinations = devm_kcalloc(&slave->dev, 2518c2ecf20Sopenharmony_ci dpn[i].num_ch_combinations, 2528c2ecf20Sopenharmony_ci sizeof(*dpn[i].ch_combinations), 2538c2ecf20Sopenharmony_ci GFP_KERNEL); 2548c2ecf20Sopenharmony_ci if (!dpn[i].ch_combinations) 2558c2ecf20Sopenharmony_ci return -ENOMEM; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci fwnode_property_read_u32_array(node, 2588c2ecf20Sopenharmony_ci "mipi-sdw-channel-combination-list", 2598c2ecf20Sopenharmony_ci dpn[i].ch_combinations, 2608c2ecf20Sopenharmony_ci dpn[i].num_ch_combinations); 2618c2ecf20Sopenharmony_ci } 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci fwnode_property_read_u32(node, 2648c2ecf20Sopenharmony_ci "mipi-sdw-modes-supported", &dpn[i].modes); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci fwnode_property_read_u32(node, "mipi-sdw-max-async-buffer", 2678c2ecf20Sopenharmony_ci &dpn[i].max_async_buffer); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci dpn[i].block_pack_mode = fwnode_property_read_bool(node, 2708c2ecf20Sopenharmony_ci "mipi-sdw-block-packing-mode"); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci fwnode_property_read_u32(node, "mipi-sdw-port-encoding-type", 2738c2ecf20Sopenharmony_ci &dpn[i].port_encoding); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci /* TODO: Read audio mode */ 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci i++; 2788c2ecf20Sopenharmony_ci } 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci return 0; 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci/** 2848c2ecf20Sopenharmony_ci * sdw_slave_read_prop() - Read Slave properties 2858c2ecf20Sopenharmony_ci * @slave: SDW Slave 2868c2ecf20Sopenharmony_ci */ 2878c2ecf20Sopenharmony_ciint sdw_slave_read_prop(struct sdw_slave *slave) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci struct sdw_slave_prop *prop = &slave->prop; 2908c2ecf20Sopenharmony_ci struct device *dev = &slave->dev; 2918c2ecf20Sopenharmony_ci struct fwnode_handle *port; 2928c2ecf20Sopenharmony_ci int nval; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci device_property_read_u32(dev, "mipi-sdw-sw-interface-revision", 2958c2ecf20Sopenharmony_ci &prop->mipi_revision); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci prop->wake_capable = device_property_read_bool(dev, 2988c2ecf20Sopenharmony_ci "mipi-sdw-wake-up-unavailable"); 2998c2ecf20Sopenharmony_ci prop->wake_capable = !prop->wake_capable; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci prop->test_mode_capable = device_property_read_bool(dev, 3028c2ecf20Sopenharmony_ci "mipi-sdw-test-mode-supported"); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci prop->clk_stop_mode1 = false; 3058c2ecf20Sopenharmony_ci if (device_property_read_bool(dev, 3068c2ecf20Sopenharmony_ci "mipi-sdw-clock-stop-mode1-supported")) 3078c2ecf20Sopenharmony_ci prop->clk_stop_mode1 = true; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci prop->simple_clk_stop_capable = device_property_read_bool(dev, 3108c2ecf20Sopenharmony_ci "mipi-sdw-simplified-clockstopprepare-sm-supported"); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci device_property_read_u32(dev, "mipi-sdw-clockstopprepare-timeout", 3138c2ecf20Sopenharmony_ci &prop->clk_stop_timeout); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci device_property_read_u32(dev, "mipi-sdw-slave-channelprepare-timeout", 3168c2ecf20Sopenharmony_ci &prop->ch_prep_timeout); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci device_property_read_u32(dev, 3198c2ecf20Sopenharmony_ci "mipi-sdw-clockstopprepare-hard-reset-behavior", 3208c2ecf20Sopenharmony_ci &prop->reset_behave); 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci prop->high_PHY_capable = device_property_read_bool(dev, 3238c2ecf20Sopenharmony_ci "mipi-sdw-highPHY-capable"); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci prop->paging_support = device_property_read_bool(dev, 3268c2ecf20Sopenharmony_ci "mipi-sdw-paging-support"); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci prop->bank_delay_support = device_property_read_bool(dev, 3298c2ecf20Sopenharmony_ci "mipi-sdw-bank-delay-support"); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci device_property_read_u32(dev, 3328c2ecf20Sopenharmony_ci "mipi-sdw-port15-read-behavior", &prop->p15_behave); 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci device_property_read_u32(dev, "mipi-sdw-master-count", 3358c2ecf20Sopenharmony_ci &prop->master_count); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci device_property_read_u32(dev, "mipi-sdw-source-port-list", 3388c2ecf20Sopenharmony_ci &prop->source_ports); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci device_property_read_u32(dev, "mipi-sdw-sink-port-list", 3418c2ecf20Sopenharmony_ci &prop->sink_ports); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci /* Read dp0 properties */ 3448c2ecf20Sopenharmony_ci port = device_get_named_child_node(dev, "mipi-sdw-dp-0-subproperties"); 3458c2ecf20Sopenharmony_ci if (!port) { 3468c2ecf20Sopenharmony_ci dev_dbg(dev, "DP0 node not found!!\n"); 3478c2ecf20Sopenharmony_ci } else { 3488c2ecf20Sopenharmony_ci prop->dp0_prop = devm_kzalloc(&slave->dev, 3498c2ecf20Sopenharmony_ci sizeof(*prop->dp0_prop), 3508c2ecf20Sopenharmony_ci GFP_KERNEL); 3518c2ecf20Sopenharmony_ci if (!prop->dp0_prop) 3528c2ecf20Sopenharmony_ci return -ENOMEM; 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci sdw_slave_read_dp0(slave, port, prop->dp0_prop); 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci /* 3588c2ecf20Sopenharmony_ci * Based on each DPn port, get source and sink dpn properties. 3598c2ecf20Sopenharmony_ci * Also, some ports can operate as both source or sink. 3608c2ecf20Sopenharmony_ci */ 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci /* Allocate memory for set bits in port lists */ 3638c2ecf20Sopenharmony_ci nval = hweight32(prop->source_ports); 3648c2ecf20Sopenharmony_ci prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, 3658c2ecf20Sopenharmony_ci sizeof(*prop->src_dpn_prop), 3668c2ecf20Sopenharmony_ci GFP_KERNEL); 3678c2ecf20Sopenharmony_ci if (!prop->src_dpn_prop) 3688c2ecf20Sopenharmony_ci return -ENOMEM; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci /* Read dpn properties for source port(s) */ 3718c2ecf20Sopenharmony_ci sdw_slave_read_dpn(slave, prop->src_dpn_prop, nval, 3728c2ecf20Sopenharmony_ci prop->source_ports, "source"); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci nval = hweight32(prop->sink_ports); 3758c2ecf20Sopenharmony_ci prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval, 3768c2ecf20Sopenharmony_ci sizeof(*prop->sink_dpn_prop), 3778c2ecf20Sopenharmony_ci GFP_KERNEL); 3788c2ecf20Sopenharmony_ci if (!prop->sink_dpn_prop) 3798c2ecf20Sopenharmony_ci return -ENOMEM; 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci /* Read dpn properties for sink port(s) */ 3828c2ecf20Sopenharmony_ci sdw_slave_read_dpn(slave, prop->sink_dpn_prop, nval, 3838c2ecf20Sopenharmony_ci prop->sink_ports, "sink"); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci return 0; 3868c2ecf20Sopenharmony_ci} 3878c2ecf20Sopenharmony_ciEXPORT_SYMBOL(sdw_slave_read_prop); 388