cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mipi_disco.c (10985B)


      1// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
      2// Copyright(c) 2015-17 Intel Corporation.
      3
      4/*
      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.
      9 *
     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
     17 *    here
     18 */
     19
     20#include <linux/device.h>
     21#include <linux/property.h>
     22#include <linux/mod_devicetable.h>
     23#include <linux/soundwire/sdw.h>
     24#include "bus.h"
     25
     26/**
     27 * sdw_master_read_prop() - Read Master properties
     28 * @bus: SDW bus instance
     29 */
     30int sdw_master_read_prop(struct sdw_bus *bus)
     31{
     32	struct sdw_master_prop *prop = &bus->prop;
     33	struct fwnode_handle *link;
     34	char name[32];
     35	int nval, i;
     36
     37	device_property_read_u32(bus->dev,
     38				 "mipi-sdw-sw-interface-revision",
     39				 &prop->revision);
     40
     41	/* Find master handle */
     42	snprintf(name, sizeof(name),
     43		 "mipi-sdw-link-%d-subproperties", bus->link_id);
     44
     45	link = device_get_named_child_node(bus->dev, name);
     46	if (!link) {
     47		dev_err(bus->dev, "Master node %s not found\n", name);
     48		return -EIO;
     49	}
     50
     51	if (fwnode_property_read_bool(link,
     52				      "mipi-sdw-clock-stop-mode0-supported"))
     53		prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE0);
     54
     55	if (fwnode_property_read_bool(link,
     56				      "mipi-sdw-clock-stop-mode1-supported"))
     57		prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE1);
     58
     59	fwnode_property_read_u32(link,
     60				 "mipi-sdw-max-clock-frequency",
     61				 &prop->max_clk_freq);
     62
     63	nval = fwnode_property_count_u32(link, "mipi-sdw-clock-frequencies-supported");
     64	if (nval > 0) {
     65		prop->num_clk_freq = nval;
     66		prop->clk_freq = devm_kcalloc(bus->dev, prop->num_clk_freq,
     67					      sizeof(*prop->clk_freq),
     68					      GFP_KERNEL);
     69		if (!prop->clk_freq)
     70			return -ENOMEM;
     71
     72		fwnode_property_read_u32_array(link,
     73				"mipi-sdw-clock-frequencies-supported",
     74				prop->clk_freq, prop->num_clk_freq);
     75	}
     76
     77	/*
     78	 * Check the frequencies supported. If FW doesn't provide max
     79	 * freq, then populate here by checking values.
     80	 */
     81	if (!prop->max_clk_freq && prop->clk_freq) {
     82		prop->max_clk_freq = prop->clk_freq[0];
     83		for (i = 1; i < prop->num_clk_freq; i++) {
     84			if (prop->clk_freq[i] > prop->max_clk_freq)
     85				prop->max_clk_freq = prop->clk_freq[i];
     86		}
     87	}
     88
     89	nval = fwnode_property_count_u32(link, "mipi-sdw-supported-clock-gears");
     90	if (nval > 0) {
     91		prop->num_clk_gears = nval;
     92		prop->clk_gears = devm_kcalloc(bus->dev, prop->num_clk_gears,
     93					       sizeof(*prop->clk_gears),
     94					       GFP_KERNEL);
     95		if (!prop->clk_gears)
     96			return -ENOMEM;
     97
     98		fwnode_property_read_u32_array(link,
     99					       "mipi-sdw-supported-clock-gears",
    100					       prop->clk_gears,
    101					       prop->num_clk_gears);
    102	}
    103
    104	fwnode_property_read_u32(link, "mipi-sdw-default-frame-rate",
    105				 &prop->default_frame_rate);
    106
    107	fwnode_property_read_u32(link, "mipi-sdw-default-frame-row-size",
    108				 &prop->default_row);
    109
    110	fwnode_property_read_u32(link, "mipi-sdw-default-frame-col-size",
    111				 &prop->default_col);
    112
    113	prop->dynamic_frame =  fwnode_property_read_bool(link,
    114			"mipi-sdw-dynamic-frame-shape");
    115
    116	fwnode_property_read_u32(link, "mipi-sdw-command-error-threshold",
    117				 &prop->err_threshold);
    118
    119	return 0;
    120}
    121EXPORT_SYMBOL(sdw_master_read_prop);
    122
    123static int sdw_slave_read_dp0(struct sdw_slave *slave,
    124			      struct fwnode_handle *port,
    125			      struct sdw_dp0_prop *dp0)
    126{
    127	int nval;
    128
    129	fwnode_property_read_u32(port, "mipi-sdw-port-max-wordlength",
    130				 &dp0->max_word);
    131
    132	fwnode_property_read_u32(port, "mipi-sdw-port-min-wordlength",
    133				 &dp0->min_word);
    134
    135	nval = fwnode_property_count_u32(port, "mipi-sdw-port-wordlength-configs");
    136	if (nval > 0) {
    137
    138		dp0->num_words = nval;
    139		dp0->words = devm_kcalloc(&slave->dev,
    140					  dp0->num_words, sizeof(*dp0->words),
    141					  GFP_KERNEL);
    142		if (!dp0->words)
    143			return -ENOMEM;
    144
    145		fwnode_property_read_u32_array(port,
    146				"mipi-sdw-port-wordlength-configs",
    147				dp0->words, dp0->num_words);
    148	}
    149
    150	dp0->BRA_flow_controlled = fwnode_property_read_bool(port,
    151				"mipi-sdw-bra-flow-controlled");
    152
    153	dp0->simple_ch_prep_sm = fwnode_property_read_bool(port,
    154				"mipi-sdw-simplified-channel-prepare-sm");
    155
    156	dp0->imp_def_interrupts = fwnode_property_read_bool(port,
    157				"mipi-sdw-imp-def-dp0-interrupts-supported");
    158
    159	return 0;
    160}
    161
    162static int sdw_slave_read_dpn(struct sdw_slave *slave,
    163			      struct sdw_dpn_prop *dpn, int count, int ports,
    164			      char *type)
    165{
    166	struct fwnode_handle *node;
    167	u32 bit, i = 0;
    168	int nval;
    169	unsigned long addr;
    170	char name[40];
    171
    172	addr = ports;
    173	/* valid ports are 1 to 14 so apply mask */
    174	addr &= GENMASK(14, 1);
    175
    176	for_each_set_bit(bit, &addr, 32) {
    177		snprintf(name, sizeof(name),
    178			 "mipi-sdw-dp-%d-%s-subproperties", bit, type);
    179
    180		dpn[i].num = bit;
    181
    182		node = device_get_named_child_node(&slave->dev, name);
    183		if (!node) {
    184			dev_err(&slave->dev, "%s dpN not found\n", name);
    185			return -EIO;
    186		}
    187
    188		fwnode_property_read_u32(node, "mipi-sdw-port-max-wordlength",
    189					 &dpn[i].max_word);
    190		fwnode_property_read_u32(node, "mipi-sdw-port-min-wordlength",
    191					 &dpn[i].min_word);
    192
    193		nval = fwnode_property_count_u32(node, "mipi-sdw-port-wordlength-configs");
    194		if (nval > 0) {
    195			dpn[i].num_words = nval;
    196			dpn[i].words = devm_kcalloc(&slave->dev,
    197						    dpn[i].num_words,
    198						    sizeof(*dpn[i].words),
    199						    GFP_KERNEL);
    200			if (!dpn[i].words)
    201				return -ENOMEM;
    202
    203			fwnode_property_read_u32_array(node,
    204					"mipi-sdw-port-wordlength-configs",
    205					dpn[i].words, dpn[i].num_words);
    206		}
    207
    208		fwnode_property_read_u32(node, "mipi-sdw-data-port-type",
    209					 &dpn[i].type);
    210
    211		fwnode_property_read_u32(node,
    212					 "mipi-sdw-max-grouping-supported",
    213					 &dpn[i].max_grouping);
    214
    215		dpn[i].simple_ch_prep_sm = fwnode_property_read_bool(node,
    216				"mipi-sdw-simplified-channelprepare-sm");
    217
    218		fwnode_property_read_u32(node,
    219					 "mipi-sdw-port-channelprepare-timeout",
    220					 &dpn[i].ch_prep_timeout);
    221
    222		fwnode_property_read_u32(node,
    223				"mipi-sdw-imp-def-dpn-interrupts-supported",
    224				&dpn[i].imp_def_interrupts);
    225
    226		fwnode_property_read_u32(node, "mipi-sdw-min-channel-number",
    227					 &dpn[i].min_ch);
    228
    229		fwnode_property_read_u32(node, "mipi-sdw-max-channel-number",
    230					 &dpn[i].max_ch);
    231
    232		nval = fwnode_property_count_u32(node, "mipi-sdw-channel-number-list");
    233		if (nval > 0) {
    234			dpn[i].num_channels = nval;
    235			dpn[i].channels = devm_kcalloc(&slave->dev,
    236						       dpn[i].num_channels,
    237						       sizeof(*dpn[i].channels),
    238						 GFP_KERNEL);
    239			if (!dpn[i].channels)
    240				return -ENOMEM;
    241
    242			fwnode_property_read_u32_array(node,
    243					"mipi-sdw-channel-number-list",
    244					dpn[i].channels, dpn[i].num_channels);
    245		}
    246
    247		nval = fwnode_property_count_u32(node, "mipi-sdw-channel-combination-list");
    248		if (nval > 0) {
    249			dpn[i].num_ch_combinations = nval;
    250			dpn[i].ch_combinations = devm_kcalloc(&slave->dev,
    251					dpn[i].num_ch_combinations,
    252					sizeof(*dpn[i].ch_combinations),
    253					GFP_KERNEL);
    254			if (!dpn[i].ch_combinations)
    255				return -ENOMEM;
    256
    257			fwnode_property_read_u32_array(node,
    258					"mipi-sdw-channel-combination-list",
    259					dpn[i].ch_combinations,
    260					dpn[i].num_ch_combinations);
    261		}
    262
    263		fwnode_property_read_u32(node,
    264				"mipi-sdw-modes-supported", &dpn[i].modes);
    265
    266		fwnode_property_read_u32(node, "mipi-sdw-max-async-buffer",
    267					 &dpn[i].max_async_buffer);
    268
    269		dpn[i].block_pack_mode = fwnode_property_read_bool(node,
    270				"mipi-sdw-block-packing-mode");
    271
    272		fwnode_property_read_u32(node, "mipi-sdw-port-encoding-type",
    273					 &dpn[i].port_encoding);
    274
    275		/* TODO: Read audio mode */
    276
    277		i++;
    278	}
    279
    280	return 0;
    281}
    282
    283/**
    284 * sdw_slave_read_prop() - Read Slave properties
    285 * @slave: SDW Slave
    286 */
    287int sdw_slave_read_prop(struct sdw_slave *slave)
    288{
    289	struct sdw_slave_prop *prop = &slave->prop;
    290	struct device *dev = &slave->dev;
    291	struct fwnode_handle *port;
    292	int nval;
    293
    294	device_property_read_u32(dev, "mipi-sdw-sw-interface-revision",
    295				 &prop->mipi_revision);
    296
    297	prop->wake_capable = device_property_read_bool(dev,
    298				"mipi-sdw-wake-up-unavailable");
    299	prop->wake_capable = !prop->wake_capable;
    300
    301	prop->test_mode_capable = device_property_read_bool(dev,
    302				"mipi-sdw-test-mode-supported");
    303
    304	prop->clk_stop_mode1 = false;
    305	if (device_property_read_bool(dev,
    306				"mipi-sdw-clock-stop-mode1-supported"))
    307		prop->clk_stop_mode1 = true;
    308
    309	prop->simple_clk_stop_capable = device_property_read_bool(dev,
    310			"mipi-sdw-simplified-clockstopprepare-sm-supported");
    311
    312	device_property_read_u32(dev, "mipi-sdw-clockstopprepare-timeout",
    313				 &prop->clk_stop_timeout);
    314
    315	device_property_read_u32(dev, "mipi-sdw-slave-channelprepare-timeout",
    316				 &prop->ch_prep_timeout);
    317
    318	device_property_read_u32(dev,
    319			"mipi-sdw-clockstopprepare-hard-reset-behavior",
    320			&prop->reset_behave);
    321
    322	prop->high_PHY_capable = device_property_read_bool(dev,
    323			"mipi-sdw-highPHY-capable");
    324
    325	prop->paging_support = device_property_read_bool(dev,
    326			"mipi-sdw-paging-support");
    327
    328	prop->bank_delay_support = device_property_read_bool(dev,
    329			"mipi-sdw-bank-delay-support");
    330
    331	device_property_read_u32(dev,
    332			"mipi-sdw-port15-read-behavior", &prop->p15_behave);
    333
    334	device_property_read_u32(dev, "mipi-sdw-master-count",
    335				 &prop->master_count);
    336
    337	device_property_read_u32(dev, "mipi-sdw-source-port-list",
    338				 &prop->source_ports);
    339
    340	device_property_read_u32(dev, "mipi-sdw-sink-port-list",
    341				 &prop->sink_ports);
    342
    343	/* Read dp0 properties */
    344	port = device_get_named_child_node(dev, "mipi-sdw-dp-0-subproperties");
    345	if (!port) {
    346		dev_dbg(dev, "DP0 node not found!!\n");
    347	} else {
    348		prop->dp0_prop = devm_kzalloc(&slave->dev,
    349					      sizeof(*prop->dp0_prop),
    350					      GFP_KERNEL);
    351		if (!prop->dp0_prop)
    352			return -ENOMEM;
    353
    354		sdw_slave_read_dp0(slave, port, prop->dp0_prop);
    355	}
    356
    357	/*
    358	 * Based on each DPn port, get source and sink dpn properties.
    359	 * Also, some ports can operate as both source or sink.
    360	 */
    361
    362	/* Allocate memory for set bits in port lists */
    363	nval = hweight32(prop->source_ports);
    364	prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval,
    365					  sizeof(*prop->src_dpn_prop),
    366					  GFP_KERNEL);
    367	if (!prop->src_dpn_prop)
    368		return -ENOMEM;
    369
    370	/* Read dpn properties for source port(s) */
    371	sdw_slave_read_dpn(slave, prop->src_dpn_prop, nval,
    372			   prop->source_ports, "source");
    373
    374	nval = hweight32(prop->sink_ports);
    375	prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval,
    376					   sizeof(*prop->sink_dpn_prop),
    377					   GFP_KERNEL);
    378	if (!prop->sink_dpn_prop)
    379		return -ENOMEM;
    380
    381	/* Read dpn properties for sink port(s) */
    382	sdw_slave_read_dpn(slave, prop->sink_dpn_prop, nval,
    383			   prop->sink_ports, "sink");
    384
    385	return 0;
    386}
    387EXPORT_SYMBOL(sdw_slave_read_prop);