summaryrefslogtreecommitdiff
path: root/drivers/hsi/hsi.c
diff options
context:
space:
mode:
authorSebastian Reichel <sre@kernel.org>2014-03-29 01:48:23 +0400
committerSebastian Reichel <sre@kernel.org>2014-05-16 02:54:36 +0400
commita088cf161cc87b39e83c7c53b9f239773422d212 (patch)
treea58304be6d5e9fd06e2739c1485a87a0824db0e6 /drivers/hsi/hsi.c
parenta0bf37edb4d34c21bdaa19a1624378924b917491 (diff)
downloadlinux-a088cf161cc87b39e83c7c53b9f239773422d212.tar.xz
HSI: Add channel resource support to HSI clients
Make HSI channel ids platform data, which can be provided by platform data. Signed-off-by: Sebastian Reichel <sre@kernel.org> Tested-By: Ivaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
Diffstat (limited to 'drivers/hsi/hsi.c')
-rw-r--r--drivers/hsi/hsi.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/drivers/hsi/hsi.c b/drivers/hsi/hsi.c
index e96a9874b1a4..de2ad8f20d55 100644
--- a/drivers/hsi/hsi.c
+++ b/drivers/hsi/hsi.c
@@ -62,18 +62,36 @@ static struct bus_type hsi_bus_type = {
static void hsi_client_release(struct device *dev)
{
- kfree(to_hsi_client(dev));
+ struct hsi_client *cl = to_hsi_client(dev);
+
+ kfree(cl->tx_cfg.channels);
+ kfree(cl->rx_cfg.channels);
+ kfree(cl);
}
static void hsi_new_client(struct hsi_port *port, struct hsi_board_info *info)
{
struct hsi_client *cl;
+ size_t size;
cl = kzalloc(sizeof(*cl), GFP_KERNEL);
if (!cl)
return;
+
cl->tx_cfg = info->tx_cfg;
+ if (cl->tx_cfg.channels) {
+ size = cl->tx_cfg.num_channels * sizeof(*cl->tx_cfg.channels);
+ cl->tx_cfg.channels = kzalloc(size , GFP_KERNEL);
+ memcpy(cl->tx_cfg.channels, info->tx_cfg.channels, size);
+ }
+
cl->rx_cfg = info->rx_cfg;
+ if (cl->rx_cfg.channels) {
+ size = cl->rx_cfg.num_channels * sizeof(*cl->rx_cfg.channels);
+ cl->rx_cfg.channels = kzalloc(size , GFP_KERNEL);
+ memcpy(cl->rx_cfg.channels, info->rx_cfg.channels, size);
+ }
+
cl->device.bus = &hsi_bus_type;
cl->device.parent = &port->device;
cl->device.release = hsi_client_release;
@@ -502,6 +520,32 @@ int hsi_event(struct hsi_port *port, unsigned long event)
}
EXPORT_SYMBOL_GPL(hsi_event);
+/**
+ * hsi_get_channel_id_by_name - acquire channel id by channel name
+ * @cl: HSI client, which uses the channel
+ * @name: name the channel is known under
+ *
+ * Clients can call this function to get the hsi channel ids similar to
+ * requesting IRQs or GPIOs by name. This function assumes the same
+ * channel configuration is used for RX and TX.
+ *
+ * Returns -errno on error or channel id on success.
+ */
+int hsi_get_channel_id_by_name(struct hsi_client *cl, char *name)
+{
+ int i;
+
+ if (!cl->rx_cfg.channels)
+ return -ENOENT;
+
+ for (i = 0; i < cl->rx_cfg.num_channels; i++)
+ if (!strcmp(cl->rx_cfg.channels[i].name, name))
+ return cl->rx_cfg.channels[i].id;
+
+ return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(hsi_get_channel_id_by_name);
+
static int __init hsi_init(void)
{
return bus_register(&hsi_bus_type);