0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/errno.h>
0012 #include <linux/types.h>
0013 #include <linux/atomic.h>
0014 #include <linux/kernel.h>
0015 #include <linux/init.h>
0016 #include <linux/module.h>
0017 #include <linux/mutex.h>
0018 #include <linux/list.h>
0019 #include <linux/slab.h>
0020 #include <linux/kmemleak.h>
0021 #include <linux/ioctl.h>
0022 #include <linux/wait.h>
0023 #include <linux/fs.h>
0024 #include <linux/sched.h>
0025 #include <linux/device.h>
0026 #include <linux/cdev.h>
0027 #include <linux/uaccess.h>
0028 #include <linux/scatterlist.h>
0029 #include <linux/stat.h>
0030 #include <linux/hsi/hsi.h>
0031 #include <linux/hsi/hsi_char.h>
0032
0033 #define HSC_DEVS 16
0034 #define HSC_MSGS 4
0035
0036 #define HSC_RXBREAK 0
0037
0038 #define HSC_ID_BITS 6
0039 #define HSC_PORT_ID_BITS 4
0040 #define HSC_ID_MASK 3
0041 #define HSC_PORT_ID_MASK 3
0042 #define HSC_CH_MASK 0xf
0043
0044
0045
0046
0047
0048 #define HSC_BASEMINOR(id, port_id) \
0049 ((((id) & HSC_ID_MASK) << HSC_ID_BITS) | \
0050 (((port_id) & HSC_PORT_ID_MASK) << HSC_PORT_ID_BITS))
0051
0052 enum {
0053 HSC_CH_OPEN,
0054 HSC_CH_READ,
0055 HSC_CH_WRITE,
0056 HSC_CH_WLINE,
0057 };
0058
0059 enum {
0060 HSC_RX,
0061 HSC_TX,
0062 };
0063
0064 struct hsc_client_data;
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078 struct hsc_channel {
0079 unsigned int ch;
0080 unsigned long flags;
0081 struct list_head free_msgs_list;
0082 struct list_head rx_msgs_queue;
0083 struct list_head tx_msgs_queue;
0084 spinlock_t lock;
0085 struct hsi_client *cl;
0086 struct hsc_client_data *cl_data;
0087 wait_queue_head_t rx_wait;
0088 wait_queue_head_t tx_wait;
0089 };
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100 struct hsc_client_data {
0101 struct cdev cdev;
0102 struct mutex lock;
0103 unsigned long flags;
0104 unsigned int usecnt;
0105 struct hsi_client *cl;
0106 struct hsc_channel channels[HSC_DEVS];
0107 };
0108
0109
0110 static unsigned int hsc_major;
0111
0112 static unsigned int max_data_size = 0x1000;
0113 module_param(max_data_size, uint, 0);
0114 MODULE_PARM_DESC(max_data_size, "max read/write data size [4,8..65536] (^2)");
0115
0116 static void hsc_add_tail(struct hsc_channel *channel, struct hsi_msg *msg,
0117 struct list_head *queue)
0118 {
0119 unsigned long flags;
0120
0121 spin_lock_irqsave(&channel->lock, flags);
0122 list_add_tail(&msg->link, queue);
0123 spin_unlock_irqrestore(&channel->lock, flags);
0124 }
0125
0126 static struct hsi_msg *hsc_get_first_msg(struct hsc_channel *channel,
0127 struct list_head *queue)
0128 {
0129 struct hsi_msg *msg = NULL;
0130 unsigned long flags;
0131
0132 spin_lock_irqsave(&channel->lock, flags);
0133
0134 if (list_empty(queue))
0135 goto out;
0136
0137 msg = list_first_entry(queue, struct hsi_msg, link);
0138 list_del(&msg->link);
0139 out:
0140 spin_unlock_irqrestore(&channel->lock, flags);
0141
0142 return msg;
0143 }
0144
0145 static inline void hsc_msg_free(struct hsi_msg *msg)
0146 {
0147 kfree(sg_virt(msg->sgt.sgl));
0148 hsi_free_msg(msg);
0149 }
0150
0151 static void hsc_free_list(struct list_head *list)
0152 {
0153 struct hsi_msg *msg, *tmp;
0154
0155 list_for_each_entry_safe(msg, tmp, list, link) {
0156 list_del(&msg->link);
0157 hsc_msg_free(msg);
0158 }
0159 }
0160
0161 static void hsc_reset_list(struct hsc_channel *channel, struct list_head *l)
0162 {
0163 unsigned long flags;
0164 LIST_HEAD(list);
0165
0166 spin_lock_irqsave(&channel->lock, flags);
0167 list_splice_init(l, &list);
0168 spin_unlock_irqrestore(&channel->lock, flags);
0169
0170 hsc_free_list(&list);
0171 }
0172
0173 static inline struct hsi_msg *hsc_msg_alloc(unsigned int alloc_size)
0174 {
0175 struct hsi_msg *msg;
0176 void *buf;
0177
0178 msg = hsi_alloc_msg(1, GFP_KERNEL);
0179 if (!msg)
0180 goto out;
0181 buf = kmalloc(alloc_size, GFP_KERNEL);
0182 if (!buf) {
0183 hsi_free_msg(msg);
0184 goto out;
0185 }
0186 sg_init_one(msg->sgt.sgl, buf, alloc_size);
0187
0188 kmemleak_ignore(buf);
0189
0190 return msg;
0191 out:
0192 return NULL;
0193 }
0194
0195 static inline int hsc_msgs_alloc(struct hsc_channel *channel)
0196 {
0197 struct hsi_msg *msg;
0198 int i;
0199
0200 for (i = 0; i < HSC_MSGS; i++) {
0201 msg = hsc_msg_alloc(max_data_size);
0202 if (!msg)
0203 goto out;
0204 msg->channel = channel->ch;
0205 list_add_tail(&msg->link, &channel->free_msgs_list);
0206 }
0207
0208 return 0;
0209 out:
0210 hsc_free_list(&channel->free_msgs_list);
0211
0212 return -ENOMEM;
0213 }
0214
0215 static inline unsigned int hsc_msg_len_get(struct hsi_msg *msg)
0216 {
0217 return msg->sgt.sgl->length;
0218 }
0219
0220 static inline void hsc_msg_len_set(struct hsi_msg *msg, unsigned int len)
0221 {
0222 msg->sgt.sgl->length = len;
0223 }
0224
0225 static void hsc_rx_completed(struct hsi_msg *msg)
0226 {
0227 struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
0228 struct hsc_channel *channel = cl_data->channels + msg->channel;
0229
0230 if (test_bit(HSC_CH_READ, &channel->flags)) {
0231 hsc_add_tail(channel, msg, &channel->rx_msgs_queue);
0232 wake_up(&channel->rx_wait);
0233 } else {
0234 hsc_add_tail(channel, msg, &channel->free_msgs_list);
0235 }
0236 }
0237
0238 static void hsc_rx_msg_destructor(struct hsi_msg *msg)
0239 {
0240 msg->status = HSI_STATUS_ERROR;
0241 hsc_msg_len_set(msg, 0);
0242 hsc_rx_completed(msg);
0243 }
0244
0245 static void hsc_tx_completed(struct hsi_msg *msg)
0246 {
0247 struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
0248 struct hsc_channel *channel = cl_data->channels + msg->channel;
0249
0250 if (test_bit(HSC_CH_WRITE, &channel->flags)) {
0251 hsc_add_tail(channel, msg, &channel->tx_msgs_queue);
0252 wake_up(&channel->tx_wait);
0253 } else {
0254 hsc_add_tail(channel, msg, &channel->free_msgs_list);
0255 }
0256 }
0257
0258 static void hsc_tx_msg_destructor(struct hsi_msg *msg)
0259 {
0260 msg->status = HSI_STATUS_ERROR;
0261 hsc_msg_len_set(msg, 0);
0262 hsc_tx_completed(msg);
0263 }
0264
0265 static void hsc_break_req_destructor(struct hsi_msg *msg)
0266 {
0267 struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
0268
0269 hsi_free_msg(msg);
0270 clear_bit(HSC_RXBREAK, &cl_data->flags);
0271 }
0272
0273 static void hsc_break_received(struct hsi_msg *msg)
0274 {
0275 struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
0276 struct hsc_channel *channel = cl_data->channels;
0277 int i, ret;
0278
0279
0280 for (i = 0; i < HSC_DEVS; i++, channel++) {
0281 struct hsi_msg *msg2;
0282
0283 if (!test_bit(HSC_CH_READ, &channel->flags))
0284 continue;
0285 msg2 = hsc_get_first_msg(channel, &channel->free_msgs_list);
0286 if (!msg2)
0287 continue;
0288 clear_bit(HSC_CH_READ, &channel->flags);
0289 hsc_msg_len_set(msg2, 0);
0290 msg2->status = HSI_STATUS_COMPLETED;
0291 hsc_add_tail(channel, msg2, &channel->rx_msgs_queue);
0292 wake_up(&channel->rx_wait);
0293 }
0294 hsi_flush(msg->cl);
0295 ret = hsi_async_read(msg->cl, msg);
0296 if (ret < 0)
0297 hsc_break_req_destructor(msg);
0298 }
0299
0300 static int hsc_break_request(struct hsi_client *cl)
0301 {
0302 struct hsc_client_data *cl_data = hsi_client_drvdata(cl);
0303 struct hsi_msg *msg;
0304 int ret;
0305
0306 if (test_and_set_bit(HSC_RXBREAK, &cl_data->flags))
0307 return -EBUSY;
0308
0309 msg = hsi_alloc_msg(0, GFP_KERNEL);
0310 if (!msg) {
0311 clear_bit(HSC_RXBREAK, &cl_data->flags);
0312 return -ENOMEM;
0313 }
0314 msg->break_frame = 1;
0315 msg->complete = hsc_break_received;
0316 msg->destructor = hsc_break_req_destructor;
0317 ret = hsi_async_read(cl, msg);
0318 if (ret < 0)
0319 hsc_break_req_destructor(msg);
0320
0321 return ret;
0322 }
0323
0324 static int hsc_break_send(struct hsi_client *cl)
0325 {
0326 struct hsi_msg *msg;
0327 int ret;
0328
0329 msg = hsi_alloc_msg(0, GFP_ATOMIC);
0330 if (!msg)
0331 return -ENOMEM;
0332 msg->break_frame = 1;
0333 msg->complete = hsi_free_msg;
0334 msg->destructor = hsi_free_msg;
0335 ret = hsi_async_write(cl, msg);
0336 if (ret < 0)
0337 hsi_free_msg(msg);
0338
0339 return ret;
0340 }
0341
0342 static int hsc_rx_set(struct hsi_client *cl, struct hsc_rx_config *rxc)
0343 {
0344 struct hsi_config tmp;
0345 int ret;
0346
0347 if ((rxc->mode != HSI_MODE_STREAM) && (rxc->mode != HSI_MODE_FRAME))
0348 return -EINVAL;
0349 if ((rxc->channels == 0) || (rxc->channels > HSC_DEVS))
0350 return -EINVAL;
0351 if (rxc->channels & (rxc->channels - 1))
0352 return -EINVAL;
0353 if ((rxc->flow != HSI_FLOW_SYNC) && (rxc->flow != HSI_FLOW_PIPE))
0354 return -EINVAL;
0355 tmp = cl->rx_cfg;
0356 cl->rx_cfg.mode = rxc->mode;
0357 cl->rx_cfg.num_hw_channels = rxc->channels;
0358 cl->rx_cfg.flow = rxc->flow;
0359 ret = hsi_setup(cl);
0360 if (ret < 0) {
0361 cl->rx_cfg = tmp;
0362 return ret;
0363 }
0364 if (rxc->mode == HSI_MODE_FRAME)
0365 hsc_break_request(cl);
0366
0367 return ret;
0368 }
0369
0370 static inline void hsc_rx_get(struct hsi_client *cl, struct hsc_rx_config *rxc)
0371 {
0372 rxc->mode = cl->rx_cfg.mode;
0373 rxc->channels = cl->rx_cfg.num_hw_channels;
0374 rxc->flow = cl->rx_cfg.flow;
0375 }
0376
0377 static int hsc_tx_set(struct hsi_client *cl, struct hsc_tx_config *txc)
0378 {
0379 struct hsi_config tmp;
0380 int ret;
0381
0382 if ((txc->mode != HSI_MODE_STREAM) && (txc->mode != HSI_MODE_FRAME))
0383 return -EINVAL;
0384 if ((txc->channels == 0) || (txc->channels > HSC_DEVS))
0385 return -EINVAL;
0386 if (txc->channels & (txc->channels - 1))
0387 return -EINVAL;
0388 if ((txc->arb_mode != HSI_ARB_RR) && (txc->arb_mode != HSI_ARB_PRIO))
0389 return -EINVAL;
0390 tmp = cl->tx_cfg;
0391 cl->tx_cfg.mode = txc->mode;
0392 cl->tx_cfg.num_hw_channels = txc->channels;
0393 cl->tx_cfg.speed = txc->speed;
0394 cl->tx_cfg.arb_mode = txc->arb_mode;
0395 ret = hsi_setup(cl);
0396 if (ret < 0) {
0397 cl->tx_cfg = tmp;
0398 return ret;
0399 }
0400
0401 return ret;
0402 }
0403
0404 static inline void hsc_tx_get(struct hsi_client *cl, struct hsc_tx_config *txc)
0405 {
0406 txc->mode = cl->tx_cfg.mode;
0407 txc->channels = cl->tx_cfg.num_hw_channels;
0408 txc->speed = cl->tx_cfg.speed;
0409 txc->arb_mode = cl->tx_cfg.arb_mode;
0410 }
0411
0412 static ssize_t hsc_read(struct file *file, char __user *buf, size_t len,
0413 loff_t *ppos __maybe_unused)
0414 {
0415 struct hsc_channel *channel = file->private_data;
0416 struct hsi_msg *msg;
0417 ssize_t ret;
0418
0419 if (len == 0)
0420 return 0;
0421 if (!IS_ALIGNED(len, sizeof(u32)))
0422 return -EINVAL;
0423 if (len > max_data_size)
0424 len = max_data_size;
0425 if (channel->ch >= channel->cl->rx_cfg.num_hw_channels)
0426 return -ECHRNG;
0427 if (test_and_set_bit(HSC_CH_READ, &channel->flags))
0428 return -EBUSY;
0429 msg = hsc_get_first_msg(channel, &channel->free_msgs_list);
0430 if (!msg) {
0431 ret = -ENOSPC;
0432 goto out;
0433 }
0434 hsc_msg_len_set(msg, len);
0435 msg->complete = hsc_rx_completed;
0436 msg->destructor = hsc_rx_msg_destructor;
0437 ret = hsi_async_read(channel->cl, msg);
0438 if (ret < 0) {
0439 hsc_add_tail(channel, msg, &channel->free_msgs_list);
0440 goto out;
0441 }
0442
0443 ret = wait_event_interruptible(channel->rx_wait,
0444 !list_empty(&channel->rx_msgs_queue));
0445 if (ret < 0) {
0446 clear_bit(HSC_CH_READ, &channel->flags);
0447 hsi_flush(channel->cl);
0448 return -EINTR;
0449 }
0450
0451 msg = hsc_get_first_msg(channel, &channel->rx_msgs_queue);
0452 if (msg) {
0453 if (msg->status != HSI_STATUS_ERROR) {
0454 ret = copy_to_user((void __user *)buf,
0455 sg_virt(msg->sgt.sgl), hsc_msg_len_get(msg));
0456 if (ret)
0457 ret = -EFAULT;
0458 else
0459 ret = hsc_msg_len_get(msg);
0460 } else {
0461 ret = -EIO;
0462 }
0463 hsc_add_tail(channel, msg, &channel->free_msgs_list);
0464 }
0465 out:
0466 clear_bit(HSC_CH_READ, &channel->flags);
0467
0468 return ret;
0469 }
0470
0471 static ssize_t hsc_write(struct file *file, const char __user *buf, size_t len,
0472 loff_t *ppos __maybe_unused)
0473 {
0474 struct hsc_channel *channel = file->private_data;
0475 struct hsi_msg *msg;
0476 ssize_t ret;
0477
0478 if ((len == 0) || !IS_ALIGNED(len, sizeof(u32)))
0479 return -EINVAL;
0480 if (len > max_data_size)
0481 len = max_data_size;
0482 if (channel->ch >= channel->cl->tx_cfg.num_hw_channels)
0483 return -ECHRNG;
0484 if (test_and_set_bit(HSC_CH_WRITE, &channel->flags))
0485 return -EBUSY;
0486 msg = hsc_get_first_msg(channel, &channel->free_msgs_list);
0487 if (!msg) {
0488 clear_bit(HSC_CH_WRITE, &channel->flags);
0489 return -ENOSPC;
0490 }
0491 if (copy_from_user(sg_virt(msg->sgt.sgl), (void __user *)buf, len)) {
0492 ret = -EFAULT;
0493 goto out;
0494 }
0495 hsc_msg_len_set(msg, len);
0496 msg->complete = hsc_tx_completed;
0497 msg->destructor = hsc_tx_msg_destructor;
0498 ret = hsi_async_write(channel->cl, msg);
0499 if (ret < 0)
0500 goto out;
0501
0502 ret = wait_event_interruptible(channel->tx_wait,
0503 !list_empty(&channel->tx_msgs_queue));
0504 if (ret < 0) {
0505 clear_bit(HSC_CH_WRITE, &channel->flags);
0506 hsi_flush(channel->cl);
0507 return -EINTR;
0508 }
0509
0510 msg = hsc_get_first_msg(channel, &channel->tx_msgs_queue);
0511 if (msg) {
0512 if (msg->status == HSI_STATUS_ERROR)
0513 ret = -EIO;
0514 else
0515 ret = hsc_msg_len_get(msg);
0516
0517 hsc_add_tail(channel, msg, &channel->free_msgs_list);
0518 }
0519 out:
0520 clear_bit(HSC_CH_WRITE, &channel->flags);
0521
0522 return ret;
0523 }
0524
0525 static long hsc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
0526 {
0527 struct hsc_channel *channel = file->private_data;
0528 unsigned int state;
0529 struct hsc_rx_config rxc;
0530 struct hsc_tx_config txc;
0531 long ret = 0;
0532
0533 switch (cmd) {
0534 case HSC_RESET:
0535 hsi_flush(channel->cl);
0536 break;
0537 case HSC_SET_PM:
0538 if (copy_from_user(&state, (void __user *)arg, sizeof(state)))
0539 return -EFAULT;
0540 if (state == HSC_PM_DISABLE) {
0541 if (test_and_set_bit(HSC_CH_WLINE, &channel->flags))
0542 return -EINVAL;
0543 ret = hsi_start_tx(channel->cl);
0544 } else if (state == HSC_PM_ENABLE) {
0545 if (!test_and_clear_bit(HSC_CH_WLINE, &channel->flags))
0546 return -EINVAL;
0547 ret = hsi_stop_tx(channel->cl);
0548 } else {
0549 ret = -EINVAL;
0550 }
0551 break;
0552 case HSC_SEND_BREAK:
0553 return hsc_break_send(channel->cl);
0554 case HSC_SET_RX:
0555 if (copy_from_user(&rxc, (void __user *)arg, sizeof(rxc)))
0556 return -EFAULT;
0557 return hsc_rx_set(channel->cl, &rxc);
0558 case HSC_GET_RX:
0559 hsc_rx_get(channel->cl, &rxc);
0560 if (copy_to_user((void __user *)arg, &rxc, sizeof(rxc)))
0561 return -EFAULT;
0562 break;
0563 case HSC_SET_TX:
0564 if (copy_from_user(&txc, (void __user *)arg, sizeof(txc)))
0565 return -EFAULT;
0566 return hsc_tx_set(channel->cl, &txc);
0567 case HSC_GET_TX:
0568 hsc_tx_get(channel->cl, &txc);
0569 if (copy_to_user((void __user *)arg, &txc, sizeof(txc)))
0570 return -EFAULT;
0571 break;
0572 default:
0573 return -ENOIOCTLCMD;
0574 }
0575
0576 return ret;
0577 }
0578
0579 static inline void __hsc_port_release(struct hsc_client_data *cl_data)
0580 {
0581 BUG_ON(cl_data->usecnt == 0);
0582
0583 if (--cl_data->usecnt == 0) {
0584 hsi_flush(cl_data->cl);
0585 hsi_release_port(cl_data->cl);
0586 }
0587 }
0588
0589 static int hsc_open(struct inode *inode, struct file *file)
0590 {
0591 struct hsc_client_data *cl_data;
0592 struct hsc_channel *channel;
0593 int ret = 0;
0594
0595 pr_debug("open, minor = %d\n", iminor(inode));
0596
0597 cl_data = container_of(inode->i_cdev, struct hsc_client_data, cdev);
0598 mutex_lock(&cl_data->lock);
0599 channel = cl_data->channels + (iminor(inode) & HSC_CH_MASK);
0600
0601 if (test_and_set_bit(HSC_CH_OPEN, &channel->flags)) {
0602 ret = -EBUSY;
0603 goto out;
0604 }
0605
0606
0607
0608
0609 if (cl_data->usecnt == 0) {
0610 ret = hsi_claim_port(cl_data->cl, 0);
0611 if (ret < 0)
0612 goto out;
0613 hsi_setup(cl_data->cl);
0614 }
0615 cl_data->usecnt++;
0616
0617 ret = hsc_msgs_alloc(channel);
0618 if (ret < 0) {
0619 __hsc_port_release(cl_data);
0620 goto out;
0621 }
0622
0623 file->private_data = channel;
0624 mutex_unlock(&cl_data->lock);
0625
0626 return ret;
0627 out:
0628 mutex_unlock(&cl_data->lock);
0629
0630 return ret;
0631 }
0632
0633 static int hsc_release(struct inode *inode __maybe_unused, struct file *file)
0634 {
0635 struct hsc_channel *channel = file->private_data;
0636 struct hsc_client_data *cl_data = channel->cl_data;
0637
0638 mutex_lock(&cl_data->lock);
0639 file->private_data = NULL;
0640 if (test_and_clear_bit(HSC_CH_WLINE, &channel->flags))
0641 hsi_stop_tx(channel->cl);
0642 __hsc_port_release(cl_data);
0643 hsc_reset_list(channel, &channel->rx_msgs_queue);
0644 hsc_reset_list(channel, &channel->tx_msgs_queue);
0645 hsc_reset_list(channel, &channel->free_msgs_list);
0646 clear_bit(HSC_CH_READ, &channel->flags);
0647 clear_bit(HSC_CH_WRITE, &channel->flags);
0648 clear_bit(HSC_CH_OPEN, &channel->flags);
0649 wake_up(&channel->rx_wait);
0650 wake_up(&channel->tx_wait);
0651 mutex_unlock(&cl_data->lock);
0652
0653 return 0;
0654 }
0655
0656 static const struct file_operations hsc_fops = {
0657 .owner = THIS_MODULE,
0658 .read = hsc_read,
0659 .write = hsc_write,
0660 .unlocked_ioctl = hsc_ioctl,
0661 .open = hsc_open,
0662 .release = hsc_release,
0663 };
0664
0665 static void hsc_channel_init(struct hsc_channel *channel)
0666 {
0667 init_waitqueue_head(&channel->rx_wait);
0668 init_waitqueue_head(&channel->tx_wait);
0669 spin_lock_init(&channel->lock);
0670 INIT_LIST_HEAD(&channel->free_msgs_list);
0671 INIT_LIST_HEAD(&channel->rx_msgs_queue);
0672 INIT_LIST_HEAD(&channel->tx_msgs_queue);
0673 }
0674
0675 static int hsc_probe(struct device *dev)
0676 {
0677 const char devname[] = "hsi_char";
0678 struct hsc_client_data *cl_data;
0679 struct hsc_channel *channel;
0680 struct hsi_client *cl = to_hsi_client(dev);
0681 unsigned int hsc_baseminor;
0682 dev_t hsc_dev;
0683 int ret;
0684 int i;
0685
0686 cl_data = kzalloc(sizeof(*cl_data), GFP_KERNEL);
0687 if (!cl_data)
0688 return -ENOMEM;
0689
0690 hsc_baseminor = HSC_BASEMINOR(hsi_id(cl), hsi_port_id(cl));
0691 if (!hsc_major) {
0692 ret = alloc_chrdev_region(&hsc_dev, hsc_baseminor,
0693 HSC_DEVS, devname);
0694 if (ret == 0)
0695 hsc_major = MAJOR(hsc_dev);
0696 } else {
0697 hsc_dev = MKDEV(hsc_major, hsc_baseminor);
0698 ret = register_chrdev_region(hsc_dev, HSC_DEVS, devname);
0699 }
0700 if (ret < 0) {
0701 dev_err(dev, "Device %s allocation failed %d\n",
0702 hsc_major ? "minor" : "major", ret);
0703 goto out1;
0704 }
0705 mutex_init(&cl_data->lock);
0706 hsi_client_set_drvdata(cl, cl_data);
0707 cdev_init(&cl_data->cdev, &hsc_fops);
0708 cl_data->cdev.owner = THIS_MODULE;
0709 cl_data->cl = cl;
0710 for (i = 0, channel = cl_data->channels; i < HSC_DEVS; i++, channel++) {
0711 hsc_channel_init(channel);
0712 channel->ch = i;
0713 channel->cl = cl;
0714 channel->cl_data = cl_data;
0715 }
0716
0717
0718 ret = cdev_add(&cl_data->cdev, hsc_dev, HSC_DEVS);
0719 if (ret) {
0720 dev_err(dev, "Could not add char device %d\n", ret);
0721 goto out2;
0722 }
0723
0724 return 0;
0725 out2:
0726 unregister_chrdev_region(hsc_dev, HSC_DEVS);
0727 out1:
0728 kfree(cl_data);
0729
0730 return ret;
0731 }
0732
0733 static int hsc_remove(struct device *dev)
0734 {
0735 struct hsi_client *cl = to_hsi_client(dev);
0736 struct hsc_client_data *cl_data = hsi_client_drvdata(cl);
0737 dev_t hsc_dev = cl_data->cdev.dev;
0738
0739 cdev_del(&cl_data->cdev);
0740 unregister_chrdev_region(hsc_dev, HSC_DEVS);
0741 hsi_client_set_drvdata(cl, NULL);
0742 kfree(cl_data);
0743
0744 return 0;
0745 }
0746
0747 static struct hsi_client_driver hsc_driver = {
0748 .driver = {
0749 .name = "hsi_char",
0750 .owner = THIS_MODULE,
0751 .probe = hsc_probe,
0752 .remove = hsc_remove,
0753 },
0754 };
0755
0756 static int __init hsc_init(void)
0757 {
0758 int ret;
0759
0760 if ((max_data_size < 4) || (max_data_size > 0x10000) ||
0761 (max_data_size & (max_data_size - 1))) {
0762 pr_err("Invalid max read/write data size\n");
0763 return -EINVAL;
0764 }
0765
0766 ret = hsi_register_client_driver(&hsc_driver);
0767 if (ret) {
0768 pr_err("Error while registering HSI/SSI driver %d\n", ret);
0769 return ret;
0770 }
0771
0772 pr_info("HSI/SSI char device loaded\n");
0773
0774 return 0;
0775 }
0776 module_init(hsc_init);
0777
0778 static void __exit hsc_exit(void)
0779 {
0780 hsi_unregister_client_driver(&hsc_driver);
0781 pr_info("HSI char device removed\n");
0782 }
0783 module_exit(hsc_exit);
0784
0785 MODULE_AUTHOR("Andras Domokos <andras.domokos@nokia.com>");
0786 MODULE_ALIAS("hsi:hsi_char");
0787 MODULE_DESCRIPTION("HSI character device");
0788 MODULE_LICENSE("GPL v2");