blob: 7eed41b6054c9acfab93395f88a1471e09012526 [file] [log] [blame]
/*
* MST drv Support
*
*/
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/syscalls.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/fs.h>
#include <linux/smc.h>
#include <linux/platform_device.h>
#include <linux/wakelock.h>
#include <linux/delay.h>
#include <linux/power_supply.h>
#if defined(CONFIG_MST_LPM_CONTROL)
#include <linux/exynos-pci-ctrl.h>
#endif
//#include <mach/exynos-pm.h>
#include <linux/spinlock.h>
#include "mstdrv.h"
#if defined(CONFIG_MST_TEEGRIS)
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include "../../drivers/misc/tzdev/3.0/include/tzdev/tee_client_api.h"
#endif
#define MST_LDO3_0 "MST_LEVEL_3.0V"
#define MST_NOT_SUPPORT (0x1 << 3)
#if !defined(CONFIG_MST_IF_PMIC)
static int mst_pwr_en;
#endif
#if defined(CONFIG_MST_SUPPORT_GPIO)
static int mst_support_check;
#endif
#if defined(CONFIG_MST_NONSECURE)
static int mst_en;
static int mst_data;
static spinlock_t event_lock;
#endif
static struct class *mst_drv_class;
struct device *mst_drv_dev;
static int escape_loop = 1;
//static int rt;
static int nfc_state;
static struct wake_lock mst_wakelock;
#if defined(CONFIG_MFC_CHARGER)
static int wpc_det;
#endif
#if defined(CONFIG_MST_TEEGRIS)
/* swd_ta_mstdrv */
/*
static TEEC_UUID uuid_driver = {
0,0,0,{0,0,0,0x4d,0x53,0x54,0x44,0x56}
};
*/
/* swd_ta_mst */
static TEEC_UUID uuid_ta = {
0,0,0,{0,0,0x6d,0x73,0x74,0x5f,0x54,0x41}
};
enum cmd_drv_client
{
/* ta cmd */
CMD_OPEN,
CMD_CLOSE,
CMD_IOCTL,
CMD_TRACK1,
CMD_TRACK2,
CMD_MAX
};
#endif
EXPORT_SYMBOL_GPL(mst_drv_dev);
#if defined(CONFIG_MFC_CHARGER)
#define MST_MODE_ON 1
#define MST_MODE_OFF 0
static inline struct power_supply *get_power_supply_by_name(char *name)
{
if (!name)
return (struct power_supply *)NULL;
else
return power_supply_get_by_name(name);
}
#define psy_do_property(name, function, property, value) \
{ \
struct power_supply *psy; \
int ret; \
psy = get_power_supply_by_name((name)); \
if (!psy) { \
pr_err("%s: Fail to "#function" psy (%s)\n", \
__func__, (name)); \
value.intval = 0; \
} else { \
if (psy->desc->function##_property != NULL) { \
ret = psy->desc->function##_property(psy, (property), &(value)); \
if (ret < 0) { \
pr_err("%s: Fail to %s "#function" (%d=>%d)\n", \
__func__, name, (property), ret); \
value.intval = 0; \
} \
} \
} \
}
#endif
extern void mst_ctrl_of_mst_hw_onoff(bool on)
{
#if defined(CONFIG_MFC_CHARGER)
union power_supply_propval value; /* power_supply prop */
#endif
printk("[MST] mst-drv : mst_ctrl : mst_power_onoff : %d\n", on);
if (on) {
printk("[MST] %s : nfc_status gets back to 0(unlock)\n",
__func__);
nfc_state = 0;
} else {
#if !defined(CONFIG_MST_IF_PMIC)
gpio_set_value(mst_pwr_en, 0);
printk("%s : mst_pwr_en gets the LOW\n", __func__);
#endif
usleep_range(800, 1000);
printk("%s : msleep(1)\n", __func__);
#if defined(CONFIG_MFC_CHARGER)
value.intval = MST_MODE_OFF;
psy_do_property("mfc-charger", set,
POWER_SUPPLY_PROP_TECHNOLOGY, value);
printk("%s : MST_MODE_OFF notify : %d\n", __func__,
value.intval);
#endif
#if defined(CONFIG_MST_LPM_CONTROL)
/* PCIe LPM Enable */
printk("%s : l1ss enable, id : %d\n", __func__, PCIE_L1SS_CTRL_MST);
exynos_pcie_l1ss_ctrl(1, PCIE_L1SS_CTRL_MST);
#endif
printk("%s : nfc_status gets 1(lock)\n", __func__);
nfc_state = 1;
}
}
static void of_mst_hw_onoff(bool on)
{
#if defined(CONFIG_MFC_CHARGER)
union power_supply_propval value; /* power_supply prop */
int retry_cnt = 8;
#endif
printk("mst-drv : mst_power_onoff : %d\n", on);
if (nfc_state == 1) {
printk("[MST] %s : nfc_state is on!!!\n", __func__);
return;
}
if (on) {
#if defined(CONFIG_MFC_CHARGER)
printk("%s : MST_MODE_ON notify start\n", __func__);
value.intval = MST_MODE_ON;
psy_do_property("mfc-charger", set,
POWER_SUPPLY_PROP_TECHNOLOGY, value);
printk("%s : MST_MODE_ON notified : %d\n", __func__,
value.intval);
#endif
#if !defined(CONFIG_MST_IF_PMIC)
gpio_set_value(mst_pwr_en, 1);
printk("%s : mst_pwr_en gets the HIGH\n", __func__);
#endif
#if defined(CONFIG_MST_LPM_CONTROL)
/* PCIe LPM Disable */
printk("%s : l1ss disable, id : %d\n", __func__, PCIE_L1SS_CTRL_MST);
exynos_pcie_l1ss_ctrl(0, PCIE_L1SS_CTRL_MST);
#endif
mdelay(40);
#if defined(CONFIG_MFC_CHARGER)
while (--retry_cnt) {
psy_do_property("mfc-charger", get,
POWER_SUPPLY_PROP_TECHNOLOGY, value);
//printk("%s : check mst mode status : %d\n", __func__, value.intval);
if (value.intval == 0x02) {
printk("%s : mst mode set!!! : %d\n", __func__,
value.intval);
retry_cnt = 1;
break;
}
usleep_range(3600, 4000);
}
if (!retry_cnt) {
printk("%s : timeout !!! : %d\n", __func__,
value.intval);
}
#endif
} else {
#if !defined(CONFIG_MST_IF_PMIC)
gpio_set_value(mst_pwr_en, 0);
printk("%s : mst_pwr_en gets the LOW\n", __func__);
#endif
usleep_range(800, 1000);
printk("%s : msleep(1)\n", __func__);
#if defined(CONFIG_MFC_CHARGER)
value.intval = MST_MODE_OFF;
psy_do_property("mfc-charger", set,
POWER_SUPPLY_PROP_TECHNOLOGY, value);
printk("%s : MST_MODE_OFF notify : %d\n", __func__,
value.intval);
#endif
#if defined(CONFIG_MST_LPM_CONTROL)
/* PCIe LPM Enable */
printk("%s : l1ss enable, id : %d\n", __func__, PCIE_L1SS_CTRL_MST);
exynos_pcie_l1ss_ctrl(1, PCIE_L1SS_CTRL_MST);
#endif
}
}
#if defined(CONFIG_MST_TEEGRIS)
uint32_t transmit_mst_teegris(uint32_t cmd)
{
TEEC_Context context;
TEEC_Session session_ta;
//TEEC_Session session_driver;
TEEC_Operation operation;
TEEC_Result result;
uint32_t origin;
origin = 0x0;
operation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
printk("TEST: TEEC_InitializeContext\n");
result = TEEC_InitializeContext(NULL, &context);
if (result != TEEC_SUCCESS) {
printk("TEST: TEEC_InitializeContext failed, %d\n", result);
goto exit;
}
/*
printk("TEST: TEEC_OpenSession (driver)\n");
result = TEEC_OpenSession(&context, &session_driver, &uuid_driver, 0,
NULL, &operation, &origin);
if (result != TEEC_SUCCESS) {
printk("TEST: TEEC_OpenSession(driver) failed, %d\n", result);
goto finalize_context;
}
*/
printk("TEST: TEEC_OpenSession (ta)\n");
result = TEEC_OpenSession(&context, &session_ta, &uuid_ta, 0,
NULL, &operation, &origin);
if (result != TEEC_SUCCESS) {
printk("TEST: TEEC_OpenSession(ta) failed, %d\n", result);
goto finalize_context;
}
printk("TEST: TEEC_InvokeCommand (CMD_OPEN)\n");
result = TEEC_InvokeCommand(&session_ta, CMD_OPEN, &operation, &origin);
if (result != TEEC_SUCCESS) {
printk("TEST: TEEC_InvokeCommand(OPEN) failed, %d\n", result);
goto ta_close_session;
}
/* MST IOCTL - transmit track1 */
printk("TEST: TEEC_InvokeCommand (CMD_TRACK1 or CMD_TRACK2)\n");
result = TEEC_InvokeCommand(&session_ta, cmd, &operation, &origin);
if (result != TEEC_SUCCESS) {
printk("TEST: TEEC_InvokeCommand(CMD_TRACK1 or CMD_TRACK2) failed, %d\n", result);
goto ta_close_session;
}
printk("TEST: TEEC_InvokeCommand (CMD_CLOSE)\n");
result = TEEC_InvokeCommand(&session_ta, CMD_CLOSE, &operation, &origin);
if (result != TEEC_SUCCESS) {
printk("TEST: TEEC_InvokeCommand(CLOSE) failed, %d\n", result);
goto ta_close_session;
}
ta_close_session:
TEEC_CloseSession(&session_ta);
//driver_close_session:
//TEEC_CloseSession(&session_driver);
finalize_context:
TEEC_FinalizeContext(&context);
exit:
return result;
}
/*
uint32_t mst_driver_test_teegris(uint32_t cmd)
{
TEEC_Context context;
TEEC_Session session_driver;
TEEC_Operation operation;
TEEC_Result result;
uint32_t origin;
printk("TEST: Begin mst_driver_test_teegris() +\n");
origin = 0x0;
operation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
printk("TEST: TEEC_InitializeContext\n");
result = TEEC_InitializeContext(NULL, &context);
if (result != TEEC_SUCCESS) {
printk("TEST: TEEC_InitializeContext failed, %d\n", result);
goto exit;
}
printk("TEST: TEEC_OpenSession (driver)\n");
result = TEEC_OpenSession(&context, &session_driver, &uuid_driver, 0,
NULL, &operation, &origin);
if (result != TEEC_SUCCESS) {
printk("TEST: TEEC_OpenSession(driver) failed, %d\n", result);
goto finalize_context;
}
printk("TEST: TEEC_InvokeCommand\n");
result = TEEC_InvokeCommand(&session_driver, cmd, &operation, &origin);
if (result != TEEC_SUCCESS) {
printk("TEST: TEEC_InvokeCommand(CLOSE) failed, %d\n", result);
goto driver_close_session;
}
driver_close_session:
TEEC_CloseSession(&session_driver);
finalize_context:
TEEC_FinalizeContext(&context);
exit:
printk("TEST: Begin mst_ta_driver_test_teegris() -, %d\n", result);
return result;
}
*/
#endif
static ssize_t show_mst_drv(struct device *dev,
struct device_attribute *attr, char *buf)
{
if (!dev)
return -ENODEV;
// todo
if (escape_loop == 0) {
return sprintf(buf, "%s\n", "activating");
} else {
return sprintf(buf, "%s\n", "waiting");
}
}
static ssize_t store_mst_drv(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
u64 r0 = 0, r1 = 0, r2 = 0, r3 = 0;
char test_result[256] = { 0, };
int result = 0;
#if defined(CONFIG_MST_NONSECURE)
int case_i = 0;
#endif
#if defined(CONFIG_MFC_CHARGER)
struct device_node *np;
enum of_gpio_flags irq_gpio_flags;
#endif
sscanf(buf, "%20s\n", test_result);
printk(KERN_ERR "MST Store test result : %s\n", test_result);
#if defined(CONFIG_MFC_CHARGER)
if (wpc_det < 0) {
np = of_find_node_by_name(NULL, "battery");
if (!np) {
pr_err("%s np NULL\n", __func__);
} else {
/* wpc_det */
wpc_det = of_get_named_gpio_flags(np, "battery,wpc_det",
0, &irq_gpio_flags);
if (wpc_det < 0) {
dev_err(dev, "%s : can't get wpc_det = %d\n", __FUNCTION__, wpc_det);
}
}
}
if (wpc_det && (gpio_get_value(wpc_det) == 1)) {
printk("[MST] Wireless charging is ongoing, do not proceed MST work\n");
return count;
}
#endif
switch (test_result[0]) {
case '1':
of_mst_hw_onoff(1);
break;
case '0':
of_mst_hw_onoff(0);
break;
case '2':
#if !defined(CONFIG_MFC_CHARGER)
of_mst_hw_onoff(1);
#endif
trace_printk("tracing mark write: MST transmission Start\n");
#if defined(CONFIG_MST_NONSECURE)
case_i= 1;
printk("MST send track1 data, case_i %d\n", case_i);
if (transmit_mst_data(case_i)) {
printk("track1 data is sent\n");
}
#else
#if defined(CONFIG_MST_TEEGRIS)
printk("MST_LDO_DRV]]] Call to Blowfish ta_mst for TRACK1\n");
result = transmit_mst_teegris(CMD_TRACK1);
printk(KERN_INFO "MST_LDO_DRV]]] Track1 data sent : %d\n", result);
#else
printk(KERN_INFO "%s\n", __func__);
printk(KERN_INFO "MST_LDO_DRV]]] Track1 data transmit\n");
//Will Add here
r0 = (0x8300000f);
r1 = 1;
result = exynos_smc(r0, r1, r2, r3);
printk(KERN_INFO "MST_LDO_DRV]]] Track1 data sent : %d\n", result);
#endif
#endif
trace_printk("tracing mark write: MST transmission End\n");
#if !defined(CONFIG_MFC_CHARGER)
of_mst_hw_onoff(0);
#endif
break;
case '3':
#if !defined(CONFIG_MFC_CHARGER)
of_mst_hw_onoff(1);
#endif
trace_printk("tracing mark write: MST transmission Start\n");
#if defined(CONFIG_MST_NONSECURE)
case_i = 2;
printk("MST send track2 data, case_i : %d\n", case_i);
if (transmit_mst_data(case_i)) {
printk("track2 data is sent\n");
}
#else
#if defined(CONFIG_MST_TEEGRIS)
printk("MST_LDO_DRV]]] Call to Blowfish ta_mst for TRACK2\n");
result = transmit_mst_teegris(CMD_TRACK2);
printk(KERN_INFO "MST_LDO_DRV]]] Track2 data sent : %d\n", result);
#else
printk(KERN_INFO "%s\n", __func__);
printk(KERN_INFO "MST_LDO_DRV]]] Track2 data transmit\n");
//Will Add here
r0 = (0x8300000f);
r1 = 2;
result = exynos_smc(r0, r1, r2, r3);
printk(KERN_INFO "MST_LDO_DRV]]] Track2 data sent : %d\n", result);
#endif
#endif
trace_printk("tracing mark write: MST transmission End\n");
#if !defined(CONFIG_MFC_CHARGER)
of_mst_hw_onoff(0);
#endif
break;
case '4':
if (escape_loop) {
wake_lock_init(&mst_wakelock, WAKE_LOCK_SUSPEND,
"mst_wakelock");
wake_lock(&mst_wakelock);
}
escape_loop = 0;
while (1) {
if (escape_loop == 1)
break;
#if !defined(CONFIG_MFC_CHARGER)
of_mst_hw_onoff(1);
#endif
mdelay(10);
printk("MST_LDO_DRV]]] Continuous Track2 data transmit\n");
r0 = (0x8300000f);
r1 = 2;
result = exynos_smc(r0, r1, r2, r3);
printk(KERN_INFO
"MST_LDO_DRV]]] Continuous Track2 data transmit after smc : %d\n",
result);
#if !defined(CONFIG_MFC_CHARGER)
of_mst_hw_onoff(0);
#endif
mdelay(1000);
}
break;
case '5':
if (!escape_loop)
wake_lock_destroy(&mst_wakelock);
escape_loop = 1;
printk("MST escape_loop value = 1\n");
break;
default:
printk(KERN_ERR "MST invalid value : %s\n", test_result);
break;
}
return count;
}
static DEVICE_ATTR(transmit, 0770, show_mst_drv, store_mst_drv);
/* MST support node */
static ssize_t show_support(struct device *dev,
struct device_attribute *attr, char *buf)
{
#if defined(CONFIG_MST_SUPPORT_GPIO)
uint8_t is_mst_support = 0;
#endif
if (!dev)
return -ENODEV;
#if defined(CONFIG_MST_SUPPORT_GPIO)
is_mst_support = gpio_get_value(mst_support_check);
if (is_mst_support == 1) {
printk(KERN_ERR "MST_DRV]]] This device supports MST, %d\n", is_mst_support);
return sprintf(buf, "%d\n", 1);
} else {
printk(KERN_ERR "MST_DRV]]] This device doesn't supports MST, %d\n", is_mst_support);
return sprintf(buf, "%d\n", 0);
}
#else
printk("%s no support gpio, bug MST_LDO is enabled, supports MST\n", __func__);
return sprintf(buf, "%d\n", 1);
#endif
}
static ssize_t store_support(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
return count;
}
static DEVICE_ATTR(support, 0444, show_support, store_support);
#if defined(CONFIG_MFC_CHARGER)
static ssize_t show_mfc(struct device *dev,
struct device_attribute *attr, char *buf)
{
if (!dev)
return -ENODEV;
return sprintf(buf, "%s\n", "mfc_charger");
}
static ssize_t store_mfc(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
return count;
}
static DEVICE_ATTR(mfc, 0770, show_mfc, store_mfc);
#endif
static int sec_mst_gpio_init(struct device *dev)
{
#if defined(CONFIG_MST_NONSECURE) || !defined(CONFIG_MST_IF_PMIC)
int ret = 0;
#endif
#if defined(CONFIG_MFC_CHARGER)
struct device_node *np;
enum of_gpio_flags irq_gpio_flags;
/* get wireless chraging check gpio */
np = of_find_node_by_name(NULL, "battery");
if (!np) {
pr_err("%s np NULL\n", __func__);
} else {
/* wpc_det */
wpc_det = of_get_named_gpio_flags(np, "battery,wpc_det",
0, &irq_gpio_flags);
if (wpc_det < 0) {
dev_err(dev, "%s : can't get wpc_det = %d\n", __FUNCTION__, wpc_det);
}
}
#endif
#if !defined(CONFIG_MST_IF_PMIC)
mst_pwr_en = of_get_named_gpio(dev->of_node, "sec-mst,mst-pwr-gpio", 0);
printk("[MST] Data Value : %d\n", mst_pwr_en);
/* check if gpio pin is inited */
if (mst_pwr_en < 0) {
printk(KERN_ERR "%s : Cannot create the gpio\n", __func__);
return 1;
}
printk(KERN_ERR "MST_DRV]]] gpio pwr en inited\n");
/* gpio request */
ret = gpio_request(mst_pwr_en, "sec-mst,mst-pwr-gpio");
if (ret) {
printk(KERN_ERR "[MST] failed to get en gpio : %d, %d\n", ret,
mst_pwr_en);
}
/* set gpio direction */
if (!(ret < 0) && (mst_pwr_en > 0)) {
gpio_direction_output(mst_pwr_en, 0);
printk(KERN_ERR "%s : Send Output\n", __func__);
}
#endif
#if defined(CONFIG_MST_NONSECURE)
mst_en = of_get_named_gpio(dev->of_node, "sec-mst,mst-en-gpio", 0);
mst_data = of_get_named_gpio(dev->of_node, "sec-mst,mst-data-gpio", 0);
printk("[MST] NONSECURE Data Value mst_en : %d, mst_data : %d\n", mst_en, mst_data);
/* check if gpio pin is inited */
if (mst_en < 0) {
printk(KERN_ERR "%s : Cannot create the gpio\n", __func__);
return 1;
}
printk(KERN_ERR "MST_DRV]]] gpio en inited\n");
if (mst_data < 0) {
printk(KERN_ERR "%s : Cannot create the gpio\n", __func__);
return 1;
}
printk(KERN_ERR "MST_DRV]]] gpio data inited\n");
/* gpio request */
ret = gpio_request(mst_en, "sec-mst,mst-en-gpio");
if (ret) {
printk(KERN_ERR "[MST] failed to get pd gpio : %d, %d\n", ret, mst_en);
}
ret = gpio_request(mst_data, "sec-mst,mst-data-gpio");
if (ret) {
printk(KERN_ERR "[MST] failed to get data gpio : %d, %d\n", ret, mst_data);
}
/* set gpio direction */
if (!(ret < 0) && (mst_en > 0)) {
gpio_direction_output(mst_en, 0);
printk(KERN_ERR "%s : Send Output\n", __func__);
}
if (!(ret < 0) && (mst_data > 0)) {
gpio_direction_output(mst_data, 0);
printk(KERN_ERR "%s : Send Output\n", __func__);
}
#endif
return 0;
}
static int mst_ldo_device_probe(struct platform_device *pdev)
{
int retval = 0;
#if defined(CONFIG_MST_SUPPORT_GPIO)
struct device *dev = &pdev->dev;
uint8_t is_mst_support = 0;
#endif
printk("%s init start\n", __func__);
#if defined(CONFIG_MST_SUPPORT_GPIO)
/* MST support/non-support node check gpio */
mst_support_check = of_get_named_gpio(dev->of_node, "sec-mst,mst-support-gpio", 0);
printk("[MST] mst_support_check Value : %d\n", mst_support_check);
if (mst_support_check < 0) {
printk(KERN_ERR "%s : Cannot create the gpio\n", __func__);
return -1;
}
printk(KERN_ERR "MST_DRV]]] gpio support_check inited\n");
is_mst_support = gpio_get_value(mst_support_check);
if (is_mst_support == 1) {
printk(KERN_ERR "MST_DRV]]] This device supports MST, %d\n", is_mst_support);
} else {
printk(KERN_ERR "MST_DRV]]] This device doesn't supports MST, %d\n", is_mst_support);
mst_drv_class = class_create(THIS_MODULE, "mstldo");
if (IS_ERR(mst_drv_class)) {
retval = PTR_ERR(mst_drv_class);
goto error;
}
mst_drv_dev = device_create(mst_drv_class,
NULL /* parent */, 0 /* dev_t */,
NULL /* drvdata */,
MST_DRV_DEV);
if (IS_ERR(mst_drv_dev)) {
retval = PTR_ERR(mst_drv_dev);
goto error_destroy;
}
retval = device_create_file(mst_drv_dev, &dev_attr_support);
if (retval)
goto error_destroy;
return -1;
}
#endif
#if defined(CONFIG_MST_NONSECURE)
spin_lock_init(&event_lock);
#endif
if (sec_mst_gpio_init(&pdev->dev))
return -1;
printk(KERN_ALERT "%s\n", __func__);
mst_drv_class = class_create(THIS_MODULE, "mstldo");
if (IS_ERR(mst_drv_class)) {
retval = PTR_ERR(mst_drv_class);
goto error;
}
mst_drv_dev = device_create(mst_drv_class,
NULL /* parent */, 0 /* dev_t */,
NULL /* drvdata */,
MST_DRV_DEV);
if (IS_ERR(mst_drv_dev)) {
retval = PTR_ERR(mst_drv_dev);
goto error_destroy;
}
/* register this mst device with the driver core */
retval = device_create_file(mst_drv_dev, &dev_attr_transmit);
if (retval)
goto error_destroy;
retval = device_create_file(mst_drv_dev, &dev_attr_support);
if (retval)
goto error_destroy;
#if defined(CONFIG_MFC_CHARGER)
retval = device_create_file(mst_drv_dev, &dev_attr_mfc);
if (retval)
goto error_destroy;
#endif
printk(KERN_DEBUG "MST drv driver (%s) is initialized.\n", MST_DRV_DEV);
return 0;
error_destroy:
kfree(mst_drv_dev);
device_destroy(mst_drv_class, 0);
error:
printk(KERN_ERR "%s: MST drv driver initialization failed\n", __FILE__);
return retval;
}
static struct of_device_id mst_match_ldo_table[] = {
{.compatible = "sec-mst",},
{},
};
static int mst_ldo_device_suspend(struct platform_device *dev, pm_message_t state)
{
#if !defined(CONFIG_MST_IF_PMIC)
uint8_t is_mst_pwr_on;
is_mst_pwr_on = gpio_get_value(mst_pwr_en);
if (is_mst_pwr_on == 1) {
pr_info("%s: mst power is on, is_mst_pwr_on = %d\n", __func__, is_mst_pwr_on);
pr_info("%s: mst power off\n", __func__);
of_mst_hw_onoff(0);
} else {
pr_info("%s: mst power is off, is_mst_pwr_on = %d\n", __func__, is_mst_pwr_on);
}
#endif
return 0;
}
#if 0
static int mst_ldo_device_resume(struct platform_device *dev)
{
u64 r0 = 0, r1 = 0, r2 = 0, r3 = 0;
int result = 0;
printk(KERN_INFO "%s\n", __func__);
printk(KERN_INFO "MST_LDO_DRV]]] resume");
//Will Add here
r0 = (0x8300000d);
result = exynos_smc(r0, r1, r2, r3);
if (result == MST_NOT_SUPPORT) {
printk(KERN_INFO
"MST_LDO_DRV]]] resume do nothing after smc : %x\n",
result);
} else {
printk(KERN_INFO
"MST_LDO_DRV]]] resume success after smc : %x\n",
result);
}
rt = result;
return 0;
}
#endif
static struct platform_driver sec_mst_ldo_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "mstldo",
.of_match_table = mst_match_ldo_table,
},
.probe = mst_ldo_device_probe,
.suspend = mst_ldo_device_suspend,
//.resume = mst_ldo_device_resume,
};
static int __init mst_drv_init(void)
{
int ret = 0;
printk(KERN_ERR "%s\n", __func__);
ret = platform_driver_register(&sec_mst_ldo_driver);
printk(KERN_ERR "MST_LDO_DRV]]] init , ret val : %d\n", ret);
return ret;
}
static void __exit mst_drv_exit(void)
{
class_destroy(mst_drv_class);
printk(KERN_ALERT "%s\n", __func__);
}
MODULE_AUTHOR("JASON KANG, j_seok.kang@samsung.com");
MODULE_DESCRIPTION("MST drv driver");
MODULE_VERSION("0.1");
module_init(mst_drv_init);
module_exit(mst_drv_exit);