lkml.org 
[lkml]   [2014]   [Apr]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCHv4 05/13] HSI: Add channel resource support to HSI clients
    Date
    Make HSI channel ids platform data, which can be provided
    by platform data.

    Signed-off-by: Sebastian Reichel <sre@kernel.org>
    ---
    drivers/hsi/clients/hsi_char.c | 12 +++++------
    drivers/hsi/hsi.c | 46 +++++++++++++++++++++++++++++++++++++++++-
    include/linux/hsi/hsi.h | 24 ++++++++++++++++++----
    3 files changed, 71 insertions(+), 11 deletions(-)

    diff --git a/drivers/hsi/clients/hsi_char.c b/drivers/hsi/clients/hsi_char.c
    index 3073320..57f70c2 100644
    --- a/drivers/hsi/clients/hsi_char.c
    +++ b/drivers/hsi/clients/hsi_char.c
    @@ -367,7 +367,7 @@ static int hsc_rx_set(struct hsi_client *cl, struct hsc_rx_config *rxc)
    return -EINVAL;
    tmp = cl->rx_cfg;
    cl->rx_cfg.mode = rxc->mode;
    - cl->rx_cfg.channels = rxc->channels;
    + cl->rx_cfg.num_hw_channels = rxc->channels;
    cl->rx_cfg.flow = rxc->flow;
    ret = hsi_setup(cl);
    if (ret < 0) {
    @@ -383,7 +383,7 @@ static int hsc_rx_set(struct hsi_client *cl, struct hsc_rx_config *rxc)
    static inline void hsc_rx_get(struct hsi_client *cl, struct hsc_rx_config *rxc)
    {
    rxc->mode = cl->rx_cfg.mode;
    - rxc->channels = cl->rx_cfg.channels;
    + rxc->channels = cl->rx_cfg.num_hw_channels;
    rxc->flow = cl->rx_cfg.flow;
    }

    @@ -402,7 +402,7 @@ static int hsc_tx_set(struct hsi_client *cl, struct hsc_tx_config *txc)
    return -EINVAL;
    tmp = cl->tx_cfg;
    cl->tx_cfg.mode = txc->mode;
    - cl->tx_cfg.channels = txc->channels;
    + cl->tx_cfg.num_hw_channels = txc->channels;
    cl->tx_cfg.speed = txc->speed;
    cl->tx_cfg.arb_mode = txc->arb_mode;
    ret = hsi_setup(cl);
    @@ -417,7 +417,7 @@ static int hsc_tx_set(struct hsi_client *cl, struct hsc_tx_config *txc)
    static inline void hsc_tx_get(struct hsi_client *cl, struct hsc_tx_config *txc)
    {
    txc->mode = cl->tx_cfg.mode;
    - txc->channels = cl->tx_cfg.channels;
    + txc->channels = cl->tx_cfg.num_hw_channels;
    txc->speed = cl->tx_cfg.speed;
    txc->arb_mode = cl->tx_cfg.arb_mode;
    }
    @@ -435,7 +435,7 @@ static ssize_t hsc_read(struct file *file, char __user *buf, size_t len,
    return -EINVAL;
    if (len > max_data_size)
    len = max_data_size;
    - if (channel->ch >= channel->cl->rx_cfg.channels)
    + if (channel->ch >= channel->cl->rx_cfg.num_hw_channels)
    return -ECHRNG;
    if (test_and_set_bit(HSC_CH_READ, &channel->flags))
    return -EBUSY;
    @@ -492,7 +492,7 @@ static ssize_t hsc_write(struct file *file, const char __user *buf, size_t len,
    return -EINVAL;
    if (len > max_data_size)
    len = max_data_size;
    - if (channel->ch >= channel->cl->tx_cfg.channels)
    + if (channel->ch >= channel->cl->tx_cfg.num_hw_channels)
    return -ECHRNG;
    if (test_and_set_bit(HSC_CH_WRITE, &channel->flags))
    return -EBUSY;
    diff --git a/drivers/hsi/hsi.c b/drivers/hsi/hsi.c
    index e96a987..de2ad8f 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);
    diff --git a/include/linux/hsi/hsi.h b/include/linux/hsi/hsi.h
    index 5a9f121..e3cff94 100644
    --- a/include/linux/hsi/hsi.h
    +++ b/include/linux/hsi/hsi.h
    @@ -68,17 +68,31 @@ enum {
    };

    /**
    + * struct hsi_channel - channel resource used by the hsi clients
    + * @id: Channel number
    + * @name: Channel name
    + */
    +struct hsi_channel {
    + unsigned int id;
    + const char *name;
    +};
    +
    +/**
    * struct hsi_config - Configuration for RX/TX HSI modules
    * @mode: Bit transmission mode (STREAM or FRAME)
    - * @channels: Number of channels to use [1..16]
    + * @channels: Channel resources used by the client
    + * @num_channels: Number of channel resources
    + * @num_hw_channels: Number of channels the transceiver is configured for [1..16]
    * @speed: Max bit transmission speed (Kbit/s)
    * @flow: RX flow type (SYNCHRONIZED or PIPELINE)
    * @arb_mode: Arbitration mode for TX frame (Round robin, priority)
    */
    struct hsi_config {
    - unsigned int mode;
    - unsigned int channels;
    - unsigned int speed;
    + unsigned int mode;
    + struct hsi_channel *channels;
    + unsigned int num_channels;
    + unsigned int num_hw_channels;
    + unsigned int speed;
    union {
    unsigned int flow; /* RX only */
    unsigned int arb_mode; /* TX only */
    @@ -306,6 +320,8 @@ static inline struct hsi_port *hsi_find_port_num(struct hsi_controller *hsi,
    */
    int hsi_async(struct hsi_client *cl, struct hsi_msg *msg);

    +int hsi_get_channel_id_by_name(struct hsi_client *cl, char *name);
    +
    /**
    * hsi_id - Get HSI controller ID associated to a client
    * @cl: Pointer to a HSI client
    --
    1.9.2


    \
     
     \ /
      Last update: 2014-04-25 21:41    [W:4.693 / U:0.000 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site