diff options
Diffstat (limited to 'arch/arm/plat-mxc/audmux.c')
-rw-r--r-- | arch/arm/plat-mxc/audmux.c | 127 |
1 files changed, 92 insertions, 35 deletions
diff --git a/arch/arm/plat-mxc/audmux.c b/arch/arm/plat-mxc/audmux.c index b49a39ff99da..a8c9e04771bf 100644 --- a/arch/arm/plat-mxc/audmux.c +++ b/arch/arm/plat-mxc/audmux.c | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * Copyright 2012 Linaro Ltd. | ||
2 | * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> | 4 | * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> |
3 | * | 5 | * |
4 | * Initial development of this code was funded by | 6 | * Initial development of this code was funded by |
@@ -15,14 +17,16 @@ | |||
15 | * GNU General Public License for more details. | 17 | * GNU General Public License for more details. |
16 | */ | 18 | */ |
17 | 19 | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/io.h> | ||
21 | #include <linux/clk.h> | 20 | #include <linux/clk.h> |
22 | #include <linux/debugfs.h> | 21 | #include <linux/debugfs.h> |
22 | #include <linux/err.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/platform_device.h> | ||
23 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
24 | #include <mach/audmux.h> | 27 | #include <mach/audmux.h> |
25 | #include <mach/hardware.h> | 28 | |
29 | #define DRIVER_NAME "imx-audmux" | ||
26 | 30 | ||
27 | static struct clk *audmux_clk; | 31 | static struct clk *audmux_clk; |
28 | static void __iomem *audmux_base; | 32 | static void __iomem *audmux_base; |
@@ -140,7 +144,7 @@ static const struct file_operations audmux_debugfs_fops = { | |||
140 | .llseek = default_llseek, | 144 | .llseek = default_llseek, |
141 | }; | 145 | }; |
142 | 146 | ||
143 | static void audmux_debugfs_init(void) | 147 | static void __init audmux_debugfs_init(void) |
144 | { | 148 | { |
145 | int i; | 149 | int i; |
146 | char buf[20]; | 150 | char buf[20]; |
@@ -159,18 +163,48 @@ static void audmux_debugfs_init(void) | |||
159 | i); | 163 | i); |
160 | } | 164 | } |
161 | } | 165 | } |
166 | |||
167 | static void __exit audmux_debugfs_remove(void) | ||
168 | { | ||
169 | debugfs_remove_recursive(audmux_debugfs_root); | ||
170 | } | ||
162 | #else | 171 | #else |
163 | static inline void audmux_debugfs_init(void) | 172 | static inline void audmux_debugfs_init(void) |
164 | { | 173 | { |
165 | } | 174 | } |
175 | |||
176 | static inline void audmux_debugfs_remove(void) | ||
177 | { | ||
178 | } | ||
166 | #endif | 179 | #endif |
167 | 180 | ||
181 | enum imx_audmux_type { | ||
182 | IMX21_AUDMUX, | ||
183 | IMX31_AUDMUX, | ||
184 | } audmux_type; | ||
185 | |||
186 | static struct platform_device_id imx_audmux_ids[] = { | ||
187 | { | ||
188 | .name = "imx21-audmux", | ||
189 | .driver_data = IMX21_AUDMUX, | ||
190 | }, { | ||
191 | .name = "imx31-audmux", | ||
192 | .driver_data = IMX31_AUDMUX, | ||
193 | }, { | ||
194 | /* sentinel */ | ||
195 | } | ||
196 | }; | ||
197 | MODULE_DEVICE_TABLE(platform, imx_audmux_ids); | ||
198 | |||
168 | static const uint8_t port_mapping[] = { | 199 | static const uint8_t port_mapping[] = { |
169 | 0x0, 0x4, 0x8, 0x10, 0x14, 0x1c, | 200 | 0x0, 0x4, 0x8, 0x10, 0x14, 0x1c, |
170 | }; | 201 | }; |
171 | 202 | ||
172 | int mxc_audmux_v1_configure_port(unsigned int port, unsigned int pcr) | 203 | int mxc_audmux_v1_configure_port(unsigned int port, unsigned int pcr) |
173 | { | 204 | { |
205 | if (audmux_type != IMX21_AUDMUX) | ||
206 | return -EINVAL; | ||
207 | |||
174 | if (!audmux_base) | 208 | if (!audmux_base) |
175 | return -ENOSYS; | 209 | return -ENOSYS; |
176 | 210 | ||
@@ -186,6 +220,9 @@ EXPORT_SYMBOL_GPL(mxc_audmux_v1_configure_port); | |||
186 | int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, | 220 | int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, |
187 | unsigned int pdcr) | 221 | unsigned int pdcr) |
188 | { | 222 | { |
223 | if (audmux_type != IMX31_AUDMUX) | ||
224 | return -EINVAL; | ||
225 | |||
189 | if (!audmux_base) | 226 | if (!audmux_base) |
190 | return -ENOSYS; | 227 | return -ENOSYS; |
191 | 228 | ||
@@ -202,41 +239,61 @@ int mxc_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, | |||
202 | } | 239 | } |
203 | EXPORT_SYMBOL_GPL(mxc_audmux_v2_configure_port); | 240 | EXPORT_SYMBOL_GPL(mxc_audmux_v2_configure_port); |
204 | 241 | ||
205 | static int mxc_audmux_init(void) | 242 | static int __init imx_audmux_probe(struct platform_device *pdev) |
206 | { | 243 | { |
207 | int ret; | 244 | struct resource *res; |
208 | if (cpu_is_mx51()) { | 245 | |
209 | audmux_base = MX51_IO_ADDRESS(MX51_AUDMUX_BASE_ADDR); | 246 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
210 | } else if (cpu_is_mx31()) { | 247 | audmux_base = devm_request_and_ioremap(&pdev->dev, res); |
211 | audmux_base = MX31_IO_ADDRESS(MX31_AUDMUX_BASE_ADDR); | 248 | if (!audmux_base) |
212 | } else if (cpu_is_mx35()) { | 249 | return -EADDRNOTAVAIL; |
213 | audmux_clk = clk_get(NULL, "audmux"); | 250 | |
214 | if (IS_ERR(audmux_clk)) { | 251 | audmux_clk = clk_get(&pdev->dev, "audmux"); |
215 | ret = PTR_ERR(audmux_clk); | 252 | if (IS_ERR(audmux_clk)) { |
216 | printk(KERN_ERR "%s: cannot get clock: %d\n", __func__, | 253 | dev_dbg(&pdev->dev, "cannot get clock: %ld\n", |
217 | ret); | 254 | PTR_ERR(audmux_clk)); |
218 | return ret; | 255 | audmux_clk = NULL; |
219 | } | ||
220 | audmux_base = MX35_IO_ADDRESS(MX35_AUDMUX_BASE_ADDR); | ||
221 | } else if (cpu_is_mx25()) { | ||
222 | audmux_clk = clk_get(NULL, "audmux"); | ||
223 | if (IS_ERR(audmux_clk)) { | ||
224 | ret = PTR_ERR(audmux_clk); | ||
225 | printk(KERN_ERR "%s: cannot get clock: %d\n", __func__, | ||
226 | ret); | ||
227 | return ret; | ||
228 | } | ||
229 | audmux_base = MX25_IO_ADDRESS(MX25_AUDMUX_BASE_ADDR); | ||
230 | } else if (cpu_is_mx27()) { | ||
231 | audmux_base = MX27_IO_ADDRESS(MX27_AUDMUX_BASE_ADDR); | ||
232 | } else if (cpu_is_mx21()) { | ||
233 | audmux_base = MX21_IO_ADDRESS(MX21_AUDMUX_BASE_ADDR); | ||
234 | } | 256 | } |
235 | 257 | ||
236 | if (!cpu_is_mx2()) | 258 | audmux_type = pdev->id_entry->driver_data; |
259 | if (audmux_type == IMX31_AUDMUX) | ||
237 | audmux_debugfs_init(); | 260 | audmux_debugfs_init(); |
238 | 261 | ||
239 | return 0; | 262 | return 0; |
240 | } | 263 | } |
241 | 264 | ||
242 | postcore_initcall(mxc_audmux_init); | 265 | static int __exit imx_audmux_remove(struct platform_device *pdev) |
266 | { | ||
267 | if (audmux_type == IMX31_AUDMUX) | ||
268 | audmux_debugfs_remove(); | ||
269 | clk_put(audmux_clk); | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static struct platform_driver imx_audmux_driver = { | ||
275 | .probe = imx_audmux_probe, | ||
276 | .remove = __exit_p(imx_audmux_remove), | ||
277 | .id_table = imx_audmux_ids, | ||
278 | .driver = { | ||
279 | .name = DRIVER_NAME, | ||
280 | .owner = THIS_MODULE, | ||
281 | } | ||
282 | }; | ||
283 | |||
284 | static int __init imx_audmux_init(void) | ||
285 | { | ||
286 | return platform_driver_register(&imx_audmux_driver); | ||
287 | } | ||
288 | subsys_initcall(imx_audmux_init); | ||
289 | |||
290 | static void __exit imx_audmux_exit(void) | ||
291 | { | ||
292 | platform_driver_unregister(&imx_audmux_driver); | ||
293 | } | ||
294 | module_exit(imx_audmux_exit); | ||
295 | |||
296 | MODULE_DESCRIPTION("Freescale i.MX AUDMUX driver"); | ||
297 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); | ||
298 | MODULE_LICENSE("GPL v2"); | ||
299 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||