diff options
-rw-r--r-- | drivers/i2c/busses/i2c-sh_mobile.c | 98 |
1 files changed, 48 insertions, 50 deletions
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index b49e946b2940..a12297e7680a 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c | |||
@@ -140,6 +140,7 @@ struct sh_mobile_i2c_data { | |||
140 | int sr; | 140 | int sr; |
141 | bool send_stop; | 141 | bool send_stop; |
142 | 142 | ||
143 | struct resource *res; | ||
143 | struct dma_chan *dma_tx; | 144 | struct dma_chan *dma_tx; |
144 | struct dma_chan *dma_rx; | 145 | struct dma_chan *dma_rx; |
145 | struct scatterlist sg; | 146 | struct scatterlist sg; |
@@ -539,6 +540,41 @@ static void sh_mobile_i2c_dma_callback(void *data) | |||
539 | iic_set_clr(pd, ICIC, 0, ICIC_TDMAE | ICIC_RDMAE); | 540 | iic_set_clr(pd, ICIC, 0, ICIC_TDMAE | ICIC_RDMAE); |
540 | } | 541 | } |
541 | 542 | ||
543 | static struct dma_chan *sh_mobile_i2c_request_dma_chan(struct device *dev, | ||
544 | enum dma_transfer_direction dir, dma_addr_t port_addr) | ||
545 | { | ||
546 | struct dma_chan *chan; | ||
547 | struct dma_slave_config cfg; | ||
548 | char *chan_name = dir == DMA_MEM_TO_DEV ? "tx" : "rx"; | ||
549 | int ret; | ||
550 | |||
551 | chan = dma_request_slave_channel_reason(dev, chan_name); | ||
552 | if (IS_ERR(chan)) { | ||
553 | dev_dbg(dev, "request_channel failed for %s (%d)\n", chan_name, ret); | ||
554 | return chan; | ||
555 | } | ||
556 | |||
557 | memset(&cfg, 0, sizeof(cfg)); | ||
558 | cfg.direction = dir; | ||
559 | if (dir == DMA_MEM_TO_DEV) { | ||
560 | cfg.dst_addr = port_addr; | ||
561 | cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; | ||
562 | } else { | ||
563 | cfg.src_addr = port_addr; | ||
564 | cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; | ||
565 | } | ||
566 | |||
567 | ret = dmaengine_slave_config(chan, &cfg); | ||
568 | if (ret) { | ||
569 | dev_dbg(dev, "slave_config failed for %s (%d)\n", chan_name, ret); | ||
570 | dma_release_channel(chan); | ||
571 | return ERR_PTR(ret); | ||
572 | } | ||
573 | |||
574 | dev_dbg(dev, "got DMA channel for %s\n", chan_name); | ||
575 | return chan; | ||
576 | } | ||
577 | |||
542 | static void sh_mobile_i2c_xfer_dma(struct sh_mobile_i2c_data *pd) | 578 | static void sh_mobile_i2c_xfer_dma(struct sh_mobile_i2c_data *pd) |
543 | { | 579 | { |
544 | bool read = pd->msg->flags & I2C_M_RD; | 580 | bool read = pd->msg->flags & I2C_M_RD; |
@@ -548,6 +584,15 @@ static void sh_mobile_i2c_xfer_dma(struct sh_mobile_i2c_data *pd) | |||
548 | dma_addr_t dma_addr; | 584 | dma_addr_t dma_addr; |
549 | dma_cookie_t cookie; | 585 | dma_cookie_t cookie; |
550 | 586 | ||
587 | if (PTR_ERR(chan) == -EPROBE_DEFER) { | ||
588 | if (read) | ||
589 | chan = pd->dma_rx = sh_mobile_i2c_request_dma_chan(pd->dev, DMA_DEV_TO_MEM, | ||
590 | pd->res->start + ICDR); | ||
591 | else | ||
592 | chan = pd->dma_tx = sh_mobile_i2c_request_dma_chan(pd->dev, DMA_MEM_TO_DEV, | ||
593 | pd->res->start + ICDR); | ||
594 | } | ||
595 | |||
551 | if (IS_ERR(chan)) | 596 | if (IS_ERR(chan)) |
552 | return; | 597 | return; |
553 | 598 | ||
@@ -747,41 +792,6 @@ static const struct of_device_id sh_mobile_i2c_dt_ids[] = { | |||
747 | }; | 792 | }; |
748 | MODULE_DEVICE_TABLE(of, sh_mobile_i2c_dt_ids); | 793 | MODULE_DEVICE_TABLE(of, sh_mobile_i2c_dt_ids); |
749 | 794 | ||
750 | static struct dma_chan *sh_mobile_i2c_request_dma_chan(struct device *dev, | ||
751 | enum dma_transfer_direction dir, dma_addr_t port_addr) | ||
752 | { | ||
753 | struct dma_chan *chan; | ||
754 | struct dma_slave_config cfg; | ||
755 | char *chan_name = dir == DMA_MEM_TO_DEV ? "tx" : "rx"; | ||
756 | int ret; | ||
757 | |||
758 | chan = dma_request_slave_channel_reason(dev, chan_name); | ||
759 | if (IS_ERR(chan)) { | ||
760 | dev_dbg(dev, "request_channel failed for %s (%d)\n", chan_name, ret); | ||
761 | return chan; | ||
762 | } | ||
763 | |||
764 | memset(&cfg, 0, sizeof(cfg)); | ||
765 | cfg.direction = dir; | ||
766 | if (dir == DMA_MEM_TO_DEV) { | ||
767 | cfg.dst_addr = port_addr; | ||
768 | cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; | ||
769 | } else { | ||
770 | cfg.src_addr = port_addr; | ||
771 | cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; | ||
772 | } | ||
773 | |||
774 | ret = dmaengine_slave_config(chan, &cfg); | ||
775 | if (ret) { | ||
776 | dev_dbg(dev, "slave_config failed for %s (%d)\n", chan_name, ret); | ||
777 | dma_release_channel(chan); | ||
778 | return ERR_PTR(ret); | ||
779 | } | ||
780 | |||
781 | dev_dbg(dev, "got DMA channel for %s\n", chan_name); | ||
782 | return chan; | ||
783 | } | ||
784 | |||
785 | static void sh_mobile_i2c_release_dma(struct sh_mobile_i2c_data *pd) | 795 | static void sh_mobile_i2c_release_dma(struct sh_mobile_i2c_data *pd) |
786 | { | 796 | { |
787 | if (!IS_ERR(pd->dma_tx)) { | 797 | if (!IS_ERR(pd->dma_tx)) { |
@@ -844,6 +854,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) | |||
844 | 854 | ||
845 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | 855 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); |
846 | 856 | ||
857 | pd->res = res; | ||
847 | pd->reg = devm_ioremap_resource(&dev->dev, res); | 858 | pd->reg = devm_ioremap_resource(&dev->dev, res); |
848 | if (IS_ERR(pd->reg)) | 859 | if (IS_ERR(pd->reg)) |
849 | return PTR_ERR(pd->reg); | 860 | return PTR_ERR(pd->reg); |
@@ -884,19 +895,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) | |||
884 | /* Init DMA */ | 895 | /* Init DMA */ |
885 | sg_init_table(&pd->sg, 1); | 896 | sg_init_table(&pd->sg, 1); |
886 | pd->dma_direction = DMA_NONE; | 897 | pd->dma_direction = DMA_NONE; |
887 | pd->dma_rx = sh_mobile_i2c_request_dma_chan(pd->dev, DMA_DEV_TO_MEM, | 898 | pd->dma_rx = pd->dma_tx = ERR_PTR(-EPROBE_DEFER); |
888 | res->start + ICDR); | ||
889 | ret = PTR_ERR(pd->dma_rx); | ||
890 | if (ret == -EPROBE_DEFER) | ||
891 | return ret; | ||
892 | |||
893 | pd->dma_tx = sh_mobile_i2c_request_dma_chan(pd->dev, DMA_MEM_TO_DEV, | ||
894 | res->start + ICDR); | ||
895 | ret = PTR_ERR(pd->dma_tx); | ||
896 | if (ret == -EPROBE_DEFER) { | ||
897 | sh_mobile_i2c_release_dma(pd); | ||
898 | return ret; | ||
899 | } | ||
900 | 899 | ||
901 | /* Enable Runtime PM for this device. | 900 | /* Enable Runtime PM for this device. |
902 | * | 901 | * |
@@ -934,8 +933,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) | |||
934 | return ret; | 933 | return ret; |
935 | } | 934 | } |
936 | 935 | ||
937 | dev_info(&dev->dev, "I2C adapter %d, bus speed %lu Hz, DMA=%c\n", | 936 | dev_info(&dev->dev, "I2C adapter %d, bus speed %lu Hz\n", adap->nr, pd->bus_speed); |
938 | adap->nr, pd->bus_speed, (pd->dma_rx || pd->dma_tx) ? 'y' : 'n'); | ||
939 | 937 | ||
940 | return 0; | 938 | return 0; |
941 | } | 939 | } |