diff options
Diffstat (limited to 'arch/arm/mach-exynos/mdm_device.c')
-rw-r--r-- | arch/arm/mach-exynos/mdm_device.c | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/arch/arm/mach-exynos/mdm_device.c b/arch/arm/mach-exynos/mdm_device.c new file mode 100644 index 0000000..620936e --- /dev/null +++ b/arch/arm/mach-exynos/mdm_device.c @@ -0,0 +1,265 @@ +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/gpio.h> +#include <mach/gpio-exynos4.h> +#include <plat/gpio-cfg.h> +#include <plat/devs.h> +#include <plat/ehci.h> +#include <linux/msm_charm.h> +#include <mach/mdm2.h> +#include "mdm_private.h" + +#include <linux/cpufreq_pegasusq.h> +#include <mach/cpufreq.h> +#include <mach/dev.h> + +static struct resource mdm_resources[] = { + { + .start = GPIO_MDM2AP_ERR_FATAL, + .end = GPIO_MDM2AP_ERR_FATAL, + .name = "MDM2AP_ERRFATAL", + .flags = IORESOURCE_IO, + }, + { + .start = GPIO_AP2MDM_ERR_FATAL, + .end = GPIO_AP2MDM_ERR_FATAL, + .name = "AP2MDM_ERRFATAL", + .flags = IORESOURCE_IO, + }, + { + .start = GPIO_MDM2AP_STATUS, + .end = GPIO_MDM2AP_STATUS, + .name = "MDM2AP_STATUS", + .flags = IORESOURCE_IO, + }, + { + .start = GPIO_AP2MDM_STATUS, + .end = GPIO_AP2MDM_STATUS, + .name = "AP2MDM_STATUS", + .flags = IORESOURCE_IO, + }, + { + .start = GPIO_AP2MDM_PON_RESET_N, + .end = GPIO_AP2MDM_PON_RESET_N, + .name = "AP2MDM_SOFT_RESET", + .flags = IORESOURCE_IO, + }, + { + .start = GPIO_AP2MDM_PMIC_RESET_N, + .end = GPIO_AP2MDM_PMIC_RESET_N, + .name = "AP2MDM_PMIC_PWR_EN", + .flags = IORESOURCE_IO, + }, + { + .start = GPIO_AP2MDM_WAKEUP, + .end = GPIO_AP2MDM_WAKEUP, + .name = "AP2MDM_WAKEUP", + .flags = IORESOURCE_IO, + }, +#ifdef CONFIG_HSIC_EURONLY_APPLY + { + .start = GPIO_MDM2AP_HSIC_READY, + .end = GPIO_MDM2AP_HSIC_READY, + .name = "MDM2AP_HSIC_READY", + .flags = IORESOURCE_IO, + }, +#endif +#ifdef CONFIG_SIM_DETECT + { + .start = GPIO_SIM_DETECT, + .end = GPIO_SIM_DETECT, + .name = "SIM_DETECT", + .flags = IORESOURCE_IO, + }, +#endif + +}; + +#ifdef CONFIG_MDM_HSIC_PM +static struct resource mdm_pm_resource[] = { + { + .start = GPIO_AP2MDM_HSIC_PORT_ACTIVE, + .end = GPIO_AP2MDM_HSIC_PORT_ACTIVE, + .name = "AP2MDM_HSIC_ACTIVE", + .flags = IORESOURCE_IO, + }, + { + .start = GPIO_MDM2AP_HSIC_PWR_ACTIVE, + .end = GPIO_MDM2AP_HSIC_PWR_ACTIVE, + .name = "MDM2AP_DEVICE_PWR_ACTIVE", + .flags = IORESOURCE_IO, + }, + { + .start = GPIO_MDM2AP_HSIC_RESUME_REQ, + .end = GPIO_MDM2AP_HSIC_RESUME_REQ, + .name = "MDM2AP_RESUME_REQ", + .flags = IORESOURCE_IO, + }, +}; + +static int exynos_frequency_lock(struct device *dev); +static int exynos_frequency_unlock(struct device *dev); + +static struct mdm_hsic_pm_platform_data mdm_hsic_pm_pdata = { + .freqlock = ATOMIC_INIT(0), + .freq_lock = exynos_frequency_lock, + .freq_unlock = exynos_frequency_unlock, +}; + +struct platform_device mdm_pm_device = { + .name = "mdm_hsic_pm0", + .id = -1, + .num_resources = ARRAY_SIZE(mdm_pm_resource), + .resource = mdm_pm_resource, +}; +#endif + +static struct mdm_platform_data mdm_platform_data = { + .mdm_version = "3.0", + .ramdump_delay_ms = 3000, + .early_power_on = 1, + .sfr_query = 0, + .vddmin_resource = NULL, +#ifdef CONFIG_USB_EHCI_S5P + .peripheral_platform_device_ehci = &s5p_device_ehci, +#endif +#ifdef CONFIG_USB_OHCI_S5P + .peripheral_platform_device_ohci = &s5p_device_ohci, +#endif + .ramdump_timeout_ms = 120000, +#if defined(CONFIG_SIM_DETECT) + .sim_polarity = 0, +#endif +}; + +static int exynos_frequency_lock(struct device *dev) +{ + unsigned int level, cpufreq = 1400; /* 200 ~ 1400 */ + unsigned int busfreq = 400200; /* 100100 ~ 400200 */ + int ret = 0; + struct device *busdev = dev_get("exynos-busfreq"); + + if (atomic_read(&mdm_hsic_pm_pdata.freqlock) == 0) { + /* cpu frequency lock */ + ret = exynos_cpufreq_get_level(cpufreq * 1000, &level); + if (ret < 0) { + pr_err("ERR: exynos_cpufreq_get_level fail: %d\n", + ret); + goto exit; + } + + ret = exynos_cpufreq_lock(DVFS_LOCK_ID_USB_IF, level); + if (ret < 0) { + pr_err("ERR: exynos_cpufreq_lock fail: %d\n", ret); + goto exit; + } + + /* bus frequncy lock */ + if (!busdev) { + pr_err("ERR: busdev is not exist\n"); + ret = -ENODEV; + goto exit; + } + + ret = dev_lock(busdev, dev, busfreq); + if (ret < 0) { + pr_err("ERR: dev_lock error: %d\n", ret); + goto exit; + } + + /* lock minimum number of cpu cores */ + cpufreq_pegasusq_min_cpu_lock(2); + + atomic_set(&mdm_hsic_pm_pdata.freqlock, 1); + pr_debug("level=%d, cpufreq=%d MHz, busfreq=%06d\n", + level, cpufreq, busfreq); + } +exit: + return ret; +} + +static int exynos_frequency_unlock(struct device *dev) +{ + int ret = 0; + struct device *busdev = dev_get("exynos-busfreq"); + + if (atomic_read(&mdm_hsic_pm_pdata.freqlock) == 1) { + /* cpu frequency unlock */ + exynos_cpufreq_lock_free(DVFS_LOCK_ID_USB_IF); + + /* bus frequency unlock */ + ret = dev_unlock(busdev, dev); + if (ret < 0) { + pr_err("ERR: dev_unlock error: %d\n", ret); + goto exit; + } + + /* unlock minimum number of cpu cores */ + cpufreq_pegasusq_min_cpu_unlock(); + + atomic_set(&mdm_hsic_pm_pdata.freqlock, 0); + pr_debug("success\n"); + } +exit: + return ret; +} + +struct platform_device mdm_device = { + .name = "mdm2_modem", + .id = -1, + .num_resources = ARRAY_SIZE(mdm_resources), + .resource = mdm_resources, +}; + +static int __init init_mdm_modem(void) +{ + int ret; + pr_info("%s: registering modem dev, pm dev\n", __func__); + + mdm_pm_device.dev.platform_data = &mdm_hsic_pm_pdata; + ((struct mdm_hsic_pm_platform_data *) + mdm_pm_device.dev.platform_data)->dev = + &mdm_pm_device.dev; +#ifdef CONFIG_MDM_HSIC_PM + ret = platform_device_register(&mdm_pm_device); + if (ret < 0) { + pr_err("%s: fail to register mdm hsic pm dev(err:%d)\n", + __func__, ret); + return ret; + } +#endif + +#if defined(CONFIG_MACH_P4NOTE) && defined(CONFIG_QC_MODEM) \ + && defined(CONFIG_SIM_DETECT) + mdm_platform_data.sim_polarity = 0; +#endif + +#if (defined(CONFIG_MACH_GC1_USA_VZW) || defined(CONFIG_TARGET_LOCALE_EUR)) \ + && defined(CONFIG_QC_MODEM) && defined(CONFIG_SIM_DETECT) + mdm_platform_data.sim_polarity = 1; +#endif + +#if defined(CONFIG_MACH_KONA) && defined(CONFIG_QC_MODEM) \ + && defined(CONFIG_SIM_DETECT) +#if defined(CONFIG_MACH_KONALTE_USA_ATT) + if (system_rev >= 1) + mdm_platform_data.sim_polarity = 0; + else + mdm_platform_data.sim_polarity = 1; +#else + if (system_rev >= 1) + mdm_platform_data.sim_polarity = 1; + else + mdm_platform_data.sim_polarity = 0; +#endif +#endif + mdm_device.dev.platform_data = &mdm_platform_data; + ret = platform_device_register(&mdm_device); + if (ret < 0) { + pr_err("%s: fail to register mdm modem dev(err:%d)\n", + __func__, ret); + return ret; + } + return 0; +} +module_init(init_mdm_modem); |