/* | |
* 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); |