diff options
-rw-r--r-- | drivers/i2c/busses/i2c-nomadik.c | 73 |
1 files changed, 58 insertions, 15 deletions
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index e10e5cf3751a..182761eace80 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/err.h> | 22 | #include <linux/err.h> |
23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | #include <linux/regulator/consumer.h> | ||
25 | 26 | ||
26 | #include <plat/i2c.h> | 27 | #include <plat/i2c.h> |
27 | 28 | ||
@@ -151,6 +152,7 @@ struct i2c_nmk_client { | |||
151 | * @stop: stop condition | 152 | * @stop: stop condition |
152 | * @xfer_complete: acknowledge completion for a I2C message | 153 | * @xfer_complete: acknowledge completion for a I2C message |
153 | * @result: controller propogated result | 154 | * @result: controller propogated result |
155 | * @busy: Busy doing transfer | ||
154 | */ | 156 | */ |
155 | struct nmk_i2c_dev { | 157 | struct nmk_i2c_dev { |
156 | struct platform_device *pdev; | 158 | struct platform_device *pdev; |
@@ -163,6 +165,8 @@ struct nmk_i2c_dev { | |||
163 | int stop; | 165 | int stop; |
164 | struct completion xfer_complete; | 166 | struct completion xfer_complete; |
165 | int result; | 167 | int result; |
168 | struct regulator *regulator; | ||
169 | bool busy; | ||
166 | }; | 170 | }; |
167 | 171 | ||
168 | /* controller's abort causes */ | 172 | /* controller's abort causes */ |
@@ -257,7 +261,7 @@ static int init_hw(struct nmk_i2c_dev *dev) | |||
257 | 261 | ||
258 | stat = flush_i2c_fifo(dev); | 262 | stat = flush_i2c_fifo(dev); |
259 | if (stat) | 263 | if (stat) |
260 | return stat; | 264 | goto exit; |
261 | 265 | ||
262 | /* disable the controller */ | 266 | /* disable the controller */ |
263 | i2c_clr_bit(dev->virtbase + I2C_CR , I2C_CR_PE); | 267 | i2c_clr_bit(dev->virtbase + I2C_CR , I2C_CR_PE); |
@@ -268,10 +272,16 @@ static int init_hw(struct nmk_i2c_dev *dev) | |||
268 | 272 | ||
269 | dev->cli.operation = I2C_NO_OPERATION; | 273 | dev->cli.operation = I2C_NO_OPERATION; |
270 | 274 | ||
275 | exit: | ||
276 | /* TODO: Why disable clocks after init hw? */ | ||
271 | clk_disable(dev->clk); | 277 | clk_disable(dev->clk); |
272 | 278 | /* | |
279 | * TODO: What is this delay for? | ||
280 | * Must be pretty pointless since the hw block | ||
281 | * is frozen. Or? | ||
282 | */ | ||
273 | udelay(I2C_DELAY); | 283 | udelay(I2C_DELAY); |
274 | return 0; | 284 | return stat; |
275 | } | 285 | } |
276 | 286 | ||
277 | /* enable peripheral, master mode operation */ | 287 | /* enable peripheral, master mode operation */ |
@@ -562,9 +572,14 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
562 | u32 cause; | 572 | u32 cause; |
563 | struct nmk_i2c_dev *dev = i2c_get_adapdata(i2c_adap); | 573 | struct nmk_i2c_dev *dev = i2c_get_adapdata(i2c_adap); |
564 | 574 | ||
575 | dev->busy = true; | ||
576 | |||
577 | if (dev->regulator) | ||
578 | regulator_enable(dev->regulator); | ||
579 | |||
565 | status = init_hw(dev); | 580 | status = init_hw(dev); |
566 | if (status) | 581 | if (status) |
567 | return status; | 582 | goto out2; |
568 | 583 | ||
569 | clk_enable(dev->clk); | 584 | clk_enable(dev->clk); |
570 | 585 | ||
@@ -575,7 +590,9 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
575 | if (unlikely(msgs[i].flags & I2C_M_TEN)) { | 590 | if (unlikely(msgs[i].flags & I2C_M_TEN)) { |
576 | dev_err(&dev->pdev->dev, "10 bit addressing" | 591 | dev_err(&dev->pdev->dev, "10 bit addressing" |
577 | "not supported\n"); | 592 | "not supported\n"); |
578 | return -EINVAL; | 593 | |
594 | status = -EINVAL; | ||
595 | goto out; | ||
579 | } | 596 | } |
580 | dev->cli.slave_adr = msgs[i].addr; | 597 | dev->cli.slave_adr = msgs[i].addr; |
581 | dev->cli.buffer = msgs[i].buf; | 598 | dev->cli.buffer = msgs[i].buf; |
@@ -600,12 +617,19 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
600 | dev_err(&dev->pdev->dev, "%s\n", | 617 | dev_err(&dev->pdev->dev, "%s\n", |
601 | cause >= ARRAY_SIZE(abort_causes) | 618 | cause >= ARRAY_SIZE(abort_causes) |
602 | ? "unknown reason" : abort_causes[cause]); | 619 | ? "unknown reason" : abort_causes[cause]); |
603 | clk_disable(dev->clk); | 620 | |
604 | return status; | 621 | goto out; |
605 | } | 622 | } |
606 | udelay(I2C_DELAY); | 623 | udelay(I2C_DELAY); |
607 | } | 624 | } |
625 | |||
626 | out: | ||
608 | clk_disable(dev->clk); | 627 | clk_disable(dev->clk); |
628 | out2: | ||
629 | if (dev->regulator) | ||
630 | regulator_disable(dev->regulator); | ||
631 | |||
632 | dev->busy = false; | ||
609 | 633 | ||
610 | /* return the no. messages processed */ | 634 | /* return the no. messages processed */ |
611 | if (status) | 635 | if (status) |
@@ -805,6 +829,21 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg) | |||
805 | return IRQ_HANDLED; | 829 | return IRQ_HANDLED; |
806 | } | 830 | } |
807 | 831 | ||
832 | |||
833 | #ifdef CONFIG_PM | ||
834 | static int nmk_i2c_suspend(struct platform_device *pdev, pm_message_t mesg) | ||
835 | { | ||
836 | struct nmk_i2c_dev *dev = platform_get_drvdata(pdev); | ||
837 | |||
838 | if (dev->busy) | ||
839 | return -EBUSY; | ||
840 | else | ||
841 | return 0; | ||
842 | } | ||
843 | #else | ||
844 | #define nmk_i2c_suspend NULL | ||
845 | #endif | ||
846 | |||
808 | static unsigned int nmk_i2c_functionality(struct i2c_adapter *adap) | 847 | static unsigned int nmk_i2c_functionality(struct i2c_adapter *adap) |
809 | { | 848 | { |
810 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | 849 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; |
@@ -830,7 +869,7 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev) | |||
830 | ret = -ENOMEM; | 869 | ret = -ENOMEM; |
831 | goto err_no_mem; | 870 | goto err_no_mem; |
832 | } | 871 | } |
833 | 872 | dev->busy = false; | |
834 | dev->pdev = pdev; | 873 | dev->pdev = pdev; |
835 | platform_set_drvdata(pdev, dev); | 874 | platform_set_drvdata(pdev, dev); |
836 | 875 | ||
@@ -860,6 +899,12 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev) | |||
860 | goto err_irq; | 899 | goto err_irq; |
861 | } | 900 | } |
862 | 901 | ||
902 | dev->regulator = regulator_get(&pdev->dev, "v-i2c"); | ||
903 | if (IS_ERR(dev->regulator)) { | ||
904 | dev_warn(&pdev->dev, "could not get i2c regulator\n"); | ||
905 | dev->regulator = NULL; | ||
906 | } | ||
907 | |||
863 | dev->clk = clk_get(&pdev->dev, NULL); | 908 | dev->clk = clk_get(&pdev->dev, NULL); |
864 | if (IS_ERR(dev->clk)) { | 909 | if (IS_ERR(dev->clk)) { |
865 | dev_err(&pdev->dev, "could not get i2c clock\n"); | 910 | dev_err(&pdev->dev, "could not get i2c clock\n"); |
@@ -887,12 +932,6 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev) | |||
887 | 932 | ||
888 | i2c_set_adapdata(adap, dev); | 933 | i2c_set_adapdata(adap, dev); |
889 | 934 | ||
890 | ret = init_hw(dev); | ||
891 | if (ret != 0) { | ||
892 | dev_err(&pdev->dev, "error in initializing i2c hardware\n"); | ||
893 | goto err_init_hw; | ||
894 | } | ||
895 | |||
896 | dev_info(&pdev->dev, "initialize %s on virtual " | 935 | dev_info(&pdev->dev, "initialize %s on virtual " |
897 | "base %p\n", adap->name, dev->virtbase); | 936 | "base %p\n", adap->name, dev->virtbase); |
898 | 937 | ||
@@ -904,10 +943,11 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev) | |||
904 | 943 | ||
905 | return 0; | 944 | return 0; |
906 | 945 | ||
907 | err_init_hw: | ||
908 | err_add_adap: | 946 | err_add_adap: |
909 | clk_put(dev->clk); | 947 | clk_put(dev->clk); |
910 | err_no_clk: | 948 | err_no_clk: |
949 | if (dev->regulator) | ||
950 | regulator_put(dev->regulator); | ||
911 | free_irq(dev->irq, dev); | 951 | free_irq(dev->irq, dev); |
912 | err_irq: | 952 | err_irq: |
913 | iounmap(dev->virtbase); | 953 | iounmap(dev->virtbase); |
@@ -938,6 +978,8 @@ static int __devexit nmk_i2c_remove(struct platform_device *pdev) | |||
938 | if (res) | 978 | if (res) |
939 | release_mem_region(res->start, resource_size(res)); | 979 | release_mem_region(res->start, resource_size(res)); |
940 | clk_put(dev->clk); | 980 | clk_put(dev->clk); |
981 | if (dev->regulator) | ||
982 | regulator_put(dev->regulator); | ||
941 | platform_set_drvdata(pdev, NULL); | 983 | platform_set_drvdata(pdev, NULL); |
942 | kfree(dev); | 984 | kfree(dev); |
943 | 985 | ||
@@ -951,6 +993,7 @@ static struct platform_driver nmk_i2c_driver = { | |||
951 | }, | 993 | }, |
952 | .probe = nmk_i2c_probe, | 994 | .probe = nmk_i2c_probe, |
953 | .remove = __devexit_p(nmk_i2c_remove), | 995 | .remove = __devexit_p(nmk_i2c_remove), |
996 | .suspend = nmk_i2c_suspend, | ||
954 | }; | 997 | }; |
955 | 998 | ||
956 | static int __init nmk_i2c_init(void) | 999 | static int __init nmk_i2c_init(void) |