mipi_disco.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
  2. // Copyright(c) 2015-17 Intel Corporation.
  3. /*
  4. * MIPI Discovery And Configuration (DisCo) Specification for SoundWire
  5. * specifies properties to be implemented for SoundWire Masters and Slaves.
  6. * The DisCo spec doesn't mandate these properties. However, SDW bus cannot
  7. * work without knowing these values.
  8. *
  9. * The helper functions read the Master and Slave properties. Implementers
  10. * of Master or Slave drivers can use any of the below three mechanisms:
  11. * a) Use these APIs here as .read_prop() callback for Master and Slave
  12. * b) Implement own methods and set those as .read_prop(), but invoke
  13. * APIs in this file for generic read and override the values with
  14. * platform specific data
  15. * c) Implement ones own methods which do not use anything provided
  16. * here
  17. */
  18. #include <linux/device.h>
  19. #include <linux/property.h>
  20. #include <linux/mod_devicetable.h>
  21. #include <linux/soundwire/sdw.h>
  22. #include "bus.h"
  23. static bool mipi_fwnode_property_read_bool(const struct fwnode_handle *fwnode,
  24. const char *propname)
  25. {
  26. int ret;
  27. u8 val;
  28. if (!fwnode_property_present(fwnode, propname))
  29. return false;
  30. ret = fwnode_property_read_u8_array(fwnode, propname, &val, 1);
  31. if (ret < 0)
  32. return false;
  33. return !!val;
  34. }
  35. static bool mipi_device_property_read_bool(const struct device *dev,
  36. const char *propname)
  37. {
  38. return mipi_fwnode_property_read_bool(dev_fwnode(dev), propname);
  39. }
  40. /**
  41. * sdw_master_read_prop() - Read Master properties
  42. * @bus: SDW bus instance
  43. */
  44. int sdw_master_read_prop(struct sdw_bus *bus)
  45. {
  46. struct sdw_master_prop *prop = &bus->prop;
  47. struct fwnode_handle *link;
  48. const char *scales_prop;
  49. char name[32];
  50. int nval;
  51. int ret;
  52. int i;
  53. device_property_read_u32(bus->dev,
  54. "mipi-sdw-sw-interface-revision",
  55. &prop->revision);
  56. /* Find master handle */
  57. snprintf(name, sizeof(name),
  58. "mipi-sdw-link-%d-subproperties", bus->link_id);
  59. link = device_get_named_child_node(bus->dev, name);
  60. if (!link) {
  61. dev_err(bus->dev, "Master node %s not found\n", name);
  62. return -EIO;
  63. }
  64. if (mipi_fwnode_property_read_bool(link,
  65. "mipi-sdw-clock-stop-mode0-supported"))
  66. prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE0);
  67. if (mipi_fwnode_property_read_bool(link,
  68. "mipi-sdw-clock-stop-mode1-supported"))
  69. prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE1);
  70. fwnode_property_read_u32(link,
  71. "mipi-sdw-max-clock-frequency",
  72. &prop->max_clk_freq);
  73. nval = fwnode_property_count_u32(link, "mipi-sdw-clock-frequencies-supported");
  74. if (nval > 0) {
  75. prop->num_clk_freq = nval;
  76. prop->clk_freq = devm_kcalloc(bus->dev, prop->num_clk_freq,
  77. sizeof(*prop->clk_freq),
  78. GFP_KERNEL);
  79. if (!prop->clk_freq) {
  80. fwnode_handle_put(link);
  81. return -ENOMEM;
  82. }
  83. ret = fwnode_property_read_u32_array(link,
  84. "mipi-sdw-clock-frequencies-supported",
  85. prop->clk_freq, prop->num_clk_freq);
  86. if (ret < 0)
  87. return ret;
  88. }
  89. /*
  90. * Check the frequencies supported. If FW doesn't provide max
  91. * freq, then populate here by checking values.
  92. */
  93. if (!prop->max_clk_freq && prop->clk_freq) {
  94. prop->max_clk_freq = prop->clk_freq[0];
  95. for (i = 1; i < prop->num_clk_freq; i++) {
  96. if (prop->clk_freq[i] > prop->max_clk_freq)
  97. prop->max_clk_freq = prop->clk_freq[i];
  98. }
  99. }
  100. scales_prop = "mipi-sdw-supported-clock-scales";
  101. nval = fwnode_property_count_u32(link, scales_prop);
  102. if (nval == 0) {
  103. scales_prop = "mipi-sdw-supported-clock-gears";
  104. nval = fwnode_property_count_u32(link, scales_prop);
  105. }
  106. if (nval > 0) {
  107. prop->num_clk_gears = nval;
  108. prop->clk_gears = devm_kcalloc(bus->dev, prop->num_clk_gears,
  109. sizeof(*prop->clk_gears),
  110. GFP_KERNEL);
  111. if (!prop->clk_gears) {
  112. fwnode_handle_put(link);
  113. return -ENOMEM;
  114. }
  115. ret = fwnode_property_read_u32_array(link,
  116. scales_prop,
  117. prop->clk_gears,
  118. prop->num_clk_gears);
  119. if (ret < 0)
  120. return ret;
  121. }
  122. fwnode_property_read_u32(link, "mipi-sdw-default-frame-rate",
  123. &prop->default_frame_rate);
  124. fwnode_property_read_u32(link, "mipi-sdw-default-frame-row-size",
  125. &prop->default_row);
  126. fwnode_property_read_u32(link, "mipi-sdw-default-frame-col-size",
  127. &prop->default_col);
  128. prop->dynamic_frame = mipi_fwnode_property_read_bool(link,
  129. "mipi-sdw-dynamic-frame-shape");
  130. fwnode_property_read_u32(link, "mipi-sdw-command-error-threshold",
  131. &prop->err_threshold);
  132. fwnode_handle_put(link);
  133. return 0;
  134. }
  135. EXPORT_SYMBOL(sdw_master_read_prop);
  136. static int sdw_slave_read_dp0(struct sdw_slave *slave,
  137. struct fwnode_handle *port,
  138. struct sdw_dp0_prop *dp0)
  139. {
  140. int nval;
  141. int ret;
  142. fwnode_property_read_u32(port, "mipi-sdw-port-max-wordlength",
  143. &dp0->max_word);
  144. fwnode_property_read_u32(port, "mipi-sdw-port-min-wordlength",
  145. &dp0->min_word);
  146. nval = fwnode_property_count_u32(port, "mipi-sdw-port-wordlength-configs");
  147. if (nval > 0) {
  148. dp0->num_words = nval;
  149. dp0->words = devm_kcalloc(&slave->dev,
  150. dp0->num_words, sizeof(*dp0->words),
  151. GFP_KERNEL);
  152. if (!dp0->words)
  153. return -ENOMEM;
  154. ret = fwnode_property_read_u32_array(port,
  155. "mipi-sdw-port-wordlength-configs",
  156. dp0->words, dp0->num_words);
  157. if (ret < 0)
  158. return ret;
  159. }
  160. dp0->BRA_flow_controlled = mipi_fwnode_property_read_bool(port,
  161. "mipi-sdw-bra-flow-controlled");
  162. dp0->simple_ch_prep_sm = mipi_fwnode_property_read_bool(port,
  163. "mipi-sdw-simplified-channel-prepare-sm");
  164. dp0->imp_def_interrupts = mipi_fwnode_property_read_bool(port,
  165. "mipi-sdw-imp-def-dp0-interrupts-supported");
  166. nval = fwnode_property_count_u32(port, "mipi-sdw-lane-list");
  167. if (nval > 0) {
  168. dp0->num_lanes = nval;
  169. dp0->lane_list = devm_kcalloc(&slave->dev,
  170. dp0->num_lanes, sizeof(*dp0->lane_list),
  171. GFP_KERNEL);
  172. if (!dp0->lane_list)
  173. return -ENOMEM;
  174. ret = fwnode_property_read_u32_array(port,
  175. "mipi-sdw-lane-list",
  176. dp0->lane_list, dp0->num_lanes);
  177. if (ret < 0)
  178. return ret;
  179. }
  180. return 0;
  181. }
  182. static int sdw_slave_read_dpn(struct sdw_slave *slave,
  183. struct sdw_dpn_prop *dpn, int count, int ports,
  184. char *type)
  185. {
  186. struct fwnode_handle *node;
  187. u32 bit, i = 0;
  188. unsigned long addr;
  189. char name[40];
  190. int nval;
  191. int ret;
  192. addr = ports;
  193. /* valid ports are 1 to 14 so apply mask */
  194. addr &= GENMASK(14, 1);
  195. for_each_set_bit(bit, &addr, 32) {
  196. snprintf(name, sizeof(name),
  197. "mipi-sdw-dp-%d-%s-subproperties", bit, type);
  198. dpn[i].num = bit;
  199. node = device_get_named_child_node(&slave->dev, name);
  200. if (!node) {
  201. dev_err(&slave->dev, "%s dpN not found\n", name);
  202. return -EIO;
  203. }
  204. fwnode_property_read_u32(node, "mipi-sdw-port-max-wordlength",
  205. &dpn[i].max_word);
  206. fwnode_property_read_u32(node, "mipi-sdw-port-min-wordlength",
  207. &dpn[i].min_word);
  208. nval = fwnode_property_count_u32(node, "mipi-sdw-port-wordlength-configs");
  209. if (nval > 0) {
  210. dpn[i].num_words = nval;
  211. dpn[i].words = devm_kcalloc(&slave->dev,
  212. dpn[i].num_words,
  213. sizeof(*dpn[i].words),
  214. GFP_KERNEL);
  215. if (!dpn[i].words) {
  216. fwnode_handle_put(node);
  217. return -ENOMEM;
  218. }
  219. ret = fwnode_property_read_u32_array(node,
  220. "mipi-sdw-port-wordlength-configs",
  221. dpn[i].words, dpn[i].num_words);
  222. if (ret < 0)
  223. return ret;
  224. }
  225. fwnode_property_read_u32(node, "mipi-sdw-data-port-type",
  226. &dpn[i].type);
  227. fwnode_property_read_u32(node,
  228. "mipi-sdw-max-grouping-supported",
  229. &dpn[i].max_grouping);
  230. dpn[i].simple_ch_prep_sm = mipi_fwnode_property_read_bool(node,
  231. "mipi-sdw-simplified-channelprepare-sm");
  232. fwnode_property_read_u32(node,
  233. "mipi-sdw-port-channelprepare-timeout",
  234. &dpn[i].ch_prep_timeout);
  235. fwnode_property_read_u32(node,
  236. "mipi-sdw-imp-def-dpn-interrupts-supported",
  237. &dpn[i].imp_def_interrupts);
  238. fwnode_property_read_u32(node, "mipi-sdw-min-channel-number",
  239. &dpn[i].min_ch);
  240. fwnode_property_read_u32(node, "mipi-sdw-max-channel-number",
  241. &dpn[i].max_ch);
  242. nval = fwnode_property_count_u32(node, "mipi-sdw-channel-number-list");
  243. if (nval > 0) {
  244. dpn[i].num_channels = nval;
  245. dpn[i].channels = devm_kcalloc(&slave->dev,
  246. dpn[i].num_channels,
  247. sizeof(*dpn[i].channels),
  248. GFP_KERNEL);
  249. if (!dpn[i].channels) {
  250. fwnode_handle_put(node);
  251. return -ENOMEM;
  252. }
  253. ret = fwnode_property_read_u32_array(node,
  254. "mipi-sdw-channel-number-list",
  255. dpn[i].channels, dpn[i].num_channels);
  256. if (ret < 0)
  257. return ret;
  258. }
  259. nval = fwnode_property_count_u32(node, "mipi-sdw-channel-combination-list");
  260. if (nval > 0) {
  261. dpn[i].num_ch_combinations = nval;
  262. dpn[i].ch_combinations = devm_kcalloc(&slave->dev,
  263. dpn[i].num_ch_combinations,
  264. sizeof(*dpn[i].ch_combinations),
  265. GFP_KERNEL);
  266. if (!dpn[i].ch_combinations) {
  267. fwnode_handle_put(node);
  268. return -ENOMEM;
  269. }
  270. ret = fwnode_property_read_u32_array(node,
  271. "mipi-sdw-channel-combination-list",
  272. dpn[i].ch_combinations,
  273. dpn[i].num_ch_combinations);
  274. if (ret < 0)
  275. return ret;
  276. }
  277. fwnode_property_read_u32(node,
  278. "mipi-sdw-modes-supported", &dpn[i].modes);
  279. fwnode_property_read_u32(node, "mipi-sdw-max-async-buffer",
  280. &dpn[i].max_async_buffer);
  281. dpn[i].block_pack_mode = mipi_fwnode_property_read_bool(node,
  282. "mipi-sdw-block-packing-mode");
  283. fwnode_property_read_u32(node, "mipi-sdw-port-encoding-type",
  284. &dpn[i].port_encoding);
  285. nval = fwnode_property_count_u32(node, "mipi-sdw-lane-list");
  286. if (nval > 0) {
  287. dpn[i].num_lanes = nval;
  288. dpn[i].lane_list = devm_kcalloc(&slave->dev,
  289. dpn[i].num_lanes, sizeof(*dpn[i].lane_list),
  290. GFP_KERNEL);
  291. if (!dpn[i].lane_list)
  292. return -ENOMEM;
  293. ret = fwnode_property_read_u32_array(node,
  294. "mipi-sdw-lane-list",
  295. dpn[i].lane_list, dpn[i].num_lanes);
  296. if (ret < 0)
  297. return ret;
  298. }
  299. fwnode_handle_put(node);
  300. i++;
  301. }
  302. return 0;
  303. }
  304. /*
  305. * In MIPI DisCo spec for SoundWire, lane mapping for a slave device is done with
  306. * mipi-sdw-lane-x-mapping properties, where x is 1..7, and the values for those
  307. * properties are mipi-sdw-manager-lane-x or mipi-sdw-peripheral-link-y, where x
  308. * is an integer between 1 to 7 if the lane is connected to a manager lane, y is a
  309. * character between A to E if the lane is connected to another peripheral lane.
  310. */
  311. int sdw_slave_read_lane_mapping(struct sdw_slave *slave)
  312. {
  313. struct sdw_slave_prop *prop = &slave->prop;
  314. struct device *dev = &slave->dev;
  315. char prop_name[30];
  316. const char *prop_val;
  317. size_t len;
  318. int ret, i;
  319. u8 lane;
  320. for (i = 0; i < SDW_MAX_LANES; i++) {
  321. snprintf(prop_name, sizeof(prop_name), "mipi-sdw-lane-%d-mapping", i);
  322. ret = device_property_read_string(dev, prop_name, &prop_val);
  323. if (ret)
  324. continue;
  325. len = strlen(prop_val);
  326. if (len < 1)
  327. return -EINVAL;
  328. /* The last character is enough to identify the connection */
  329. ret = kstrtou8(&prop_val[len - 1], 10, &lane);
  330. if (ret)
  331. return ret;
  332. if (in_range(lane, 1, SDW_MAX_LANES - 1))
  333. prop->lane_maps[i] = lane;
  334. }
  335. return 0;
  336. }
  337. EXPORT_SYMBOL(sdw_slave_read_lane_mapping);
  338. /**
  339. * sdw_slave_read_prop() - Read Slave properties
  340. * @slave: SDW Slave
  341. */
  342. int sdw_slave_read_prop(struct sdw_slave *slave)
  343. {
  344. struct sdw_slave_prop *prop = &slave->prop;
  345. struct device *dev = &slave->dev;
  346. struct fwnode_handle *port;
  347. int nval;
  348. int ret;
  349. device_property_read_u32(dev, "mipi-sdw-sw-interface-revision",
  350. &prop->mipi_revision);
  351. prop->wake_capable = mipi_device_property_read_bool(dev,
  352. "mipi-sdw-wake-up-unavailable");
  353. prop->wake_capable = !prop->wake_capable;
  354. prop->test_mode_capable = mipi_device_property_read_bool(dev,
  355. "mipi-sdw-test-mode-supported");
  356. prop->clk_stop_mode1 = false;
  357. if (mipi_device_property_read_bool(dev,
  358. "mipi-sdw-clock-stop-mode1-supported"))
  359. prop->clk_stop_mode1 = true;
  360. prop->simple_clk_stop_capable = mipi_device_property_read_bool(dev,
  361. "mipi-sdw-simplified-clockstopprepare-sm-supported");
  362. device_property_read_u32(dev, "mipi-sdw-clockstopprepare-timeout",
  363. &prop->clk_stop_timeout);
  364. ret = device_property_read_u32(dev, "mipi-sdw-peripheral-channelprepare-timeout",
  365. &prop->ch_prep_timeout);
  366. if (ret < 0)
  367. device_property_read_u32(dev, "mipi-sdw-slave-channelprepare-timeout",
  368. &prop->ch_prep_timeout);
  369. device_property_read_u32(dev,
  370. "mipi-sdw-clockstopprepare-hard-reset-behavior",
  371. &prop->reset_behave);
  372. prop->high_PHY_capable = mipi_device_property_read_bool(dev,
  373. "mipi-sdw-highPHY-capable");
  374. prop->paging_support = mipi_device_property_read_bool(dev,
  375. "mipi-sdw-paging-supported");
  376. prop->bank_delay_support = mipi_device_property_read_bool(dev,
  377. "mipi-sdw-bank-delay-supported");
  378. device_property_read_u32(dev,
  379. "mipi-sdw-port15-read-behavior", &prop->p15_behave);
  380. device_property_read_u32(dev, "mipi-sdw-master-count",
  381. &prop->master_count);
  382. device_property_read_u32(dev, "mipi-sdw-source-port-list",
  383. &prop->source_ports);
  384. device_property_read_u32(dev, "mipi-sdw-sink-port-list",
  385. &prop->sink_ports);
  386. device_property_read_u32(dev, "mipi-sdw-sdca-interrupt-register-list",
  387. &prop->sdca_interrupt_register_list);
  388. prop->commit_register_supported = mipi_device_property_read_bool(dev,
  389. "mipi-sdw-commit-register-supported");
  390. /*
  391. * Read dp0 properties - we don't rely on the 'mipi-sdw-dp-0-supported'
  392. * property since the 'mipi-sdw-dp0-subproperties' property is logically
  393. * equivalent.
  394. */
  395. port = device_get_named_child_node(dev, "mipi-sdw-dp-0-subproperties");
  396. if (!port) {
  397. dev_dbg(dev, "DP0 node not found!!\n");
  398. } else {
  399. prop->dp0_prop = devm_kzalloc(&slave->dev,
  400. sizeof(*prop->dp0_prop),
  401. GFP_KERNEL);
  402. if (!prop->dp0_prop) {
  403. fwnode_handle_put(port);
  404. return -ENOMEM;
  405. }
  406. sdw_slave_read_dp0(slave, port, prop->dp0_prop);
  407. fwnode_handle_put(port);
  408. }
  409. /*
  410. * Based on each DPn port, get source and sink dpn properties.
  411. * Also, some ports can operate as both source or sink.
  412. */
  413. /* Allocate memory for set bits in port lists */
  414. nval = hweight32(prop->source_ports);
  415. prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval,
  416. sizeof(*prop->src_dpn_prop),
  417. GFP_KERNEL);
  418. if (!prop->src_dpn_prop)
  419. return -ENOMEM;
  420. /* Read dpn properties for source port(s) */
  421. sdw_slave_read_dpn(slave, prop->src_dpn_prop, nval,
  422. prop->source_ports, "source");
  423. nval = hweight32(prop->sink_ports);
  424. prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval,
  425. sizeof(*prop->sink_dpn_prop),
  426. GFP_KERNEL);
  427. if (!prop->sink_dpn_prop)
  428. return -ENOMEM;
  429. /* Read dpn properties for sink port(s) */
  430. sdw_slave_read_dpn(slave, prop->sink_dpn_prop, nval,
  431. prop->sink_ports, "sink");
  432. return sdw_slave_read_lane_mapping(slave);
  433. }
  434. EXPORT_SYMBOL(sdw_slave_read_prop);