Initial Contribution
msm-2.6.38: tag AU_LINUX_ANDROID_GINGERBREAD.02.03.04.00.142
Signed-off-by: Bryan Huntsman <bryanh@codeaurora.org>
diff --git a/drivers/mfd/marimba-tsadc.c b/drivers/mfd/marimba-tsadc.c
new file mode 100644
index 0000000..8a7b781
--- /dev/null
+++ b/drivers/mfd/marimba-tsadc.c
@@ -0,0 +1,696 @@
+/*
+ * Marimba TSADC driver.
+ *
+ * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/mfd/marimba.h>
+#include <linux/mfd/marimba-tsadc.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#endif
+
+/* marimba configuration block: TS_CTL0 */
+#define TS_CTL0 0xFF
+#define TS_CTL0_RESET BIT(0)
+#define TS_CTL0_CLK_EN BIT(1)
+#define TS_CTL0_XO_EN BIT(2)
+#define TS_CTL0_EOC_EN BIT(3)
+#define TS_CTL0_PENIRQ_EN BIT(4)
+
+/* TSADC registers */
+#define SSBI_PRESET 0x00
+#define TSHK_DIG_CONFIG 0x4F
+#define TSHK_INTF_CONFIG 0x50
+#define TSHK_SETUP 0x51
+ #define TSHK_SETUP_EN_ADC BIT(0)
+ #define TSHK_SETUP_EN_PIRQ BIT(7)
+#define TSHK_PARAM 0x52
+#define TSHK_DATA_RD 0x53
+#define TSHK_STATUS 0x54
+#define TSHK_SETUP2 0x55
+#define TSHK_RSV1 0x56
+ #define TSHK_RSV1_PRECHARGE_EN BIT(0)
+#define TSHK_COMMAND 0x57
+#define TSHK_PARAM2 0x58
+ #define TSHK_INPUT_CLK_MASK 0x3F
+ #define TSHK_SAMPLE_PRD_MASK 0xC7
+ #define TSHK_INPUT_CLK_SHIFT 0x6
+ #define TSHK_SAMPLE_PRD_SHIFT 0x3
+#define TSHK_PARAM3 0x59
+ #define TSHK_PARAM3_MODE_MASK 0xFC
+ #define TSHK_PARAM3_PRE_CHG_SHIFT (5)
+ #define TSHK_PARAM3_STABIZ_SHIFT (2)
+ #define TSHK_STABLE_TIME_MASK 0xE3
+ #define TSHK_PRECHG_TIME_MASK 0x1F
+#define TSHK_PARAM4 0x5A
+#define TSHK_RSV2 0x5B
+#define TSHK_RSV3 0x5C
+#define TSHK_RSV4 0x5D
+#define TSHK_RSV5 0x5E
+
+struct marimba_tsadc_client {
+ unsigned int is_ts;
+ struct platform_device *pdev;
+};
+
+struct marimba_tsadc {
+ struct marimba *marimba;
+ struct device *dev;
+ struct marimba_tsadc_platform_data *pdata;
+ struct clk *codec_ssbi;
+ struct device *child_tssc;
+ bool clk_enabled;
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ struct early_suspend early_suspend;
+#endif
+};
+
+static struct marimba_tsadc *tsadc_dev;
+
+static int marimba_write_u8(struct marimba_tsadc *tsadc, u8 reg, u8 data)
+{
+ int rc;
+
+ tsadc->marimba->mod_id = MARIMBA_SLAVE_ID_MARIMBA;
+ rc = marimba_write(tsadc->marimba, reg, &data, 1);
+
+ if (!rc)
+ dev_warn(tsadc->dev, "Error writing marimba reg %X - ret %X\n",
+ reg, data);
+ return 0;
+}
+
+static int marimba_tsadc_write(struct marimba_tsadc *tsadc, u8 reg, u8 data)
+{
+ int rc;
+
+ tsadc->marimba->mod_id = MARIMBA_ID_TSADC;
+
+ rc = marimba_ssbi_write(tsadc->marimba, reg, &data, 1);
+ if (!rc)
+ dev_warn(tsadc->dev, "Error writing marimba reg %X - ret %X\n",
+ reg, data);
+ return rc;
+}
+
+static int marimba_tsadc_shutdown(struct marimba_tsadc *tsadc)
+{
+ u8 val;
+ int rc;
+
+ /* force reset */
+ val = TS_CTL0_XO_EN | TS_CTL0_EOC_EN | TS_CTL0_PENIRQ_EN |
+ TS_CTL0_CLK_EN;
+ rc = marimba_write_u8(tsadc, TS_CTL0, val);
+ if (rc < 0)
+ return rc;
+
+ /* disable xo, clock */
+ val = TS_CTL0_PENIRQ_EN | TS_CTL0_EOC_EN;
+ rc = marimba_write_u8(tsadc, TS_CTL0, val);
+ if (rc < 0)
+ return rc;
+
+ /* de-vote S2 1.3v */
+ if (tsadc->pdata->level_vote)
+ /* REVISIT: Ignore error for level_vote(0) for now*/
+ tsadc->pdata->level_vote(0);
+
+ return 0;
+}
+
+static int marimba_tsadc_startup(struct marimba_tsadc *tsadc)
+{
+ u8 val;
+ int rc = 0;
+
+ /* vote for S2 1.3v */
+ if (tsadc->pdata->level_vote) {
+ rc = tsadc->pdata->level_vote(1);
+ if (rc < 0)
+ return rc;
+ }
+
+ /* disable XO, clock and output enables */
+ rc = marimba_write_u8(tsadc, TS_CTL0, 0x00);
+ if (rc < 0)
+ goto fail_marimba_write;
+
+ /* Enable output enables */
+ val = TS_CTL0_XO_EN | TS_CTL0_EOC_EN | TS_CTL0_PENIRQ_EN;
+ rc = marimba_write_u8(tsadc, TS_CTL0, val);
+ if (rc < 0)
+ goto fail_marimba_write;
+
+ /* Enable clock */
+ val = val | TS_CTL0_CLK_EN;
+ rc = marimba_write_u8(tsadc, TS_CTL0, val);
+ if (rc < 0)
+ goto fail_marimba_write;
+
+ /* remove reset */
+ val = val | TS_CTL0_RESET;
+ rc = marimba_write_u8(tsadc, TS_CTL0, val);
+ if (rc < 0)
+ goto fail_marimba_write;
+
+ return 0;
+
+fail_marimba_write:
+ if (tsadc->pdata->level_vote)
+ /* REVISIT: Ignore error for level_vote(0) for now*/
+ tsadc->pdata->level_vote(0);
+ return rc;
+}
+
+
+static int marimba_tsadc_configure(struct marimba_tsadc *tsadc)
+{
+ u8 rsv1 = 0, setup = 0, i, count = 0;
+ u8 param2 = 0, param3 = 0;
+ unsigned long val;
+ int rc;
+
+ rc = marimba_tsadc_write(tsadc, SSBI_PRESET, 0x00);
+ if (rc < 0)
+ return rc;
+
+ if (!tsadc->pdata)
+ return -EINVAL;
+
+ /* Configure RSV1 register*/
+ if (tsadc->pdata->tsadc_prechg_en == true)
+ rsv1 |= TSHK_RSV1_PRECHARGE_EN;
+ else
+ rsv1 &= ~TSHK_RSV1_PRECHARGE_EN;
+
+ /* Set RSV1 register*/
+ rc = marimba_tsadc_write(tsadc, TSHK_RSV1, rsv1);
+ if (rc < 0)
+ return rc;
+
+ /* Configure PARAM2 register */
+ /* Input clk */
+ val = tsadc->pdata->params2.input_clk_khz;
+ param2 &= TSHK_INPUT_CLK_MASK;
+ val /= 600;
+ if (val >= 1 && val <= 8 && !(val & (val - 1))) {
+ /* Input clk can be .6, 1.2, 2.4, 4.8Mhz */
+ if (val % 4 != 0)
+ param2 = (4 - (val % 4)) << TSHK_INPUT_CLK_SHIFT;
+ else
+ param2 = ((val / 4) - 1) << TSHK_INPUT_CLK_SHIFT;
+ } else /* Configure the default clk 2.4Mhz */
+ param2 = 0x00 << TSHK_INPUT_CLK_SHIFT;
+
+ /* Sample period */
+ param2 &= TSHK_SAMPLE_PRD_MASK;
+ param2 |= tsadc->pdata->params2.sample_prd << TSHK_SAMPLE_PRD_SHIFT;
+
+ /* Write PARAM2 register */
+ rc = marimba_tsadc_write(tsadc, TSHK_PARAM2, param2);
+ if (rc < 0)
+ return rc;
+
+ /* REVISIT: If Precharge time, stabilization time > 409.6us */
+ /* Configure PARAM3 register */
+ val = tsadc->pdata->params3.prechg_time_nsecs;
+ param3 &= TSHK_PRECHG_TIME_MASK;
+ val /= 6400;
+ if (val >= 1 && val <= 64 && !(val & (val - 1))) {
+ count = 0;
+ while ((val = val >> 1) != 0)
+ count++;
+ param3 |= count << TSHK_PARAM3_PRE_CHG_SHIFT;
+ } else /* Set default value if the input is wrong */
+ param3 |= 0x00 << TSHK_PARAM3_PRE_CHG_SHIFT;
+
+ val = tsadc->pdata->params3.stable_time_nsecs;
+ param3 &= TSHK_STABLE_TIME_MASK;
+ val /= 6400;
+ if (val >= 1 && val <= 64 && !(val & (val - 1))) {
+ count = 0;
+ while ((val = val >> 1) != 0)
+ count++;
+ param3 |= count << TSHK_PARAM3_STABIZ_SHIFT;
+ } else /* Set default value if the input is wrong */
+ param3 |= 0x00 << TSHK_PARAM3_STABIZ_SHIFT;
+
+ /* Get TSADC mode */
+ val = tsadc->pdata->params3.tsadc_test_mode;
+ param3 &= TSHK_PARAM3_MODE_MASK;
+ if (val == 0)
+ param3 |= 0x00;
+ else
+ for (i = 0; i < 3 ; i++) {
+ if (((val + i) % 39322) == 0) {
+ param3 |= (i + 1);
+ break;
+ }
+ }
+ if (i == 3) /* Set to normal mode if input is wrong */
+ param3 |= 0x00;
+
+ rc = marimba_tsadc_write(tsadc, TSHK_PARAM3, param3);
+ if (rc < 0)
+ return rc;
+
+ /* Configure TSHK SETUP Register */
+ if (tsadc->pdata->setup.pen_irq_en == true)
+ setup |= TSHK_SETUP_EN_PIRQ;
+ else
+ setup &= ~TSHK_SETUP_EN_PIRQ;
+
+ if (tsadc->pdata->setup.tsadc_en == true)
+ setup |= TSHK_SETUP_EN_ADC;
+ else
+ setup &= ~TSHK_SETUP_EN_ADC;
+
+ /* Enable signals to ADC, pen irq assertion */
+ rc = marimba_tsadc_write(tsadc, TSHK_SETUP, setup);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
+int marimba_tsadc_start(struct marimba_tsadc_client *client)
+{
+ int rc = 0;
+
+ if (!client) {
+ pr_err("%s: Not a valid client\n", __func__);
+ return -ENODEV;
+ }
+
+ if (!tsadc_dev) {
+ dev_err(&client->pdev->dev,
+ "%s: No tsadc device available\n", __func__);
+ return -ENODEV;
+ }
+
+ /* REVISIT - add locks */
+ if (client->is_ts) {
+ rc = marimba_tsadc_startup(tsadc_dev);
+ if (rc < 0)
+ goto fail_tsadc_startup;
+ rc = marimba_tsadc_configure(tsadc_dev);
+ if (rc < 0)
+ goto fail_tsadc_conf;
+ }
+
+ return 0;
+fail_tsadc_conf:
+ marimba_tsadc_shutdown(tsadc_dev);
+fail_tsadc_startup:
+ return rc;
+}
+EXPORT_SYMBOL(marimba_tsadc_start);
+
+struct marimba_tsadc_client *
+marimba_tsadc_register(struct platform_device *pdev, unsigned int is_ts)
+{
+ struct marimba_tsadc_client *client;
+
+ if (!pdev) {
+ pr_err("%s: valid platform device pointer please\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!is_ts) {
+ dev_err(&pdev->dev, "%s: only TS right now\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!tsadc_dev) {
+ dev_err(&pdev->dev,
+ "%s: No tsadc device available\n", __func__);
+ return ERR_PTR(-ENODEV);
+ }
+
+ client = kzalloc(sizeof *client, GFP_KERNEL);
+ if (!client)
+ return ERR_PTR(-ENOMEM);
+
+ client->pdev = pdev;
+ client->is_ts = is_ts;
+
+ return client;
+}
+EXPORT_SYMBOL(marimba_tsadc_register);
+
+void marimba_tsadc_unregister(struct marimba_tsadc_client *client)
+{
+ if (client->is_ts)
+ marimba_tsadc_shutdown(tsadc_dev);
+ kfree(client);
+}
+EXPORT_SYMBOL(marimba_tsadc_unregister);
+
+static struct resource resources_tssc[] = {
+ {
+ .start = 0xAD300000,
+ .end = 0xAD300000 + SZ_4K - 1,
+ .name = "tssc",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 55,
+ .end = 55,
+ .name = "tssc1",
+ .flags = IORESOURCE_IRQ | IRQF_TRIGGER_RISING,
+ },
+ {
+ .start = 56,
+ .end = 56,
+ .name = "tssc2",
+ .flags = IORESOURCE_IRQ | IRQF_TRIGGER_RISING,
+ },
+};
+
+static struct device *
+marimba_add_tssc_subdev(struct device *parent, const char *name, int num,
+ struct resource *resources, int num_resources,
+ void *pdata, int pdata_len)
+{
+ struct platform_device *pdev;
+ int status;
+
+ pdev = platform_device_alloc(name, num);
+ if (!pdev) {
+ dev_dbg(parent, "can't alloc dev\n");
+ status = -ENOMEM;
+ goto err;
+ }
+
+ pdev->dev.parent = parent;
+
+ if (pdata) {
+ status = platform_device_add_data(pdev, pdata, pdata_len);
+ if (status < 0) {
+ dev_dbg(&pdev->dev, "can't add platform_data\n");
+ goto err;
+ }
+ }
+
+ status = platform_device_add_resources(pdev, resources, num_resources);
+ if (status < 0) {
+ dev_dbg(&pdev->dev, "can't add resources\n");
+ goto err;
+ }
+
+ status = platform_device_add(pdev);
+
+err:
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_err(parent, "can't add %s dev\n", name);
+ return ERR_PTR(status);
+ }
+ return &pdev->dev;
+}
+
+#ifdef CONFIG_PM
+static int
+marimba_tsadc_suspend(struct device *dev)
+{
+ int rc = 0, ret = 0;
+ struct marimba_tsadc *tsadc = dev_get_drvdata(dev);
+
+ if (tsadc->clk_enabled == true) {
+ clk_disable(tsadc->codec_ssbi);
+ tsadc->clk_enabled = false;
+ }
+
+ if (!(device_may_wakeup(dev) &&
+ device_may_wakeup(tsadc->child_tssc))) {
+ rc = marimba_tsadc_shutdown(tsadc);
+ if (rc < 0) {
+ pr_err("%s: Unable to shutdown TSADC\n", __func__);
+ goto fail_shutdown;
+ }
+
+ if (tsadc->pdata->marimba_tsadc_power) {
+ rc = tsadc->pdata->marimba_tsadc_power(0);
+ if (rc < 0)
+ goto fail_tsadc_power;
+ }
+ }
+ return rc;
+
+fail_tsadc_power:
+ marimba_tsadc_startup(tsadc_dev);
+ marimba_tsadc_configure(tsadc_dev);
+fail_shutdown:
+ if (tsadc->clk_enabled == false) {
+ ret = clk_enable(tsadc->codec_ssbi);
+ if (ret == 0)
+ tsadc->clk_enabled = true;
+ }
+ return rc;
+}
+
+static int marimba_tsadc_resume(struct device *dev)
+{
+ int rc = 0;
+ struct marimba_tsadc *tsadc = dev_get_drvdata(dev);
+
+ if (tsadc->clk_enabled == false) {
+ rc = clk_enable(tsadc->codec_ssbi);
+ if (rc != 0) {
+ pr_err("%s: Clk enable failed\n", __func__);
+ return rc;
+ }
+ tsadc->clk_enabled = true;
+ }
+
+ if (!(device_may_wakeup(dev) &&
+ device_may_wakeup(tsadc->child_tssc))) {
+ if (tsadc->pdata->marimba_tsadc_power) {
+ rc = tsadc->pdata->marimba_tsadc_power(1);
+ if (rc) {
+ pr_err("%s: Unable to power on TSADC \n",
+ __func__);
+ goto fail_tsadc_power;
+ }
+ }
+
+ rc = marimba_tsadc_startup(tsadc_dev);
+ if (rc < 0) {
+ pr_err("%s: Unable to startup TSADC\n", __func__);
+ goto fail_tsadc_startup;
+ }
+
+ rc = marimba_tsadc_configure(tsadc_dev);
+ if (rc < 0) {
+ pr_err("%s: Unable to configure TSADC\n", __func__);
+ goto fail_tsadc_configure;
+ }
+ }
+ return rc;
+
+fail_tsadc_configure:
+ marimba_tsadc_shutdown(tsadc_dev);
+fail_tsadc_startup:
+ if (tsadc->pdata->marimba_tsadc_power)
+ tsadc->pdata->marimba_tsadc_power(0);
+fail_tsadc_power:
+ if (tsadc->clk_enabled == true) {
+ clk_disable(tsadc->codec_ssbi);
+ tsadc->clk_enabled = false;
+ }
+ return rc;
+}
+
+static struct dev_pm_ops tsadc_pm_ops = {
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = marimba_tsadc_suspend,
+ .resume = marimba_tsadc_resume,
+#endif
+};
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void marimba_tsadc_early_suspend(struct early_suspend *h)
+{
+ struct marimba_tsadc *tsadc = container_of(h, struct marimba_tsadc,
+ early_suspend);
+
+ marimba_tsadc_suspend(tsadc->dev);
+}
+
+static void marimba_tsadc_late_resume(struct early_suspend *h)
+{
+ struct marimba_tsadc *tsadc = container_of(h, struct marimba_tsadc,
+ early_suspend);
+
+ marimba_tsadc_resume(tsadc->dev);
+}
+#endif
+
+static int __devinit marimba_tsadc_probe(struct platform_device *pdev)
+{
+ struct marimba *marimba = platform_get_drvdata(pdev);
+ struct marimba_tsadc *tsadc;
+ struct marimba_tsadc_platform_data *pdata = pdev->dev.platform_data;
+ int rc = 0;
+ struct device *child;
+
+ printk("%s\n", __func__);
+
+ if (!pdata) {
+ dev_dbg(&pdev->dev, "no tsadc platform data?\n");
+ return -EINVAL;
+ }
+
+ tsadc = kzalloc(sizeof *tsadc, GFP_KERNEL);
+ if (!tsadc)
+ return -ENOMEM;
+
+ tsadc->marimba = marimba;
+ tsadc->dev = &pdev->dev;
+ tsadc->pdata = pdata;
+
+ platform_set_drvdata(pdev, tsadc);
+
+ if (tsadc->pdata->init) {
+ rc = tsadc->pdata->init();
+ if (rc < 0)
+ goto fail_tsadc_init;
+ }
+
+ if (tsadc->pdata->marimba_tsadc_power) {
+ rc = tsadc->pdata->marimba_tsadc_power(1);
+ if (rc) {
+ pr_err("%s: Unable to power up TSADC \n", __func__);
+ goto fail_tsadc_power;
+ }
+ }
+
+ tsadc->codec_ssbi = clk_get(NULL, "codec_ssbi_clk");
+ if (IS_ERR(tsadc->codec_ssbi)) {
+ rc = PTR_ERR(tsadc->codec_ssbi);
+ goto fail_clk_get;
+ }
+ rc = clk_enable(tsadc->codec_ssbi);
+ if (rc != 0)
+ goto fail_clk_enable;
+
+ tsadc->clk_enabled = true;
+
+ child = marimba_add_tssc_subdev(&pdev->dev, "msm_touchscreen", -1,
+ resources_tssc, ARRAY_SIZE(resources_tssc),
+ pdata->tssc_data, sizeof(*pdata->tssc_data));
+
+ if (IS_ERR(child)) {
+ rc = PTR_ERR(child);
+ goto fail_add_subdev;
+ }
+
+ tsadc->child_tssc = child;
+ platform_set_drvdata(pdev, tsadc);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ tsadc->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
+ TSADC_SUSPEND_LEVEL;
+ tsadc->early_suspend.suspend = marimba_tsadc_early_suspend;
+ tsadc->early_suspend.resume = marimba_tsadc_late_resume;
+ register_early_suspend(&tsadc->early_suspend);
+#endif
+
+ tsadc_dev = tsadc;
+ device_init_wakeup(&pdev->dev, pdata->can_wakeup);
+
+ return rc;
+
+fail_add_subdev:
+ clk_disable(tsadc->codec_ssbi);
+
+fail_clk_enable:
+ clk_put(tsadc->codec_ssbi);
+
+fail_clk_get:
+ if (tsadc->pdata->marimba_tsadc_power)
+ rc = tsadc->pdata->marimba_tsadc_power(0);
+fail_tsadc_power:
+ if (tsadc->pdata->exit)
+ rc = tsadc->pdata->exit();
+fail_tsadc_init:
+ kfree(tsadc);
+ return rc;
+}
+
+static int __devexit marimba_tsadc_remove(struct platform_device *pdev)
+{
+ int rc = 0;
+ struct marimba_tsadc *tsadc = platform_get_drvdata(pdev);
+
+ device_init_wakeup(&pdev->dev, 0);
+
+ if (tsadc->clk_enabled == true)
+ clk_disable(tsadc->codec_ssbi);
+
+ clk_put(tsadc->codec_ssbi);
+
+ if (tsadc->pdata->exit)
+ rc = tsadc->pdata->exit();
+
+ if (tsadc->pdata->marimba_tsadc_power)
+ rc = tsadc->pdata->marimba_tsadc_power(0);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&tsadc->early_suspend);
+#endif
+
+ platform_set_drvdata(pdev, NULL);
+ kfree(tsadc);
+ return rc;
+}
+
+static struct platform_driver tsadc_driver = {
+ .probe = marimba_tsadc_probe,
+ .remove = __devexit_p(marimba_tsadc_remove),
+ .driver = {
+ .name = "marimba_tsadc",
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &tsadc_pm_ops,
+#endif
+ },
+};
+
+static int __init marimba_tsadc_init(void)
+{
+ return platform_driver_register(&tsadc_driver);
+}
+device_initcall(marimba_tsadc_init);
+
+static void __exit marimba_tsadc_exit(void)
+{
+ return platform_driver_unregister(&tsadc_driver);
+}
+module_exit(marimba_tsadc_exit);
+
+MODULE_DESCRIPTION("Marimba TSADC driver");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:marimba_tsadc");