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

cio2-bridge.c (12721B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Author: Dan Scally <djrscally@gmail.com> */
      3
      4#include <linux/acpi.h>
      5#include <linux/device.h>
      6#include <linux/i2c.h>
      7#include <linux/pci.h>
      8#include <linux/property.h>
      9#include <media/v4l2-fwnode.h>
     10
     11#include "cio2-bridge.h"
     12
     13/*
     14 * Extend this array with ACPI Hardware IDs of devices known to be working
     15 * plus the number of link-frequencies expected by their drivers, along with
     16 * the frequency values in hertz. This is somewhat opportunistic way of adding
     17 * support for this for now in the hopes of a better source for the information
     18 * (possibly some encoded value in the SSDB buffer that we're unaware of)
     19 * becoming apparent in the future.
     20 *
     21 * Do not add an entry for a sensor that is not actually supported.
     22 */
     23static const struct cio2_sensor_config cio2_supported_sensors[] = {
     24	/* Omnivision OV5693 */
     25	CIO2_SENSOR_CONFIG("INT33BE", 1, 419200000),
     26	/* Omnivision OV8865 */
     27	CIO2_SENSOR_CONFIG("INT347A", 1, 360000000),
     28	/* Omnivision OV7251 */
     29	CIO2_SENSOR_CONFIG("INT347E", 1, 319200000),
     30	/* Omnivision OV2680 */
     31	CIO2_SENSOR_CONFIG("OVTI2680", 0),
     32};
     33
     34static const struct cio2_property_names prop_names = {
     35	.clock_frequency = "clock-frequency",
     36	.rotation = "rotation",
     37	.orientation = "orientation",
     38	.bus_type = "bus-type",
     39	.data_lanes = "data-lanes",
     40	.remote_endpoint = "remote-endpoint",
     41	.link_frequencies = "link-frequencies",
     42};
     43
     44static const char * const cio2_vcm_types[] = {
     45	"ad5823",
     46	"dw9714",
     47	"ad5816",
     48	"dw9719",
     49	"dw9718",
     50	"dw9806b",
     51	"wv517s",
     52	"lc898122xa",
     53	"lc898212axb",
     54};
     55
     56static int cio2_bridge_read_acpi_buffer(struct acpi_device *adev, char *id,
     57					void *data, u32 size)
     58{
     59	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
     60	union acpi_object *obj;
     61	acpi_status status;
     62	int ret = 0;
     63
     64	status = acpi_evaluate_object(adev->handle, id, NULL, &buffer);
     65	if (ACPI_FAILURE(status))
     66		return -ENODEV;
     67
     68	obj = buffer.pointer;
     69	if (!obj) {
     70		dev_err(&adev->dev, "Couldn't locate ACPI buffer\n");
     71		return -ENODEV;
     72	}
     73
     74	if (obj->type != ACPI_TYPE_BUFFER) {
     75		dev_err(&adev->dev, "Not an ACPI buffer\n");
     76		ret = -ENODEV;
     77		goto out_free_buff;
     78	}
     79
     80	if (obj->buffer.length > size) {
     81		dev_err(&adev->dev, "Given buffer is too small\n");
     82		ret = -EINVAL;
     83		goto out_free_buff;
     84	}
     85
     86	memcpy(data, obj->buffer.pointer, obj->buffer.length);
     87
     88out_free_buff:
     89	kfree(buffer.pointer);
     90	return ret;
     91}
     92
     93static u32 cio2_bridge_parse_rotation(struct cio2_sensor *sensor)
     94{
     95	switch (sensor->ssdb.degree) {
     96	case CIO2_SENSOR_ROTATION_NORMAL:
     97		return 0;
     98	case CIO2_SENSOR_ROTATION_INVERTED:
     99		return 180;
    100	default:
    101		dev_warn(&sensor->adev->dev,
    102			 "Unknown rotation %d. Assume 0 degree rotation\n",
    103			 sensor->ssdb.degree);
    104		return 0;
    105	}
    106}
    107
    108static enum v4l2_fwnode_orientation cio2_bridge_parse_orientation(struct cio2_sensor *sensor)
    109{
    110	switch (sensor->pld->panel) {
    111	case ACPI_PLD_PANEL_FRONT:
    112		return V4L2_FWNODE_ORIENTATION_FRONT;
    113	case ACPI_PLD_PANEL_BACK:
    114		return V4L2_FWNODE_ORIENTATION_BACK;
    115	case ACPI_PLD_PANEL_TOP:
    116	case ACPI_PLD_PANEL_LEFT:
    117	case ACPI_PLD_PANEL_RIGHT:
    118	case ACPI_PLD_PANEL_UNKNOWN:
    119		return V4L2_FWNODE_ORIENTATION_EXTERNAL;
    120	default:
    121		dev_warn(&sensor->adev->dev, "Unknown _PLD panel value %d\n",
    122			 sensor->pld->panel);
    123		return V4L2_FWNODE_ORIENTATION_EXTERNAL;
    124	}
    125}
    126
    127static void cio2_bridge_create_fwnode_properties(
    128	struct cio2_sensor *sensor,
    129	struct cio2_bridge *bridge,
    130	const struct cio2_sensor_config *cfg)
    131{
    132	u32 rotation;
    133	enum v4l2_fwnode_orientation orientation;
    134
    135	rotation = cio2_bridge_parse_rotation(sensor);
    136	orientation = cio2_bridge_parse_orientation(sensor);
    137
    138	sensor->prop_names = prop_names;
    139
    140	sensor->local_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_CIO2_ENDPOINT]);
    141	sensor->remote_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_SENSOR_ENDPOINT]);
    142
    143	sensor->dev_properties[0] = PROPERTY_ENTRY_U32(
    144					sensor->prop_names.clock_frequency,
    145					sensor->ssdb.mclkspeed);
    146	sensor->dev_properties[1] = PROPERTY_ENTRY_U32(
    147					sensor->prop_names.rotation,
    148					rotation);
    149	sensor->dev_properties[2] = PROPERTY_ENTRY_U32(
    150					sensor->prop_names.orientation,
    151					orientation);
    152	if (sensor->ssdb.vcmtype) {
    153		sensor->vcm_ref[0] =
    154			SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_VCM]);
    155		sensor->dev_properties[3] =
    156			PROPERTY_ENTRY_REF_ARRAY("lens-focus", sensor->vcm_ref);
    157	}
    158
    159	sensor->ep_properties[0] = PROPERTY_ENTRY_U32(
    160					sensor->prop_names.bus_type,
    161					V4L2_FWNODE_BUS_TYPE_CSI2_DPHY);
    162	sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN(
    163					sensor->prop_names.data_lanes,
    164					bridge->data_lanes,
    165					sensor->ssdb.lanes);
    166	sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY(
    167					sensor->prop_names.remote_endpoint,
    168					sensor->local_ref);
    169
    170	if (cfg->nr_link_freqs > 0)
    171		sensor->ep_properties[3] = PROPERTY_ENTRY_U64_ARRAY_LEN(
    172			sensor->prop_names.link_frequencies,
    173			cfg->link_freqs,
    174			cfg->nr_link_freqs);
    175
    176	sensor->cio2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN(
    177					sensor->prop_names.data_lanes,
    178					bridge->data_lanes,
    179					sensor->ssdb.lanes);
    180	sensor->cio2_properties[1] = PROPERTY_ENTRY_REF_ARRAY(
    181					sensor->prop_names.remote_endpoint,
    182					sensor->remote_ref);
    183}
    184
    185static void cio2_bridge_init_swnode_names(struct cio2_sensor *sensor)
    186{
    187	snprintf(sensor->node_names.remote_port,
    188		 sizeof(sensor->node_names.remote_port),
    189		 SWNODE_GRAPH_PORT_NAME_FMT, sensor->ssdb.link);
    190	snprintf(sensor->node_names.port,
    191		 sizeof(sensor->node_names.port),
    192		 SWNODE_GRAPH_PORT_NAME_FMT, 0); /* Always port 0 */
    193	snprintf(sensor->node_names.endpoint,
    194		 sizeof(sensor->node_names.endpoint),
    195		 SWNODE_GRAPH_ENDPOINT_NAME_FMT, 0); /* And endpoint 0 */
    196}
    197
    198static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge,
    199						  struct cio2_sensor *sensor)
    200{
    201	struct software_node *nodes = sensor->swnodes;
    202
    203	cio2_bridge_init_swnode_names(sensor);
    204
    205	nodes[SWNODE_SENSOR_HID] = NODE_SENSOR(sensor->name,
    206					       sensor->dev_properties);
    207	nodes[SWNODE_SENSOR_PORT] = NODE_PORT(sensor->node_names.port,
    208					      &nodes[SWNODE_SENSOR_HID]);
    209	nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT(
    210						sensor->node_names.endpoint,
    211						&nodes[SWNODE_SENSOR_PORT],
    212						sensor->ep_properties);
    213	nodes[SWNODE_CIO2_PORT] = NODE_PORT(sensor->node_names.remote_port,
    214					    &bridge->cio2_hid_node);
    215	nodes[SWNODE_CIO2_ENDPOINT] = NODE_ENDPOINT(
    216						sensor->node_names.endpoint,
    217						&nodes[SWNODE_CIO2_PORT],
    218						sensor->cio2_properties);
    219	if (sensor->ssdb.vcmtype)
    220		nodes[SWNODE_VCM] =
    221			NODE_VCM(cio2_vcm_types[sensor->ssdb.vcmtype - 1]);
    222}
    223
    224static void cio2_bridge_instantiate_vcm_i2c_client(struct cio2_sensor *sensor)
    225{
    226	struct i2c_board_info board_info = { };
    227	char name[16];
    228
    229	if (!sensor->ssdb.vcmtype)
    230		return;
    231
    232	snprintf(name, sizeof(name), "%s-VCM", acpi_dev_name(sensor->adev));
    233	board_info.dev_name = name;
    234	strscpy(board_info.type, cio2_vcm_types[sensor->ssdb.vcmtype - 1],
    235		ARRAY_SIZE(board_info.type));
    236	board_info.swnode = &sensor->swnodes[SWNODE_VCM];
    237
    238	sensor->vcm_i2c_client =
    239		i2c_acpi_new_device_by_fwnode(acpi_fwnode_handle(sensor->adev),
    240					      1, &board_info);
    241	if (IS_ERR(sensor->vcm_i2c_client)) {
    242		dev_warn(&sensor->adev->dev, "Error instantiation VCM i2c-client: %ld\n",
    243			 PTR_ERR(sensor->vcm_i2c_client));
    244		sensor->vcm_i2c_client = NULL;
    245	}
    246}
    247
    248static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge)
    249{
    250	struct cio2_sensor *sensor;
    251	unsigned int i;
    252
    253	for (i = 0; i < bridge->n_sensors; i++) {
    254		sensor = &bridge->sensors[i];
    255		software_node_unregister_nodes(sensor->swnodes);
    256		ACPI_FREE(sensor->pld);
    257		acpi_dev_put(sensor->adev);
    258		i2c_unregister_device(sensor->vcm_i2c_client);
    259	}
    260}
    261
    262static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
    263				      struct cio2_bridge *bridge,
    264				      struct pci_dev *cio2)
    265{
    266	struct fwnode_handle *fwnode;
    267	struct cio2_sensor *sensor;
    268	struct acpi_device *adev;
    269	acpi_status status;
    270	int ret;
    271
    272	for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) {
    273		if (!adev->status.enabled)
    274			continue;
    275
    276		if (bridge->n_sensors >= CIO2_NUM_PORTS) {
    277			acpi_dev_put(adev);
    278			dev_err(&cio2->dev, "Exceeded available CIO2 ports\n");
    279			return -EINVAL;
    280		}
    281
    282		sensor = &bridge->sensors[bridge->n_sensors];
    283		strscpy(sensor->name, cfg->hid, sizeof(sensor->name));
    284
    285		ret = cio2_bridge_read_acpi_buffer(adev, "SSDB",
    286						   &sensor->ssdb,
    287						   sizeof(sensor->ssdb));
    288		if (ret)
    289			goto err_put_adev;
    290
    291		if (sensor->ssdb.vcmtype > ARRAY_SIZE(cio2_vcm_types)) {
    292			dev_warn(&adev->dev, "Unknown VCM type %d\n",
    293				 sensor->ssdb.vcmtype);
    294			sensor->ssdb.vcmtype = 0;
    295		}
    296
    297		status = acpi_get_physical_device_location(adev->handle, &sensor->pld);
    298		if (ACPI_FAILURE(status)) {
    299			ret = -ENODEV;
    300			goto err_put_adev;
    301		}
    302
    303		if (sensor->ssdb.lanes > CIO2_MAX_LANES) {
    304			dev_err(&adev->dev,
    305				"Number of lanes in SSDB is invalid\n");
    306			ret = -EINVAL;
    307			goto err_free_pld;
    308		}
    309
    310		cio2_bridge_create_fwnode_properties(sensor, bridge, cfg);
    311		cio2_bridge_create_connection_swnodes(bridge, sensor);
    312
    313		ret = software_node_register_nodes(sensor->swnodes);
    314		if (ret)
    315			goto err_free_pld;
    316
    317		fwnode = software_node_fwnode(&sensor->swnodes[
    318						      SWNODE_SENSOR_HID]);
    319		if (!fwnode) {
    320			ret = -ENODEV;
    321			goto err_free_swnodes;
    322		}
    323
    324		sensor->adev = acpi_dev_get(adev);
    325		adev->fwnode.secondary = fwnode;
    326
    327		cio2_bridge_instantiate_vcm_i2c_client(sensor);
    328
    329		dev_info(&cio2->dev, "Found supported sensor %s\n",
    330			 acpi_dev_name(adev));
    331
    332		bridge->n_sensors++;
    333	}
    334
    335	return 0;
    336
    337err_free_swnodes:
    338	software_node_unregister_nodes(sensor->swnodes);
    339err_free_pld:
    340	ACPI_FREE(sensor->pld);
    341err_put_adev:
    342	acpi_dev_put(adev);
    343	return ret;
    344}
    345
    346static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge,
    347				       struct pci_dev *cio2)
    348{
    349	unsigned int i;
    350	int ret;
    351
    352	for (i = 0; i < ARRAY_SIZE(cio2_supported_sensors); i++) {
    353		const struct cio2_sensor_config *cfg =
    354			&cio2_supported_sensors[i];
    355
    356		ret = cio2_bridge_connect_sensor(cfg, bridge, cio2);
    357		if (ret)
    358			goto err_unregister_sensors;
    359	}
    360
    361	return 0;
    362
    363err_unregister_sensors:
    364	cio2_bridge_unregister_sensors(bridge);
    365	return ret;
    366}
    367
    368/*
    369 * The VCM cannot be probed until the PMIC is completely setup. We cannot rely
    370 * on -EPROBE_DEFER for this, since the consumer<->supplier relations between
    371 * the VCM and regulators/clks are not described in ACPI, instead they are
    372 * passed as board-data to the PMIC drivers. Since -PROBE_DEFER does not work
    373 * for the clks/regulators the VCM i2c-clients must not be instantiated until
    374 * the PMIC is fully setup.
    375 *
    376 * The sensor/VCM ACPI device has an ACPI _DEP on the PMIC, check this using the
    377 * acpi_dev_ready_for_enumeration() helper, like the i2c-core-acpi code does
    378 * for the sensors.
    379 */
    380static int cio2_bridge_sensors_are_ready(void)
    381{
    382	struct acpi_device *adev;
    383	bool ready = true;
    384	unsigned int i;
    385
    386	for (i = 0; i < ARRAY_SIZE(cio2_supported_sensors); i++) {
    387		const struct cio2_sensor_config *cfg =
    388			&cio2_supported_sensors[i];
    389
    390		for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) {
    391			if (!adev->status.enabled)
    392				continue;
    393
    394			if (!acpi_dev_ready_for_enumeration(adev))
    395				ready = false;
    396		}
    397	}
    398
    399	return ready;
    400}
    401
    402int cio2_bridge_init(struct pci_dev *cio2)
    403{
    404	struct device *dev = &cio2->dev;
    405	struct fwnode_handle *fwnode;
    406	struct cio2_bridge *bridge;
    407	unsigned int i;
    408	int ret;
    409
    410	if (!cio2_bridge_sensors_are_ready())
    411		return -EPROBE_DEFER;
    412
    413	bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
    414	if (!bridge)
    415		return -ENOMEM;
    416
    417	strscpy(bridge->cio2_node_name, CIO2_HID,
    418		sizeof(bridge->cio2_node_name));
    419	bridge->cio2_hid_node.name = bridge->cio2_node_name;
    420
    421	ret = software_node_register(&bridge->cio2_hid_node);
    422	if (ret < 0) {
    423		dev_err(dev, "Failed to register the CIO2 HID node\n");
    424		goto err_free_bridge;
    425	}
    426
    427	/*
    428	 * Map the lane arrangement, which is fixed for the IPU3 (meaning we
    429	 * only need one, rather than one per sensor). We include it as a
    430	 * member of the struct cio2_bridge rather than a global variable so
    431	 * that it survives if the module is unloaded along with the rest of
    432	 * the struct.
    433	 */
    434	for (i = 0; i < CIO2_MAX_LANES; i++)
    435		bridge->data_lanes[i] = i + 1;
    436
    437	ret = cio2_bridge_connect_sensors(bridge, cio2);
    438	if (ret || bridge->n_sensors == 0)
    439		goto err_unregister_cio2;
    440
    441	dev_info(dev, "Connected %d cameras\n", bridge->n_sensors);
    442
    443	fwnode = software_node_fwnode(&bridge->cio2_hid_node);
    444	if (!fwnode) {
    445		dev_err(dev, "Error getting fwnode from cio2 software_node\n");
    446		ret = -ENODEV;
    447		goto err_unregister_sensors;
    448	}
    449
    450	set_secondary_fwnode(dev, fwnode);
    451
    452	return 0;
    453
    454err_unregister_sensors:
    455	cio2_bridge_unregister_sensors(bridge);
    456err_unregister_cio2:
    457	software_node_unregister(&bridge->cio2_hid_node);
    458err_free_bridge:
    459	kfree(bridge);
    460
    461	return ret;
    462}