aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c98
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
543static 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
542static void sh_mobile_i2c_xfer_dma(struct sh_mobile_i2c_data *pd) 578static 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};
748MODULE_DEVICE_TABLE(of, sh_mobile_i2c_dt_ids); 793MODULE_DEVICE_TABLE(of, sh_mobile_i2c_dt_ids);
749 794
750static 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
785static void sh_mobile_i2c_release_dma(struct sh_mobile_i2c_data *pd) 795static 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}