162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// Copyright 2012 Freescale Semiconductor, Inc.
462306a36Sopenharmony_ci// Copyright 2012 Linaro Ltd.
562306a36Sopenharmony_ci// Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
662306a36Sopenharmony_ci//
762306a36Sopenharmony_ci// Initial development of this code was funded by
862306a36Sopenharmony_ci// Phytec Messtechnik GmbH, https://www.phytec.de
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/clk.h>
1162306a36Sopenharmony_ci#include <linux/debugfs.h>
1262306a36Sopenharmony_ci#include <linux/err.h>
1362306a36Sopenharmony_ci#include <linux/io.h>
1462306a36Sopenharmony_ci#include <linux/module.h>
1562306a36Sopenharmony_ci#include <linux/of.h>
1662306a36Sopenharmony_ci#include <linux/of_device.h>
1762306a36Sopenharmony_ci#include <linux/platform_device.h>
1862306a36Sopenharmony_ci#include <linux/slab.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#include "imx-audmux.h"
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define DRIVER_NAME "imx-audmux"
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_cistatic struct clk *audmux_clk;
2562306a36Sopenharmony_cistatic void __iomem *audmux_base;
2662306a36Sopenharmony_cistatic u32 *regcache;
2762306a36Sopenharmony_cistatic u32 reg_max;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#define IMX_AUDMUX_V2_PTCR(x)		((x) * 8)
3062306a36Sopenharmony_ci#define IMX_AUDMUX_V2_PDCR(x)		((x) * 8 + 4)
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
3362306a36Sopenharmony_cistatic struct dentry *audmux_debugfs_root;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci/* There is an annoying discontinuity in the SSI numbering with regard
3662306a36Sopenharmony_ci * to the Linux number of the devices */
3762306a36Sopenharmony_cistatic const char *audmux_port_string(int port)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	switch (port) {
4062306a36Sopenharmony_ci	case MX31_AUDMUX_PORT1_SSI0:
4162306a36Sopenharmony_ci		return "imx-ssi.0";
4262306a36Sopenharmony_ci	case MX31_AUDMUX_PORT2_SSI1:
4362306a36Sopenharmony_ci		return "imx-ssi.1";
4462306a36Sopenharmony_ci	case MX31_AUDMUX_PORT3_SSI_PINS_3:
4562306a36Sopenharmony_ci		return "SSI3";
4662306a36Sopenharmony_ci	case MX31_AUDMUX_PORT4_SSI_PINS_4:
4762306a36Sopenharmony_ci		return "SSI4";
4862306a36Sopenharmony_ci	case MX31_AUDMUX_PORT5_SSI_PINS_5:
4962306a36Sopenharmony_ci		return "SSI5";
5062306a36Sopenharmony_ci	case MX31_AUDMUX_PORT6_SSI_PINS_6:
5162306a36Sopenharmony_ci		return "SSI6";
5262306a36Sopenharmony_ci	default:
5362306a36Sopenharmony_ci		return "UNKNOWN";
5462306a36Sopenharmony_ci	}
5562306a36Sopenharmony_ci}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistatic ssize_t audmux_read_file(struct file *file, char __user *user_buf,
5862306a36Sopenharmony_ci				size_t count, loff_t *ppos)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	ssize_t ret;
6162306a36Sopenharmony_ci	char *buf;
6262306a36Sopenharmony_ci	uintptr_t port = (uintptr_t)file->private_data;
6362306a36Sopenharmony_ci	u32 pdcr, ptcr;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	ret = clk_prepare_enable(audmux_clk);
6662306a36Sopenharmony_ci	if (ret)
6762306a36Sopenharmony_ci		return ret;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	ptcr = readl(audmux_base + IMX_AUDMUX_V2_PTCR(port));
7062306a36Sopenharmony_ci	pdcr = readl(audmux_base + IMX_AUDMUX_V2_PDCR(port));
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	clk_disable_unprepare(audmux_clk);
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
7562306a36Sopenharmony_ci	if (!buf)
7662306a36Sopenharmony_ci		return -ENOMEM;
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	ret = sysfs_emit(buf, "PDCR: %08x\nPTCR: %08x\n", pdcr, ptcr);
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	if (ptcr & IMX_AUDMUX_V2_PTCR_TFSDIR)
8162306a36Sopenharmony_ci		ret += scnprintf(buf + ret, PAGE_SIZE - ret,
8262306a36Sopenharmony_ci				"TxFS output from %s, ",
8362306a36Sopenharmony_ci				audmux_port_string((ptcr >> 27) & 0x7));
8462306a36Sopenharmony_ci	else
8562306a36Sopenharmony_ci		ret += scnprintf(buf + ret, PAGE_SIZE - ret,
8662306a36Sopenharmony_ci				"TxFS input, ");
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	if (ptcr & IMX_AUDMUX_V2_PTCR_TCLKDIR)
8962306a36Sopenharmony_ci		ret += scnprintf(buf + ret, PAGE_SIZE - ret,
9062306a36Sopenharmony_ci				"TxClk output from %s",
9162306a36Sopenharmony_ci				audmux_port_string((ptcr >> 22) & 0x7));
9262306a36Sopenharmony_ci	else
9362306a36Sopenharmony_ci		ret += scnprintf(buf + ret, PAGE_SIZE - ret,
9462306a36Sopenharmony_ci				"TxClk input");
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	if (ptcr & IMX_AUDMUX_V2_PTCR_SYN) {
9962306a36Sopenharmony_ci		ret += scnprintf(buf + ret, PAGE_SIZE - ret,
10062306a36Sopenharmony_ci				"Port is symmetric");
10162306a36Sopenharmony_ci	} else {
10262306a36Sopenharmony_ci		if (ptcr & IMX_AUDMUX_V2_PTCR_RFSDIR)
10362306a36Sopenharmony_ci			ret += scnprintf(buf + ret, PAGE_SIZE - ret,
10462306a36Sopenharmony_ci					"RxFS output from %s, ",
10562306a36Sopenharmony_ci					audmux_port_string((ptcr >> 17) & 0x7));
10662306a36Sopenharmony_ci		else
10762306a36Sopenharmony_ci			ret += scnprintf(buf + ret, PAGE_SIZE - ret,
10862306a36Sopenharmony_ci					"RxFS input, ");
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci		if (ptcr & IMX_AUDMUX_V2_PTCR_RCLKDIR)
11162306a36Sopenharmony_ci			ret += scnprintf(buf + ret, PAGE_SIZE - ret,
11262306a36Sopenharmony_ci					"RxClk output from %s",
11362306a36Sopenharmony_ci					audmux_port_string((ptcr >> 12) & 0x7));
11462306a36Sopenharmony_ci		else
11562306a36Sopenharmony_ci			ret += scnprintf(buf + ret, PAGE_SIZE - ret,
11662306a36Sopenharmony_ci					"RxClk input");
11762306a36Sopenharmony_ci	}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	ret += scnprintf(buf + ret, PAGE_SIZE - ret,
12062306a36Sopenharmony_ci			"\nData received from %s\n",
12162306a36Sopenharmony_ci			audmux_port_string((pdcr >> 13) & 0x7));
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	kfree(buf);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	return ret;
12862306a36Sopenharmony_ci}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cistatic const struct file_operations audmux_debugfs_fops = {
13162306a36Sopenharmony_ci	.open = simple_open,
13262306a36Sopenharmony_ci	.read = audmux_read_file,
13362306a36Sopenharmony_ci	.llseek = default_llseek,
13462306a36Sopenharmony_ci};
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_cistatic void audmux_debugfs_init(void)
13762306a36Sopenharmony_ci{
13862306a36Sopenharmony_ci	uintptr_t i;
13962306a36Sopenharmony_ci	char buf[20];
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	audmux_debugfs_root = debugfs_create_dir("audmux", NULL);
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	for (i = 0; i < MX31_AUDMUX_PORT7_SSI_PINS_7 + 1; i++) {
14462306a36Sopenharmony_ci		snprintf(buf, sizeof(buf), "ssi%lu", i);
14562306a36Sopenharmony_ci		debugfs_create_file(buf, 0444, audmux_debugfs_root,
14662306a36Sopenharmony_ci				    (void *)i, &audmux_debugfs_fops);
14762306a36Sopenharmony_ci	}
14862306a36Sopenharmony_ci}
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_cistatic void audmux_debugfs_remove(void)
15162306a36Sopenharmony_ci{
15262306a36Sopenharmony_ci	debugfs_remove_recursive(audmux_debugfs_root);
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci#else
15562306a36Sopenharmony_cistatic inline void audmux_debugfs_init(void)
15662306a36Sopenharmony_ci{
15762306a36Sopenharmony_ci}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_cistatic inline void audmux_debugfs_remove(void)
16062306a36Sopenharmony_ci{
16162306a36Sopenharmony_ci}
16262306a36Sopenharmony_ci#endif
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_cistatic enum imx_audmux_type {
16562306a36Sopenharmony_ci	IMX21_AUDMUX,
16662306a36Sopenharmony_ci	IMX31_AUDMUX,
16762306a36Sopenharmony_ci} audmux_type;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_cistatic const struct of_device_id imx_audmux_dt_ids[] = {
17062306a36Sopenharmony_ci	{ .compatible = "fsl,imx21-audmux", .data = (void *)IMX21_AUDMUX, },
17162306a36Sopenharmony_ci	{ .compatible = "fsl,imx31-audmux", .data = (void *)IMX31_AUDMUX, },
17262306a36Sopenharmony_ci	{ /* sentinel */ }
17362306a36Sopenharmony_ci};
17462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, imx_audmux_dt_ids);
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_cistatic const uint8_t port_mapping[] = {
17762306a36Sopenharmony_ci	0x0, 0x4, 0x8, 0x10, 0x14, 0x1c,
17862306a36Sopenharmony_ci};
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ciint imx_audmux_v1_configure_port(unsigned int port, unsigned int pcr)
18162306a36Sopenharmony_ci{
18262306a36Sopenharmony_ci	if (audmux_type != IMX21_AUDMUX)
18362306a36Sopenharmony_ci		return -EINVAL;
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	if (!audmux_base)
18662306a36Sopenharmony_ci		return -ENOSYS;
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	if (port >= ARRAY_SIZE(port_mapping))
18962306a36Sopenharmony_ci		return -EINVAL;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	writel(pcr, audmux_base + port_mapping[port]);
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	return 0;
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(imx_audmux_v1_configure_port);
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ciint imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
19862306a36Sopenharmony_ci		unsigned int pdcr)
19962306a36Sopenharmony_ci{
20062306a36Sopenharmony_ci	int ret;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	if (audmux_type != IMX31_AUDMUX)
20362306a36Sopenharmony_ci		return -EINVAL;
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	if (!audmux_base)
20662306a36Sopenharmony_ci		return -ENOSYS;
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	ret = clk_prepare_enable(audmux_clk);
20962306a36Sopenharmony_ci	if (ret)
21062306a36Sopenharmony_ci		return ret;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	writel(ptcr, audmux_base + IMX_AUDMUX_V2_PTCR(port));
21362306a36Sopenharmony_ci	writel(pdcr, audmux_base + IMX_AUDMUX_V2_PDCR(port));
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	clk_disable_unprepare(audmux_clk);
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	return 0;
21862306a36Sopenharmony_ci}
21962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_cistatic int imx_audmux_parse_dt_defaults(struct platform_device *pdev,
22262306a36Sopenharmony_ci		struct device_node *of_node)
22362306a36Sopenharmony_ci{
22462306a36Sopenharmony_ci	struct device_node *child;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	for_each_available_child_of_node(of_node, child) {
22762306a36Sopenharmony_ci		unsigned int port;
22862306a36Sopenharmony_ci		unsigned int ptcr = 0;
22962306a36Sopenharmony_ci		unsigned int pdcr = 0;
23062306a36Sopenharmony_ci		unsigned int pcr = 0;
23162306a36Sopenharmony_ci		unsigned int val;
23262306a36Sopenharmony_ci		int ret;
23362306a36Sopenharmony_ci		int i = 0;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci		ret = of_property_read_u32(child, "fsl,audmux-port", &port);
23662306a36Sopenharmony_ci		if (ret) {
23762306a36Sopenharmony_ci			dev_warn(&pdev->dev, "Failed to get fsl,audmux-port of child node \"%pOF\"\n",
23862306a36Sopenharmony_ci					child);
23962306a36Sopenharmony_ci			continue;
24062306a36Sopenharmony_ci		}
24162306a36Sopenharmony_ci		if (!of_property_read_bool(child, "fsl,port-config")) {
24262306a36Sopenharmony_ci			dev_warn(&pdev->dev, "child node \"%pOF\" does not have property fsl,port-config\n",
24362306a36Sopenharmony_ci					child);
24462306a36Sopenharmony_ci			continue;
24562306a36Sopenharmony_ci		}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci		for (i = 0; (ret = of_property_read_u32_index(child,
24862306a36Sopenharmony_ci					"fsl,port-config", i, &val)) == 0;
24962306a36Sopenharmony_ci				++i) {
25062306a36Sopenharmony_ci			if (audmux_type == IMX31_AUDMUX) {
25162306a36Sopenharmony_ci				if (i % 2)
25262306a36Sopenharmony_ci					pdcr |= val;
25362306a36Sopenharmony_ci				else
25462306a36Sopenharmony_ci					ptcr |= val;
25562306a36Sopenharmony_ci			} else {
25662306a36Sopenharmony_ci				pcr |= val;
25762306a36Sopenharmony_ci			}
25862306a36Sopenharmony_ci		}
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci		if (ret != -EOVERFLOW) {
26162306a36Sopenharmony_ci			dev_err(&pdev->dev, "Failed to read u32 at index %d of child %pOF\n",
26262306a36Sopenharmony_ci					i, child);
26362306a36Sopenharmony_ci			continue;
26462306a36Sopenharmony_ci		}
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci		if (audmux_type == IMX31_AUDMUX) {
26762306a36Sopenharmony_ci			if (i % 2) {
26862306a36Sopenharmony_ci				dev_err(&pdev->dev, "One pdcr value is missing in child node %pOF\n",
26962306a36Sopenharmony_ci						child);
27062306a36Sopenharmony_ci				continue;
27162306a36Sopenharmony_ci			}
27262306a36Sopenharmony_ci			imx_audmux_v2_configure_port(port, ptcr, pdcr);
27362306a36Sopenharmony_ci		} else {
27462306a36Sopenharmony_ci			imx_audmux_v1_configure_port(port, pcr);
27562306a36Sopenharmony_ci		}
27662306a36Sopenharmony_ci	}
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	return 0;
27962306a36Sopenharmony_ci}
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_cistatic int imx_audmux_probe(struct platform_device *pdev)
28262306a36Sopenharmony_ci{
28362306a36Sopenharmony_ci	audmux_base = devm_platform_ioremap_resource(pdev, 0);
28462306a36Sopenharmony_ci	if (IS_ERR(audmux_base))
28562306a36Sopenharmony_ci		return PTR_ERR(audmux_base);
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	audmux_clk = devm_clk_get(&pdev->dev, "audmux");
28862306a36Sopenharmony_ci	if (IS_ERR(audmux_clk)) {
28962306a36Sopenharmony_ci		dev_dbg(&pdev->dev, "cannot get clock: %ld\n",
29062306a36Sopenharmony_ci				PTR_ERR(audmux_clk));
29162306a36Sopenharmony_ci		audmux_clk = NULL;
29262306a36Sopenharmony_ci	}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	audmux_type = (uintptr_t)of_device_get_match_data(&pdev->dev);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	switch (audmux_type) {
29762306a36Sopenharmony_ci	case IMX31_AUDMUX:
29862306a36Sopenharmony_ci		audmux_debugfs_init();
29962306a36Sopenharmony_ci		reg_max = 14;
30062306a36Sopenharmony_ci		break;
30162306a36Sopenharmony_ci	case IMX21_AUDMUX:
30262306a36Sopenharmony_ci		reg_max = 6;
30362306a36Sopenharmony_ci		break;
30462306a36Sopenharmony_ci	default:
30562306a36Sopenharmony_ci		dev_err(&pdev->dev, "unsupported version!\n");
30662306a36Sopenharmony_ci		return -EINVAL;
30762306a36Sopenharmony_ci	}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	regcache = devm_kzalloc(&pdev->dev, sizeof(u32) * reg_max, GFP_KERNEL);
31062306a36Sopenharmony_ci	if (!regcache)
31162306a36Sopenharmony_ci		return -ENOMEM;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	imx_audmux_parse_dt_defaults(pdev, pdev->dev.of_node);
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	return 0;
31662306a36Sopenharmony_ci}
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_cistatic void imx_audmux_remove(struct platform_device *pdev)
31962306a36Sopenharmony_ci{
32062306a36Sopenharmony_ci	if (audmux_type == IMX31_AUDMUX)
32162306a36Sopenharmony_ci		audmux_debugfs_remove();
32262306a36Sopenharmony_ci}
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
32562306a36Sopenharmony_cistatic int imx_audmux_suspend(struct device *dev)
32662306a36Sopenharmony_ci{
32762306a36Sopenharmony_ci	int i;
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	clk_prepare_enable(audmux_clk);
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	for (i = 0; i < reg_max; i++)
33262306a36Sopenharmony_ci		regcache[i] = readl(audmux_base + i * 4);
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	clk_disable_unprepare(audmux_clk);
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	return 0;
33762306a36Sopenharmony_ci}
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_cistatic int imx_audmux_resume(struct device *dev)
34062306a36Sopenharmony_ci{
34162306a36Sopenharmony_ci	int i;
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	clk_prepare_enable(audmux_clk);
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	for (i = 0; i < reg_max; i++)
34662306a36Sopenharmony_ci		writel(regcache[i], audmux_base + i * 4);
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	clk_disable_unprepare(audmux_clk);
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	return 0;
35162306a36Sopenharmony_ci}
35262306a36Sopenharmony_ci#endif /* CONFIG_PM_SLEEP */
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_cistatic const struct dev_pm_ops imx_audmux_pm = {
35562306a36Sopenharmony_ci	SET_SYSTEM_SLEEP_PM_OPS(imx_audmux_suspend, imx_audmux_resume)
35662306a36Sopenharmony_ci};
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_cistatic struct platform_driver imx_audmux_driver = {
35962306a36Sopenharmony_ci	.probe		= imx_audmux_probe,
36062306a36Sopenharmony_ci	.remove_new	= imx_audmux_remove,
36162306a36Sopenharmony_ci	.driver	= {
36262306a36Sopenharmony_ci		.name	= DRIVER_NAME,
36362306a36Sopenharmony_ci		.pm = &imx_audmux_pm,
36462306a36Sopenharmony_ci		.of_match_table = imx_audmux_dt_ids,
36562306a36Sopenharmony_ci	}
36662306a36Sopenharmony_ci};
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_cistatic int __init imx_audmux_init(void)
36962306a36Sopenharmony_ci{
37062306a36Sopenharmony_ci	return platform_driver_register(&imx_audmux_driver);
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_cisubsys_initcall(imx_audmux_init);
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_cistatic void __exit imx_audmux_exit(void)
37562306a36Sopenharmony_ci{
37662306a36Sopenharmony_ci	platform_driver_unregister(&imx_audmux_driver);
37762306a36Sopenharmony_ci}
37862306a36Sopenharmony_cimodule_exit(imx_audmux_exit);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ciMODULE_DESCRIPTION("Freescale i.MX AUDMUX driver");
38162306a36Sopenharmony_ciMODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
38262306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
38362306a36Sopenharmony_ciMODULE_ALIAS("platform:" DRIVER_NAME);
384