diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-s3c2410.c')
-rw-r--r-- | drivers/i2c/busses/i2c-s3c2410.c | 75 |
1 files changed, 34 insertions, 41 deletions
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 85e3664f411e..23736ffaaa2a 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c | |||
@@ -44,8 +44,10 @@ | |||
44 | #include <plat/regs-iic.h> | 44 | #include <plat/regs-iic.h> |
45 | #include <plat/iic.h> | 45 | #include <plat/iic.h> |
46 | 46 | ||
47 | /* i2c controller state */ | 47 | /* Treat S3C2410 as baseline hardware, anything else is supported via quirks */ |
48 | #define QUIRK_S3C2440 (1 << 0) | ||
48 | 49 | ||
50 | /* i2c controller state */ | ||
49 | enum s3c24xx_i2c_state { | 51 | enum s3c24xx_i2c_state { |
50 | STATE_IDLE, | 52 | STATE_IDLE, |
51 | STATE_START, | 53 | STATE_START, |
@@ -54,14 +56,10 @@ enum s3c24xx_i2c_state { | |||
54 | STATE_STOP | 56 | STATE_STOP |
55 | }; | 57 | }; |
56 | 58 | ||
57 | enum s3c24xx_i2c_type { | ||
58 | TYPE_S3C2410, | ||
59 | TYPE_S3C2440, | ||
60 | }; | ||
61 | |||
62 | struct s3c24xx_i2c { | 59 | struct s3c24xx_i2c { |
63 | spinlock_t lock; | 60 | spinlock_t lock; |
64 | wait_queue_head_t wait; | 61 | wait_queue_head_t wait; |
62 | unsigned int quirks; | ||
65 | unsigned int suspended:1; | 63 | unsigned int suspended:1; |
66 | 64 | ||
67 | struct i2c_msg *msg; | 65 | struct i2c_msg *msg; |
@@ -88,26 +86,40 @@ struct s3c24xx_i2c { | |||
88 | #endif | 86 | #endif |
89 | }; | 87 | }; |
90 | 88 | ||
91 | /* default platform data removed, dev should always carry data. */ | 89 | static struct platform_device_id s3c24xx_driver_ids[] = { |
90 | { | ||
91 | .name = "s3c2410-i2c", | ||
92 | .driver_data = 0, | ||
93 | }, { | ||
94 | .name = "s3c2440-i2c", | ||
95 | .driver_data = QUIRK_S3C2440, | ||
96 | }, { }, | ||
97 | }; | ||
98 | MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids); | ||
99 | |||
100 | #ifdef CONFIG_OF | ||
101 | static const struct of_device_id s3c24xx_i2c_match[] = { | ||
102 | { .compatible = "samsung,s3c2410-i2c", .data = (void *)0 }, | ||
103 | { .compatible = "samsung,s3c2440-i2c", .data = (void *)QUIRK_S3C2440 }, | ||
104 | {}, | ||
105 | }; | ||
106 | MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match); | ||
107 | #endif | ||
92 | 108 | ||
93 | /* s3c24xx_i2c_is2440() | 109 | /* s3c24xx_get_device_quirks |
94 | * | 110 | * |
95 | * return true is this is an s3c2440 | 111 | * Get controller type either from device tree or platform device variant. |
96 | */ | 112 | */ |
97 | 113 | ||
98 | static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *i2c) | 114 | static inline unsigned int s3c24xx_get_device_quirks(struct platform_device *pdev) |
99 | { | 115 | { |
100 | struct platform_device *pdev = to_platform_device(i2c->dev); | 116 | if (pdev->dev.of_node) { |
101 | enum s3c24xx_i2c_type type; | 117 | const struct of_device_id *match; |
102 | 118 | match = of_match_node(&s3c24xx_i2c_match, pdev->dev.of_node); | |
103 | #ifdef CONFIG_OF | 119 | return (unsigned int)match->data; |
104 | if (i2c->dev->of_node) | 120 | } |
105 | return of_device_is_compatible(i2c->dev->of_node, | ||
106 | "samsung,s3c2440-i2c"); | ||
107 | #endif | ||
108 | 121 | ||
109 | type = platform_get_device_id(pdev)->driver_data; | 122 | return platform_get_device_id(pdev)->driver_data; |
110 | return type == TYPE_S3C2440; | ||
111 | } | 123 | } |
112 | 124 | ||
113 | /* s3c24xx_i2c_master_complete | 125 | /* s3c24xx_i2c_master_complete |
@@ -676,7 +688,7 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) | |||
676 | 688 | ||
677 | writel(iiccon, i2c->regs + S3C2410_IICCON); | 689 | writel(iiccon, i2c->regs + S3C2410_IICCON); |
678 | 690 | ||
679 | if (s3c24xx_i2c_is2440(i2c)) { | 691 | if (i2c->quirks & QUIRK_S3C2440) { |
680 | unsigned long sda_delay; | 692 | unsigned long sda_delay; |
681 | 693 | ||
682 | if (pdata->sda_delay) { | 694 | if (pdata->sda_delay) { |
@@ -906,6 +918,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) | |||
906 | goto err_noclk; | 918 | goto err_noclk; |
907 | } | 919 | } |
908 | 920 | ||
921 | i2c->quirks = s3c24xx_get_device_quirks(pdev); | ||
909 | if (pdata) | 922 | if (pdata) |
910 | memcpy(i2c->pdata, pdata, sizeof(*pdata)); | 923 | memcpy(i2c->pdata, pdata, sizeof(*pdata)); |
911 | else | 924 | else |
@@ -1110,26 +1123,6 @@ static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = { | |||
1110 | 1123 | ||
1111 | /* device driver for platform bus bits */ | 1124 | /* device driver for platform bus bits */ |
1112 | 1125 | ||
1113 | static struct platform_device_id s3c24xx_driver_ids[] = { | ||
1114 | { | ||
1115 | .name = "s3c2410-i2c", | ||
1116 | .driver_data = TYPE_S3C2410, | ||
1117 | }, { | ||
1118 | .name = "s3c2440-i2c", | ||
1119 | .driver_data = TYPE_S3C2440, | ||
1120 | }, { }, | ||
1121 | }; | ||
1122 | MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids); | ||
1123 | |||
1124 | #ifdef CONFIG_OF | ||
1125 | static const struct of_device_id s3c24xx_i2c_match[] = { | ||
1126 | { .compatible = "samsung,s3c2410-i2c" }, | ||
1127 | { .compatible = "samsung,s3c2440-i2c" }, | ||
1128 | {}, | ||
1129 | }; | ||
1130 | MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match); | ||
1131 | #endif | ||
1132 | |||
1133 | static struct platform_driver s3c24xx_i2c_driver = { | 1126 | static struct platform_driver s3c24xx_i2c_driver = { |
1134 | .probe = s3c24xx_i2c_probe, | 1127 | .probe = s3c24xx_i2c_probe, |
1135 | .remove = s3c24xx_i2c_remove, | 1128 | .remove = s3c24xx_i2c_remove, |