diff options
author | Vitaly Wool <vitalywool@gmail.com> | 2006-12-10 15:21:29 -0500 |
---|---|---|
committer | Jean Delvare <khali@arrakis.delvare> | 2006-12-10 15:21:29 -0500 |
commit | 41561f28e76a47dc6de0a954da85d0b5c42874eb (patch) | |
tree | 0113700403e5fffb57ee41b564ea68bcaab311d9 /arch/arm/mach-pnx4008/i2c.c | |
parent | 51fd554b6547b74c7e6d1f52885ba8532b531023 (diff) |
i2c: New Philips PNX bus driver
New I2C bus driver for Philips ARM boards (Philips IP3204 I2C IP
block). This I2C controller can be found on (at least) PNX010x,
PNX52xx and PNX4008 Philips boards.
Signed-off-by: Vitaly Wool <vitalywool@gmail.com>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'arch/arm/mach-pnx4008/i2c.c')
-rw-r--r-- | arch/arm/mach-pnx4008/i2c.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/arch/arm/mach-pnx4008/i2c.c b/arch/arm/mach-pnx4008/i2c.c new file mode 100644 index 000000000000..6f308827c4fe --- /dev/null +++ b/arch/arm/mach-pnx4008/i2c.c | |||
@@ -0,0 +1,167 @@ | |||
1 | /* | ||
2 | * I2C initialization for PNX4008. | ||
3 | * | ||
4 | * Author: Vitaly Wool <vitalywool@gmail.com> | ||
5 | * | ||
6 | * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/i2c-pnx.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <asm/arch/platform.h> | ||
18 | #include <asm/arch/i2c.h> | ||
19 | |||
20 | static int set_clock_run(struct platform_device *pdev) | ||
21 | { | ||
22 | struct clk *clk; | ||
23 | char name[10]; | ||
24 | int retval = 0; | ||
25 | |||
26 | snprintf(name, 10, "i2c%d_ck", pdev->id); | ||
27 | clk = clk_get(&pdev->dev, name); | ||
28 | if (!IS_ERR(clk)) { | ||
29 | clk_set_rate(clk, 1); | ||
30 | clk_put(clk); | ||
31 | } else | ||
32 | retval = -ENOENT; | ||
33 | |||
34 | return retval; | ||
35 | } | ||
36 | |||
37 | static int set_clock_stop(struct platform_device *pdev) | ||
38 | { | ||
39 | struct clk *clk; | ||
40 | char name[10]; | ||
41 | int retval = 0; | ||
42 | |||
43 | snprintf(name, 10, "i2c%d_ck", pdev->id); | ||
44 | clk = clk_get(&pdev->dev, name); | ||
45 | if (!IS_ERR(clk)) { | ||
46 | clk_set_rate(clk, 0); | ||
47 | clk_put(clk); | ||
48 | } else | ||
49 | retval = -ENOENT; | ||
50 | |||
51 | return retval; | ||
52 | } | ||
53 | |||
54 | static int i2c_pnx_suspend(struct platform_device *pdev, pm_message_t state) | ||
55 | { | ||
56 | int retval = 0; | ||
57 | #ifdef CONFIG_PM | ||
58 | retval = set_clock_run(pdev); | ||
59 | #endif | ||
60 | return retval; | ||
61 | } | ||
62 | |||
63 | static int i2c_pnx_resume(struct platform_device *pdev) | ||
64 | { | ||
65 | int retval = 0; | ||
66 | #ifdef CONFIG_PM | ||
67 | retval = set_clock_run(pdev); | ||
68 | #endif | ||
69 | return retval; | ||
70 | } | ||
71 | |||
72 | static u32 calculate_input_freq(struct platform_device *pdev) | ||
73 | { | ||
74 | return HCLK_MHZ; | ||
75 | } | ||
76 | |||
77 | |||
78 | static struct i2c_pnx_algo_data pnx_algo_data0 = { | ||
79 | .base = PNX4008_I2C1_BASE, | ||
80 | .irq = I2C_1_INT, | ||
81 | }; | ||
82 | |||
83 | static struct i2c_pnx_algo_data pnx_algo_data1 = { | ||
84 | .base = PNX4008_I2C2_BASE, | ||
85 | .irq = I2C_2_INT, | ||
86 | }; | ||
87 | |||
88 | static struct i2c_pnx_algo_data pnx_algo_data2 = { | ||
89 | .base = (PNX4008_USB_CONFIG_BASE + 0x300), | ||
90 | .irq = USB_I2C_INT, | ||
91 | }; | ||
92 | |||
93 | static struct i2c_adapter pnx_adapter0 = { | ||
94 | .name = I2C_CHIP_NAME "0", | ||
95 | .algo_data = &pnx_algo_data0, | ||
96 | }; | ||
97 | static struct i2c_adapter pnx_adapter1 = { | ||
98 | .name = I2C_CHIP_NAME "1", | ||
99 | .algo_data = &pnx_algo_data1, | ||
100 | }; | ||
101 | |||
102 | static struct i2c_adapter pnx_adapter2 = { | ||
103 | .name = "USB-I2C", | ||
104 | .algo_data = &pnx_algo_data2, | ||
105 | }; | ||
106 | |||
107 | static struct i2c_pnx_data i2c0_data = { | ||
108 | .suspend = i2c_pnx_suspend, | ||
109 | .resume = i2c_pnx_resume, | ||
110 | .calculate_input_freq = calculate_input_freq, | ||
111 | .set_clock_run = set_clock_run, | ||
112 | .set_clock_stop = set_clock_stop, | ||
113 | .adapter = &pnx_adapter0, | ||
114 | }; | ||
115 | |||
116 | static struct i2c_pnx_data i2c1_data = { | ||
117 | .suspend = i2c_pnx_suspend, | ||
118 | .resume = i2c_pnx_resume, | ||
119 | .calculate_input_freq = calculate_input_freq, | ||
120 | .set_clock_run = set_clock_run, | ||
121 | .set_clock_stop = set_clock_stop, | ||
122 | .adapter = &pnx_adapter1, | ||
123 | }; | ||
124 | |||
125 | static struct i2c_pnx_data i2c2_data = { | ||
126 | .suspend = i2c_pnx_suspend, | ||
127 | .resume = i2c_pnx_resume, | ||
128 | .calculate_input_freq = calculate_input_freq, | ||
129 | .set_clock_run = set_clock_run, | ||
130 | .set_clock_stop = set_clock_stop, | ||
131 | .adapter = &pnx_adapter2, | ||
132 | }; | ||
133 | |||
134 | static struct platform_device i2c0_device = { | ||
135 | .name = "pnx-i2c", | ||
136 | .id = 0, | ||
137 | .dev = { | ||
138 | .platform_data = &i2c0_data, | ||
139 | }, | ||
140 | }; | ||
141 | |||
142 | static struct platform_device i2c1_device = { | ||
143 | .name = "pnx-i2c", | ||
144 | .id = 1, | ||
145 | .dev = { | ||
146 | .platform_data = &i2c1_data, | ||
147 | }, | ||
148 | }; | ||
149 | |||
150 | static struct platform_device i2c2_device = { | ||
151 | .name = "pnx-i2c", | ||
152 | .id = 2, | ||
153 | .dev = { | ||
154 | .platform_data = &i2c2_data, | ||
155 | }, | ||
156 | }; | ||
157 | |||
158 | static struct platform_device *devices[] __initdata = { | ||
159 | &i2c0_device, | ||
160 | &i2c1_device, | ||
161 | &i2c2_device, | ||
162 | }; | ||
163 | |||
164 | void __init pnx4008_register_i2c_devices(void) | ||
165 | { | ||
166 | platform_add_devices(devices, ARRAY_SIZE(devices)); | ||
167 | } | ||