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);
}