static void hsi_add_client_from_dt()

in hsi_core.c [197:310]


static void hsi_add_client_from_dt(struct hsi_port *port,
						struct device_node *client)
{
	struct hsi_client *cl;
	struct hsi_channel channel;
	struct property *prop;
	char name[32];
	int length, cells, err, i, max_chan, mode;

	cl = kzalloc(sizeof(*cl), GFP_KERNEL);
	if (!cl)
		return;

	err = of_modalias_node(client, name, sizeof(name));
	if (err)
		goto err;

	err = hsi_of_property_parse_mode(client, "hsi-mode", &mode);
	if (err) {
		err = hsi_of_property_parse_mode(client, "hsi-rx-mode",
						 &cl->rx_cfg.mode);
		if (err)
			goto err;

		err = hsi_of_property_parse_mode(client, "hsi-tx-mode",
						 &cl->tx_cfg.mode);
		if (err)
			goto err;
	} else {
		cl->rx_cfg.mode = mode;
		cl->tx_cfg.mode = mode;
	}

	err = of_property_read_u32(client, "hsi-speed-kbps",
				   &cl->tx_cfg.speed);
	if (err)
		goto err;
	cl->rx_cfg.speed = cl->tx_cfg.speed;

	err = hsi_of_property_parse_flow(client, "hsi-flow",
					 &cl->rx_cfg.flow);
	if (err)
		goto err;

	err = hsi_of_property_parse_arb_mode(client, "hsi-arb-mode",
					     &cl->rx_cfg.arb_mode);
	if (err)
		goto err;

	prop = of_find_property(client, "hsi-channel-ids", &length);
	if (!prop) {
		err = -EINVAL;
		goto err;
	}

	cells = length / sizeof(u32);

	cl->rx_cfg.num_channels = cells;
	cl->tx_cfg.num_channels = cells;
	cl->rx_cfg.channels = kcalloc(cells, sizeof(channel), GFP_KERNEL);
	if (!cl->rx_cfg.channels) {
		err = -ENOMEM;
		goto err;
	}

	cl->tx_cfg.channels = kcalloc(cells, sizeof(channel), GFP_KERNEL);
	if (!cl->tx_cfg.channels) {
		err = -ENOMEM;
		goto err2;
	}

	max_chan = 0;
	for (i = 0; i < cells; i++) {
		err = of_property_read_u32_index(client, "hsi-channel-ids", i,
						 &channel.id);
		if (err)
			goto err3;

		err = of_property_read_string_index(client, "hsi-channel-names",
						    i, &channel.name);
		if (err)
			channel.name = NULL;

		if (channel.id > max_chan)
			max_chan = channel.id;

		cl->rx_cfg.channels[i] = channel;
		cl->tx_cfg.channels[i] = channel;
	}

	cl->rx_cfg.num_hw_channels = max_chan + 1;
	cl->tx_cfg.num_hw_channels = max_chan + 1;

	cl->device.bus = &hsi_bus_type;
	cl->device.parent = &port->device;
	cl->device.release = hsi_client_release;
	cl->device.of_node = client;

	dev_set_name(&cl->device, "%s", name);
	if (device_register(&cl->device) < 0) {
		pr_err("hsi: failed to register client: %s\n", name);
		put_device(&cl->device);
	}

	return;

err3:
	kfree(cl->tx_cfg.channels);
err2:
	kfree(cl->rx_cfg.channels);
err:
	kfree(cl);
	pr_err("hsi client: missing or incorrect of property: err=%d\n", err);
}