123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667 |
- /*
- * connector_setup.c
- *
- * Copyright (C) 2017 Samsung Electronics
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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/sti/sec_abc_detect_conn.h>
- #if defined(CONFIG_SEC_KUNIT)
- #define __mockable __weak
- #define __visible_for_testing
- #define KUNIT_TEST_STRLEN 30
- struct device *sec_abc_detect_conn_dev;
- char kunit_test_str[KUNIT_TEST_STRLEN];
- #else
- #define __mockable
- #define __visible_for_testing static
- #endif
- __visible_for_testing int gsec_abc_detect_conn_enabled;
- struct sec_det_conn_info *gpinfo;
- #if IS_ENABLED(CONFIG_OF)
- static const struct of_device_id sec_abc_detect_conn_dt_match[] = {
- { .compatible = "samsung,sec_abc_detect_conn" },
- { }
- };
- #endif //CONFIG_OF
- #if IS_ENABLED(CONFIG_PM)
- static int sec_abc_detect_conn_pm_suspend(struct device *dev)
- {
- return 0;
- }
- static int sec_abc_detect_conn_pm_resume(struct device *dev)
- {
- return 0;
- }
- static const struct dev_pm_ops sec_abc_detect_conn_pm = {
- .suspend = sec_abc_detect_conn_pm_suspend,
- .resume = sec_abc_detect_conn_pm_resume,
- };
- #endif //CONFIG_PM
- /*
- * Send uevent from irq handler.
- */
- void sec_abc_detect_send_uevent_by_num(int num,
- struct sec_det_conn_info *pinfo,
- int level)
- {
- char *uevent_conn_str[3] = {"", "", NULL};
- char uevent_dev_str[UEVENT_CONN_MAX_DEV_NAME];
- char uevent_dev_type_str[UEVENT_CONN_MAX_DEV_NAME];
- /* Send Uevent Data */
- snprintf(uevent_dev_str, UEVENT_CONN_MAX_DEV_NAME, "CONNECTOR_NAME=%s",
- pinfo->pdata->name[num]);
- uevent_conn_str[0] = uevent_dev_str;
- if (level == 1)
- snprintf(uevent_dev_type_str, UEVENT_CONN_MAX_DEV_NAME,
- "CONNECTOR_TYPE=HIGH_LEVEL");
- else
- snprintf(uevent_dev_type_str, UEVENT_CONN_MAX_DEV_NAME,
- "CONNECTOR_TYPE=LOW_LEVEL");
- uevent_conn_str[1] = uevent_dev_type_str;
- kobject_uevent_env(&pinfo->dev->kobj, KOBJ_CHANGE, uevent_conn_str);
- SEC_CONN_PRINT("send uevent pin[%d]:CONNECTOR_NAME=%s, TYPE=[%d].\n",
- num, pinfo->pdata->name[num], level);
- #if defined(CONFIG_SEC_KUNIT)
- snprintf(kunit_test_str, KUNIT_TEST_STRLEN, "CONNECTOR_TYPE=HIGH_LEVEL");
- #endif
- }
- #if IS_ENABLED(CONFIG_SEC_FACTORY)
- /*
- * Check gpio and send uevent.
- */
- __visible_for_testing void check_gpio_and_send_uevent(int i,
- struct sec_det_conn_info *pinfo)
- {
- if (gpio_get_value(pinfo->pdata->irq_gpio[i])) {
- SEC_CONN_PRINT("%s status changed [disconnected]\n",
- pinfo->pdata->name[i]);
- sec_abc_detect_send_uevent_by_num(i, pinfo, 1);
- } else {
- SEC_CONN_PRINT("%s status changed [connected]\n",
- pinfo->pdata->name[i]);
- sec_abc_detect_send_uevent_by_num(i, pinfo, 0);
- }
- }
- #endif
- #if IS_ENABLED(CONFIG_SEC_ABC_HUB) && IS_ENABLED(CONFIG_SEC_ABC_HUB_COND)
- /**
- * Send an ABC_event about given gpio pin number.
- */
- void send_ABC_event_by_num(int i, struct sec_det_conn_info *pinfo)
- {
- char ABC_event_dev_str[ABCEVENT_CONN_MAX_DEV_STRING];
- if (sec_abc_get_enabled() == 0)
- return;
- /*Send ABC Event Data*/
- if (gpio_get_value(pinfo->pdata->irq_gpio[i])) {
- #if IS_ENABLED(CONFIG_SEC_FACTORY)
- snprintf(ABC_event_dev_str, ABCEVENT_CONN_MAX_DEV_STRING,
- "MODULE=cond@INFO=%s", pinfo->pdata->name[i]);
- #else
- snprintf(ABC_event_dev_str, ABCEVENT_CONN_MAX_DEV_STRING,
- "MODULE=cond@WARN=%s", pinfo->pdata->name[i]);
- #endif
- sec_abc_send_event(ABC_event_dev_str);
- SEC_CONN_PRINT("send ABC cond event %s status is [disconnected] : %s\n",
- pinfo->pdata->name[i], ABC_event_dev_str);
- } else {
- SEC_CONN_PRINT("do not send ABC cond event %s status is [connected]\n",
- pinfo->pdata->name[i]);
- }
- }
- #endif
- /*
- * Check and send uevent from irq handler.
- */
- void sec_abc_detect_send_uevent_irq(int irq,
- struct sec_det_conn_info *pinfo,
- int type)
- {
- int i;
- for (i = 0; i < pinfo->pdata->gpio_total_cnt; i++) {
- if (irq == pinfo->pdata->irq_number[i]) {
- /* apply s/w debounce time */
- usleep_range(DET_CONN_DEBOUNCE_TIME_MS * 1000, DET_CONN_DEBOUNCE_TIME_MS * 1000);
- #if IS_ENABLED(CONFIG_SEC_FACTORY)
- check_gpio_and_send_uevent(i, pinfo);
- #endif
- #if IS_ENABLED(CONFIG_SEC_ABC_HUB) && IS_ENABLED(CONFIG_SEC_ABC_HUB_COND)
- send_ABC_event_by_num(i, pinfo);
- #endif
- increase_connector_disconnected_count(i, pinfo);
- }
- }
- }
- /*
- * Called when the connector pin state changes.
- */
- static irqreturn_t sec_abc_detect_conn_interrupt_handler(int irq, void *handle)
- {
- int type;
- struct sec_det_conn_info *pinfo = handle;
- if (gsec_abc_detect_conn_enabled != 0) {
- SEC_CONN_PRINT("%s\n", __func__);
- type = irq_get_trigger_type(irq);
- sec_abc_detect_send_uevent_irq(irq, pinfo, type);
- }
- return IRQ_HANDLED;
- }
- /*
- * Enable all gpio pin IRQ which is from Device Tree.
- */
- int detect_conn_irq_enable(struct sec_det_conn_info *pinfo, bool enable,
- int pin)
- {
- int ret = 0;
- int i;
- if (!enable) {
- for (i = 0; i < pinfo->pdata->gpio_total_cnt; i++) {
- if (pinfo->irq_enabled[i]) {
- disable_irq(pinfo->pdata->irq_number[i]);
- pinfo->irq_enabled[i] = DET_CONN_GPIO_IRQ_DISABLED;
- }
- }
- return ret;
- }
- if (pin >= pinfo->pdata->gpio_total_cnt)
- return ret;
- if (pinfo->irq_enabled[pin] == DET_CONN_GPIO_IRQ_NOT_INIT) {
- ret = request_threaded_irq(pinfo->pdata->irq_number[pin], NULL,
- sec_abc_detect_conn_interrupt_handler,
- pinfo->pdata->irq_type[pin] | IRQF_ONESHOT,
- pinfo->pdata->name[pin], pinfo);
- if (ret) {
- SEC_CONN_PRINT("%s: Failed to request irq %d.\n", __func__,
- ret);
- return ret;
- }
- SEC_CONN_PRINT("%s: Succeeded to request threaded irq %d:\n",
- __func__, ret);
- } else if (pinfo->irq_enabled[pin] == DET_CONN_GPIO_IRQ_DISABLED) {
- enable_irq(pinfo->pdata->irq_number[pin]);
- }
- SEC_CONN_PRINT("irq_num[%d], type[%x],name[%s].\n",
- pinfo->pdata->irq_number[pin],
- pinfo->pdata->irq_type[pin], pinfo->pdata->name[pin]);
- pinfo->irq_enabled[pin] = DET_CONN_GPIO_IRQ_ENABLED;
- return ret;
- }
- /*
- * Check and send an uevent if the pin level is high.
- * And then enable gpio pin interrupt.
- */
- __visible_for_testing int one_gpio_irq_enable(int i, struct sec_det_conn_p_data *pdata,
- const char *buf)
- {
- int ret = 0;
- SEC_CONN_PRINT("%s driver enabled.\n", buf);
- gsec_abc_detect_conn_enabled |= (1 << i);
- SEC_CONN_PRINT("gpio [%d] level %d\n", pdata->irq_gpio[i],
- gpio_get_value(pdata->irq_gpio[i]));
- /*get level value of the gpio pin.*/
- /*if there's gpio low pin, send uevent*/
- #if IS_ENABLED(CONFIG_SEC_FACTORY)
- check_gpio_and_send_uevent(i, pdata->pinfo);
- #endif
- #if IS_ENABLED(CONFIG_SEC_ABC_HUB) && IS_ENABLED(CONFIG_SEC_ABC_HUB_COND)
- send_ABC_event_by_num(i, pdata->pinfo);
- #endif
- increase_connector_disconnected_count(i, pdata->pinfo);
- /*Enable interrupt.*/
- ret = detect_conn_irq_enable(pdata->pinfo, true, i);
- if (ret < 0)
- SEC_CONN_PRINT("%s Interrupt not enabled.\n", buf);
- return ret;
- }
- /*
- * Triggered when "enabled" node is set.
- * Check and send an uevent if the pin level is high.
- * And then gpio pin interrupt is enabled.
- */
- __visible_for_testing ssize_t enabled_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct sec_det_conn_p_data *pdata;
- struct sec_det_conn_info *pinfo;
- int ret;
- int i;
- int buf_len;
- int pin_name_len;
- if (gpinfo == 0)
- return count;
- pinfo = gpinfo;
- pdata = pinfo->pdata;
- buf_len = strlen(buf);
- SEC_CONN_PRINT("buf = %s, buf_len = %d\n", buf, buf_len);
- /* disable irq when "enabled" value set to 0*/
- if (!strncmp(buf, "0", 1)) {
- SEC_CONN_PRINT("sec detect connector driver disable.\n");
- gsec_abc_detect_conn_enabled = 0;
- ret = detect_conn_irq_enable(pinfo, false, 0);
- if (ret) {
- SEC_CONN_PRINT("Interrupt not disabled.\n");
- return ret;
- }
- return count;
- }
- for (i = 0; i < pdata->gpio_total_cnt; i++) {
- pin_name_len = strlen(pdata->name[i]);
- SEC_CONN_PRINT("pinName = %s\n", pdata->name[i]);
- SEC_CONN_PRINT("pin_name_len = %d\n", pin_name_len);
- if (pin_name_len == buf_len) {
- if (!strncmp(buf, pdata->name[i], buf_len)) {
- /* buf sting is equal to pdata->name[i] */
- ret = one_gpio_irq_enable(i, pdata, buf);
- if (ret < 0)
- return ret;
- }
- }
- /*
- * For ALL_CONNECT input,
- * enable all nodes except already enabled node.
- */
- if (buf_len >= 11) {
- if (strncmp(buf, "ALL_CONNECT", 11)) {
- /* buf sting is not equal to ALL_CONNECT */
- continue;
- }
- /* buf sting is equal to pdata->name[i] */
- if (!(gsec_abc_detect_conn_enabled & (1 << i))) {
- ret = one_gpio_irq_enable(i, pdata, buf);
- if (ret < 0)
- return ret;
- }
- }
- }
- return count;
- }
- __visible_for_testing ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
- char *buf)
- {
- return snprintf(buf, 12, "%d\n", gsec_abc_detect_conn_enabled);
- }
- static DEVICE_ATTR_RW(enabled);
- __visible_for_testing ssize_t available_pins_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
- {
- struct sec_det_conn_p_data *pdata;
- struct sec_det_conn_info *pinfo;
- char available_pins_string[1024] = {0, };
- int i;
- if (gpinfo == 0)
- return 0;
- pinfo = gpinfo;
- pdata = pinfo->pdata;
- for (i = 0; i < pdata->gpio_total_cnt; i++) {
- SEC_CONN_PRINT("pinName = %s\n", pdata->name[i]);
- strlcat(available_pins_string, pdata->name[i], 1024);
- strlcat(available_pins_string, "/", 1024);
- }
- available_pins_string[strlen(available_pins_string) - 1] = '\0';
- return snprintf(buf, 1024, "%s\n", available_pins_string);
- }
- static DEVICE_ATTR_RO(available_pins);
- /**
- * Fill out the gpio cnt
- */
- static void fill_gpio_cnt(struct sec_det_conn_p_data *pdata, struct device_node *np, char *gpio_name)
- {
- int gpio_name_cnt;
- gpio_name_cnt = of_gpio_named_count(np, gpio_name);
- if (gpio_name_cnt < 1) {
- SEC_CONN_PRINT("fill gpio cnt failed %s < 1 %d.\n",
- gpio_name,
- gpio_name_cnt);
- gpio_name_cnt = 0;
- }
- pdata->gpio_last_cnt = pdata->gpio_total_cnt;
- pdata->gpio_total_cnt = pdata->gpio_total_cnt + gpio_name_cnt;
- SEC_CONN_PRINT("fill out %s gpio cnt, gpio_total_count = %d", gpio_name, pdata->gpio_total_cnt);
- }
- /**
- * Fill out the gpio name
- */
- static void fill_gpio_name(struct sec_det_conn_p_data *pdata,
- struct device_node *np,
- char *conn_name,
- int offset,
- int index)
- {
- /*Get connector name*/
- of_property_read_string_index(np, conn_name, offset, &pdata->name[index]);
- }
- /**
- * Fill out the irq info
- */
- static int fill_irq_info(struct sec_det_conn_p_data *pdata,
- struct device_node *np,
- char *gpio_name,
- int offset,
- int index)
- {
- /* get connector gpio number*/
- pdata->irq_gpio[index] = of_get_named_gpio(np, gpio_name, offset);
- if (!gpio_is_valid(pdata->irq_gpio[index])) {
- SEC_CONN_PRINT("[%s] gpio[%d] is not valid\n", gpio_name, offset);
- return 0;
- }
- pdata->irq_number[index] = gpio_to_irq(pdata->irq_gpio[index]);
- pdata->irq_type[index] = IRQ_TYPE_EDGE_BOTH;
- SEC_CONN_PRINT("i = %d, irq_gpio[i] = %d, irq_num[i] = %d, level = %d\n", index,
- pdata->irq_gpio[index],
- pdata->irq_number[index],
- gpio_get_value(pdata->irq_gpio[index]));
- return 1;
- }
- /**
- * Parse the AP device tree and get gpio number, irq type.
- * Request gpio
- */
- static void parse_ap_dt(struct sec_det_conn_p_data *pdata, struct device_node *np)
- {
- int i;
- fill_gpio_cnt(pdata, np, "sec,det_conn_gpios");
- for (i = pdata->gpio_last_cnt; i < pdata->gpio_total_cnt; i++) {
- fill_gpio_name(pdata, np, "sec,det_conn_name", i - pdata->gpio_last_cnt, i);
- if (!fill_irq_info(pdata, np, "sec,det_conn_gpios", i - pdata->gpio_last_cnt, i))
- break;
- }
- }
- #if IS_ENABLED(CONFIG_QCOM_SEC_ABC_DETECT)
- /**
- * gpio pinctrl by pinctrl-name
- */
- static void set_pinctrl_by_pinctrl_name(struct device *dev, char *pinctrl_name)
- {
- struct pinctrl *conn_pinctrl;
- conn_pinctrl = devm_pinctrl_get_select(dev, pinctrl_name);
- if (IS_ERR_OR_NULL(conn_pinctrl))
- SEC_CONN_PRINT("%s detect_pinctrl_init failed.\n", pinctrl_name);
- else
- SEC_CONN_PRINT("%s detect_pinctrl_init passed.\n", pinctrl_name);
- }
- /**
- * Parse the Expander device tree and get gpio number, irq type.
- * Request gpio
- */
- static void parse_exp_dt(struct sec_det_conn_p_data *pdata, struct device_node *np)
- {
- int i;
- fill_gpio_cnt(pdata, np, "sec,det_exp_conn_gpios");
- for (i = pdata->gpio_last_cnt; i < pdata->gpio_total_cnt; i++) {
- fill_gpio_name(pdata, np, "sec,det_exp_conn_name", i - pdata->gpio_last_cnt, i);
- if (!fill_irq_info(pdata, np, "sec,det_exp_conn_gpios", i - pdata->gpio_last_cnt, i))
- break;
- }
- }
- /**
- * Parse the PM device tree and get gpio number, irq type.
- * Request gpio
- */
- static void parse_pmic_dt(struct sec_det_conn_p_data *pdata, struct device_node *np)
- {
- int i;
- fill_gpio_cnt(pdata, np, "sec,det_pm_conn_gpios");
- for (i = pdata->gpio_last_cnt; i < pdata->gpio_total_cnt; i++) {
- fill_gpio_name(pdata, np, "sec,det_pm_conn_name", i - pdata->gpio_last_cnt, i);
- if (!fill_irq_info(pdata, np, "sec,det_pm_conn_gpios", i - pdata->gpio_last_cnt, i))
- break;
- }
- }
- #endif
- #if IS_ENABLED(CONFIG_OF)
- /**
- * Parse the device tree and get gpio number, irq type.
- * Request gpio
- */
- static int parse_detect_conn_dt(struct device *dev)
- {
- struct sec_det_conn_p_data *pdata = dev->platform_data;
- struct device_node *np = dev->of_node;
- #if IS_ENABLED(CONFIG_QCOM_SEC_ABC_DETECT)
- set_pinctrl_by_pinctrl_name(dev, "det_ap_connect");
- #endif
- parse_ap_dt(pdata, np);
- #if IS_ENABLED(CONFIG_QCOM_SEC_ABC_DETECT)
- set_pinctrl_by_pinctrl_name(dev, "det_exp_connect");
- parse_exp_dt(pdata, np);
- set_pinctrl_by_pinctrl_name(dev, "det_pm_connect");
- set_pinctrl_by_pinctrl_name(dev, "det_pm_2_connect");
- parse_pmic_dt(pdata, np);
- #endif
- return 0;
- }
- #endif //CONFIG_OF
- static int sec_abc_detect_conn_probe(struct platform_device *pdev)
- {
- struct sec_det_conn_p_data *pdata;
- struct sec_det_conn_info *pinfo;
- int ret = 0;
- SEC_CONN_PRINT("%s\n", __func__);
- /* First Get the GPIO pins; if it fails, we'll defer the probe. */
- if (pdev->dev.of_node) {
- pdata = devm_kzalloc(&pdev->dev,
- sizeof(struct sec_det_conn_p_data),
- GFP_KERNEL);
- if (!pdata) {
- dev_err(&pdev->dev, "Failed to allocate pdata.\n");
- return -ENOMEM;
- }
- pdev->dev.platform_data = pdata;
- #if IS_ENABLED(CONFIG_OF)
- ret = parse_detect_conn_dt(&pdev->dev);
- #endif
- if (ret) {
- dev_err(&pdev->dev, "Failed to parse dt data.\n");
- return ret;
- }
- pr_info("%s: parse dt done.\n", __func__);
- } else {
- pdata = pdev->dev.platform_data;
- }
- if (!pdata) {
- dev_err(&pdev->dev, "There are no platform data.\n");
- return -EINVAL;
- }
- pinfo = devm_kzalloc(&pdev->dev, sizeof(struct sec_det_conn_info),
- GFP_KERNEL);
- if (!pinfo) {
- SEC_CONN_PRINT("pinfo : failed to allocate pinfo.\n");
- return -ENOMEM;
- }
- #if defined(CONFIG_SEC_KUNIT)
- sec_abc_detect_conn_dev = pinfo->dev;
- #endif
- /* Create sys device /sys/class/sec/sec_detect_conn */
- pinfo->dev = sec_device_create(pinfo, "sec_detect_conn");
- if (IS_ERR(pinfo->dev)) {
- pr_err("%s Failed to create device(sec_abc_detect_conn).\n",
- __func__);
- ret = -ENODEV;
- goto out;
- }
- /* Create sys node /sys/class/sec/sec_detect_conn/enabled */
- ret = device_create_file(pinfo->dev, &dev_attr_enabled);
- if (ret) {
- dev_err(&pdev->dev, "%s: Failed to create device file.\n",
- __func__);
- goto err_create_detect_conn_sysfs;
- }
- /* Create sys node /sys/class/sec/sec_detect_conn/available_pins */
- ret = device_create_file(pinfo->dev, &dev_attr_available_pins);
- if (ret) {
- dev_err(&pdev->dev, "%s: Failed to create device file.\n",
- __func__);
- goto err_create_detect_conn_sysfs;
- }
- create_current_connection_state_sysnode_files(pinfo);
- create_connector_disconnected_count_sysnode_file(pinfo);
- /*save pinfo data to pdata to interrupt enable*/
- pdata->pinfo = pinfo;
- /*save pdata data to pinfo for enable node*/
- pinfo->pdata = pdata;
- /* save pinfo to gpinfo to enabled node*/
- gpinfo = pinfo;
- #if !IS_ENABLED(CONFIG_SEC_FACTORY)
- /* enable gpio irq for Big data */
- enabled_store(pinfo->dev, (struct device_attribute *)0, "ALL_CONNECT", 0);
- #endif
- return ret;
- err_create_detect_conn_sysfs:
- sec_device_destroy(pinfo->dev->devt);
- out:
- gpinfo = 0;
- kfree(pinfo);
- kfree(pdata);
- return ret;
- }
- static int sec_abc_detect_conn_remove(struct platform_device *pdev)
- {
- return 0;
- }
- static struct platform_driver sec_abc_detect_conn_driver = {
- .probe = sec_abc_detect_conn_probe,
- .remove = sec_abc_detect_conn_remove,
- .driver = {
- .name = "sec_abc_detect_conn",
- .owner = THIS_MODULE,
- #if IS_ENABLED(CONFIG_PM)
- .pm = &sec_abc_detect_conn_pm,
- #endif
- #if IS_ENABLED(CONFIG_OF)
- .of_match_table = of_match_ptr(sec_abc_detect_conn_dt_match),
- #endif
- },
- };
- static int __init sec_abc_detect_conn_init(void)
- {
- SEC_CONN_PRINT("%s gogo\n", __func__);
- return platform_driver_register(&sec_abc_detect_conn_driver);
- }
- static void __exit sec_abc_detect_conn_exit(void)
- {
- return platform_driver_unregister(&sec_abc_detect_conn_driver);
- }
- #if IS_ENABLED(CONFIG_SEC_ABC_HUB) && IS_ENABLED(CONFIG_SEC_ABC_HUB_COND)
- /**
- * This function is not used for ABC driver due to the Big Data always on Concept
- */
- void abc_hub_cond_enable(struct device *dev, int enable)
- {
- }
- EXPORT_SYMBOL(abc_hub_cond_enable);
- #endif
- module_init(sec_abc_detect_conn_init);
- module_exit(sec_abc_detect_conn_exit);
- MODULE_DESCRIPTION("Samsung Detecting Connector Driver");
- MODULE_AUTHOR("Samsung Electronics");
- MODULE_LICENSE("GPL");
|