diff options
author | Wolfram Sang <wsa+renesas@sang-engineering.com> | 2015-06-09 03:14:39 -0400 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2015-06-17 06:40:38 -0400 |
commit | 3ded3743a026e0762fa74467eafc66ecc1c484cc (patch) | |
tree | b7dd4178119f4aeafb48021c9157e9357c30673c /drivers/i2c | |
parent | f30dc5208ca270ff783fa895b74bdd76dcb4ba3e (diff) |
i2c: sh_mobile: add errata workaround
This used to be in platform init code. We want it to do in the driver
now. This is basically a code move and a new compatible added.
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Acked-by: Simon Horman <horms+renesas@verge.net.au>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-sh_mobile.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 007818b3e174..7193bcfdd940 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c | |||
@@ -150,6 +150,7 @@ struct sh_mobile_i2c_data { | |||
150 | 150 | ||
151 | struct sh_mobile_dt_config { | 151 | struct sh_mobile_dt_config { |
152 | int clks_per_count; | 152 | int clks_per_count; |
153 | void (*setup)(struct sh_mobile_i2c_data *pd); | ||
153 | }; | 154 | }; |
154 | 155 | ||
155 | #define IIC_FLAG_HAS_ICIC67 (1 << 0) | 156 | #define IIC_FLAG_HAS_ICIC67 (1 << 0) |
@@ -164,6 +165,7 @@ struct sh_mobile_dt_config { | |||
164 | #define ICIC 0x0c | 165 | #define ICIC 0x0c |
165 | #define ICCL 0x10 | 166 | #define ICCL 0x10 |
166 | #define ICCH 0x14 | 167 | #define ICCH 0x14 |
168 | #define ICSTART 0x70 | ||
167 | 169 | ||
168 | /* Register bits */ | 170 | /* Register bits */ |
169 | #define ICCR_ICE 0x80 | 171 | #define ICCR_ICE 0x80 |
@@ -190,6 +192,8 @@ struct sh_mobile_dt_config { | |||
190 | #define ICIC_WAITE 0x02 | 192 | #define ICIC_WAITE 0x02 |
191 | #define ICIC_DTEE 0x01 | 193 | #define ICIC_DTEE 0x01 |
192 | 194 | ||
195 | #define ICSTART_ICSTART 0x10 | ||
196 | |||
193 | static void iic_wr(struct sh_mobile_i2c_data *pd, int offs, unsigned char data) | 197 | static void iic_wr(struct sh_mobile_i2c_data *pd, int offs, unsigned char data) |
194 | { | 198 | { |
195 | if (offs == ICIC) | 199 | if (offs == ICIC) |
@@ -782,6 +786,33 @@ static struct i2c_algorithm sh_mobile_i2c_algorithm = { | |||
782 | .master_xfer = sh_mobile_i2c_xfer, | 786 | .master_xfer = sh_mobile_i2c_xfer, |
783 | }; | 787 | }; |
784 | 788 | ||
789 | /* | ||
790 | * r8a7740 chip has lasting errata on I2C I/O pad reset. | ||
791 | * this is work-around for it. | ||
792 | */ | ||
793 | static void sh_mobile_i2c_r8a7740_workaround(struct sh_mobile_i2c_data *pd) | ||
794 | { | ||
795 | iic_set_clr(pd, ICCR, ICCR_ICE, 0); | ||
796 | iic_rd(pd, ICCR); /* dummy read */ | ||
797 | |||
798 | iic_set_clr(pd, ICSTART, ICSTART_ICSTART, 0); | ||
799 | iic_rd(pd, ICSTART); /* dummy read */ | ||
800 | |||
801 | udelay(10); | ||
802 | |||
803 | iic_wr(pd, ICCR, ICCR_SCP); | ||
804 | iic_wr(pd, ICSTART, 0); | ||
805 | |||
806 | udelay(10); | ||
807 | |||
808 | iic_wr(pd, ICCR, ICCR_TRS); | ||
809 | udelay(10); | ||
810 | iic_wr(pd, ICCR, 0); | ||
811 | udelay(10); | ||
812 | iic_wr(pd, ICCR, ICCR_TRS); | ||
813 | udelay(10); | ||
814 | } | ||
815 | |||
785 | static const struct sh_mobile_dt_config default_dt_config = { | 816 | static const struct sh_mobile_dt_config default_dt_config = { |
786 | .clks_per_count = 1, | 817 | .clks_per_count = 1, |
787 | }; | 818 | }; |
@@ -790,9 +821,15 @@ static const struct sh_mobile_dt_config fast_clock_dt_config = { | |||
790 | .clks_per_count = 2, | 821 | .clks_per_count = 2, |
791 | }; | 822 | }; |
792 | 823 | ||
824 | static const struct sh_mobile_dt_config r8a7740_dt_config = { | ||
825 | .clks_per_count = 1, | ||
826 | .setup = sh_mobile_i2c_r8a7740_workaround, | ||
827 | }; | ||
828 | |||
793 | static const struct of_device_id sh_mobile_i2c_dt_ids[] = { | 829 | static const struct of_device_id sh_mobile_i2c_dt_ids[] = { |
794 | { .compatible = "renesas,rmobile-iic", .data = &default_dt_config }, | 830 | { .compatible = "renesas,rmobile-iic", .data = &default_dt_config }, |
795 | { .compatible = "renesas,iic-r8a73a4", .data = &fast_clock_dt_config }, | 831 | { .compatible = "renesas,iic-r8a73a4", .data = &fast_clock_dt_config }, |
832 | { .compatible = "renesas,iic-r8a7740", .data = &r8a7740_dt_config }, | ||
796 | { .compatible = "renesas,iic-r8a7790", .data = &fast_clock_dt_config }, | 833 | { .compatible = "renesas,iic-r8a7790", .data = &fast_clock_dt_config }, |
797 | { .compatible = "renesas,iic-r8a7791", .data = &fast_clock_dt_config }, | 834 | { .compatible = "renesas,iic-r8a7791", .data = &fast_clock_dt_config }, |
798 | { .compatible = "renesas,iic-r8a7792", .data = &fast_clock_dt_config }, | 835 | { .compatible = "renesas,iic-r8a7792", .data = &fast_clock_dt_config }, |
@@ -885,6 +922,9 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) | |||
885 | 922 | ||
886 | config = match->data; | 923 | config = match->data; |
887 | pd->clks_per_count = config->clks_per_count; | 924 | pd->clks_per_count = config->clks_per_count; |
925 | |||
926 | if (config->setup) | ||
927 | config->setup(pd); | ||
888 | } | 928 | } |
889 | } else { | 929 | } else { |
890 | if (pdata && pdata->bus_speed) | 930 | if (pdata && pdata->bus_speed) |