diff options
Diffstat (limited to 'arch/arm/mach-exynos/board-p8ltevzw-modems.c')
-rw-r--r-- | arch/arm/mach-exynos/board-p8ltevzw-modems.c | 904 |
1 files changed, 904 insertions, 0 deletions
diff --git a/arch/arm/mach-exynos/board-p8ltevzw-modems.c b/arch/arm/mach-exynos/board-p8ltevzw-modems.c new file mode 100644 index 0000000..a2e0540 --- /dev/null +++ b/arch/arm/mach-exynos/board-p8ltevzw-modems.c @@ -0,0 +1,904 @@ +/* linux/arch/arm/mach-xxxx/board-p8vzw-modems.c + * Copyright (C) 2010 Samsung Electronics. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/gpio.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/regulator/consumer.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/clk.h> + +/* inlcude platform specific file */ +#include <linux/platform_data/modem_na.h> +#include <mach/sec_modem.h> +#include <mach/gpio.h> +#include <mach/gpio-exynos4.h> +#include <plat/gpio-cfg.h> +#include <mach/regs-mem.h> +#include <plat/regs-srom.h> + +#include <plat/devs.h> +#include <plat/ehci.h> + + +#define IDPRAM_SIZE 0x4000 +#define IDPRAM_PHY_START 0x13A00000 +#define IDPRAM_PHY_END (IDPRAM_PHY_START + IDPRAM_SIZE) +#define MAGIC_DMDL 0x4445444C + +/*S5PV210 Interanl Dpram Special Function Register*/ +#define IDPRAM_MIFCON_INT2APEN (1<<2) +#define IDPRAM_MIFCON_INT2MSMEN (1<<3) +#define IDPRAM_MIFCON_DMATXREQEN_0 (1<<16) +#define IDPRAM_MIFCON_DMATXREQEN_1 (1<<17) +#define IDPRAM_MIFCON_DMARXREQEN_0 (1<<18) +#define IDPRAM_MIFCON_DMARXREQEN_1 (1<<19) +#define IDPRAM_MIFCON_FIXBIT (1<<20) + +#define IDPRAM_MIFPCON_ADM_MODE (1<<6) /* mux / demux mode */ + +#define IDPRAM_DMA_ADR_MASK 0x3FFF +#define IDPRAM_DMA_TX_ADR_0 /* shift 0 */ +#define IDPRAM_DMA_TX_ADR_1 /* shift 16 */ +#define IDPRAM_DMA_RX_ADR_0 /* shift 0 */ +#define IDPRAM_DMA_RX_ADR_1 /* shift 16 */ + +#define IDPRAM_SFR_PHYSICAL_ADDR 0x13A08000 +#define IDPRAM_SFR_SIZE 0x1C + +#define IDPRAM_ADDRESS_DEMUX + +static int __init init_modem(void); +static int p8_lte_ota_reset(void); + +struct idpram_sfr_reg { + unsigned int2ap; + unsigned int2msm; + unsigned mifcon; + unsigned mifpcon; + unsigned msmintclr; + unsigned dma_tx_adr; + unsigned dma_rx_adr; +}; + +/*S5PV210 Internal Dpram GPIO table*/ +struct idpram_gpio_data { + unsigned num; + unsigned cfg; + unsigned pud; + unsigned val; +}; + +static volatile void __iomem *s5pv310_dpram_sfr_va; + +static struct idpram_gpio_data idpram_gpio_address[] = { +#ifdef IDPRAM_ADDRESS_DEMUX + { + .num = EXYNOS4210_GPE1(0), /* MSM_ADDR 0 -12 */ + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE1(1), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE1(2), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE1(3), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE1(4), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE1(5), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE1(6), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE1(7), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE2(0), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE2(1), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE2(2), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE2(3), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE2(4), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE2(5), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, +#endif +}; + +static struct idpram_gpio_data idpram_gpio_data[] = { + { + .num = EXYNOS4210_GPE3(0), /* MSM_DATA 0 - 15 */ + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE3(1), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE3(2), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE3(3), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE3(4), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE3(5), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE3(6), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE3(7), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE4(0), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE4(1), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE4(2), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE4(3), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE4(4), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE4(5), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE4(6), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE4(7), + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, +}; + +static struct idpram_gpio_data idpram_gpio_init_control[] = { + { + .num = EXYNOS4210_GPE0(1), /* MDM_CSn */ + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE0(0), /* MDM_WEn */ + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE0(2), /* MDM_Rn */ + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, { + .num = EXYNOS4210_GPE0(3), /* MDM_IRQn */ + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_UP, + }, +#ifndef IDPRAM_ADDRESS_DEMUX + { + .num = EXYNOS4210_GPE0(4), /* MDM_ADVN */ + .cfg = S3C_GPIO_SFN(0x2), + .pud = S3C_GPIO_PULL_NONE, + }, +#endif +}; + +static void idpram_gpio_cfg(struct idpram_gpio_data *gpio) +{ + printk(KERN_DEBUG "MIF: idpram set gpio num=%d, cfg=0x%x, pud=%d, val=%d\n", + gpio->num, gpio->cfg, gpio->pud, gpio->val); + + s3c_gpio_cfgpin(gpio->num, gpio->cfg); + s3c_gpio_setpull(gpio->num, gpio->pud); + if (gpio->val) + gpio_set_value(gpio->num, gpio->val); +} + +static void idpram_gpio_init(void) +{ + int i; + +#ifdef IDPRAM_ADDRESS_DEMUX + for (i = 0; i < ARRAY_SIZE(idpram_gpio_address); i++) + idpram_gpio_cfg(&idpram_gpio_address[i]); +#endif + + for (i = 0; i < ARRAY_SIZE(idpram_gpio_data); i++) + idpram_gpio_cfg(&idpram_gpio_data[i]); + + for (i = 0; i < ARRAY_SIZE(idpram_gpio_init_control); i++) + idpram_gpio_cfg(&idpram_gpio_init_control[i]); +} + +static void idpram_sfr_init(void) +{ + volatile struct idpram_sfr_reg __iomem *sfr = s5pv310_dpram_sfr_va; + + sfr->mifcon = (IDPRAM_MIFCON_FIXBIT | IDPRAM_MIFCON_INT2APEN | + IDPRAM_MIFCON_INT2MSMEN); +#ifndef IDPRAM_ADDRESS_DEMUX + sfr->mifpcon = (IDPRAM_MIFPCON_ADM_MODE); +#endif +} + +static void idpram_init(void) +{ + struct clk *clk; + + /* enable internal dpram clock */ + clk = clk_get(NULL, "modem"); + if (!clk) + pr_err("MIF: idpram failed to get clock %s\n", __func__); + + clk_enable(clk); + + if (!s5pv310_dpram_sfr_va) { + s5pv310_dpram_sfr_va = (struct idpram_sfr_reg __iomem *) + ioremap_nocache(IDPRAM_SFR_PHYSICAL_ADDR, IDPRAM_SFR_SIZE); + if (!s5pv310_dpram_sfr_va) { + printk(KERN_ERR "MIF: idpram_sfr_base io-remap fail\n"); + /*iounmap(idpram_base);*/ + } + } + + idpram_sfr_init(); +} + +static void idpram_clr_intr(void) +{ + volatile struct idpram_sfr_reg __iomem *sfr = s5pv310_dpram_sfr_va; + sfr->msmintclr = 0xFF; +} + + +/* + magic_code + + access_enable + + fmt_tx_head + fmt_tx_tail + fmt_tx_buff + + raw_tx_head + raw_tx_tail + raw_tx_buff + + fmt_rx_head + fmt_rx_tail + fmt_rx_buff + + raw_rx_head + raw_rx_tail + raw_rx_buff + + padding + + mbx_cp2ap + + mbx_ap2cp + = 2 + + 2 + + 2 + 2 + 2044 + + 2 + 2 + 6128 + + 2 + 2 + 2044 + + 2 + 2 + 6128 + + 16 + + 2 + + 2 + = 16384 +*/ + +#define CBP_DP_FMT_TX_BUFF_SZ 2044 +#define CBP_DP_RAW_TX_BUFF_SZ 6128 +#define CBP_DP_FMT_RX_BUFF_SZ 2044 +#define CBP_DP_RAW_RX_BUFF_SZ 6128 + +#define MAX_CBP_IDPRAM_IPC_DEV (IPC_RAW + 1) /* FMT, RAW */ + +/* +** CDMA target platform data +*/ +static struct modem_io_t cdma_io_devices[] = { + [0] = { + .name = "multipdp", + .id = 0x1, + .format = IPC_MULTI_RAW, + .io_type = IODEV_DUMMY, + .link = LINKDEV_DPRAM, + }, + [1] = { + .name = "cdma_ipc0", + .id = 0x1, + .format = IPC_FMT, + .io_type = IODEV_MISC, + .link = LINKDEV_DPRAM, + }, + [2] = { + .name = "cdma_rfs0", + .id = 0x33, /* 0x13 (ch.id) | 0x20 (mask) */ + .format = IPC_RAW, + .io_type = IODEV_MISC, + .link = LINKDEV_DPRAM, + }, + [3] = { + .name = "cdma_boot0", + .id = 0x1, + .format = IPC_BOOT, + .io_type = IODEV_MISC, + .link = LINKDEV_DPRAM, + }, + [4] = { + .name = "cdma_rmnet0", + .id = 0x2A, + .format = IPC_RAW, + .io_type = IODEV_NET, + .link = LINKDEV_DPRAM, + }, + [5] = { + .name = "cdma_rmnet1", + .id = 0x2B, + .format = IPC_RAW, + .io_type = IODEV_NET, + .link = LINKDEV_DPRAM, + }, + [6] = { + .name = "cdma_rmnet2", + .id = 0x2C, + .format = IPC_RAW, + .io_type = IODEV_NET, + .link = LINKDEV_DPRAM, + }, + [7] = { + .name = "cdma_rmnet3", + .id = 0x2D, + .format = IPC_RAW, + .io_type = IODEV_NET, + .link = LINKDEV_DPRAM, + }, + [8] = { + .name = "cdma_rmnet4", + .id = 0x27, + .format = IPC_RAW, + .io_type = IODEV_NET, + .link = LINKDEV_DPRAM, + }, + [9] = { + .name = "cdma_rmnet5", /* DM Port IO device */ + .id = 0x3A, + .format = IPC_RAW, + .io_type = IODEV_MISC, + .link = LINKDEV_DPRAM, + }, + [10] = { + .name = "cdma_rmnet6", /* AT CMD IO device */ + .id = 0x31, + .format = IPC_RAW, + .io_type = IODEV_MISC, + .link = LINKDEV_DPRAM, + }, + [11] = { + .name = "cdma_ramdump0", + .id = 0x1, + .format = IPC_RAMDUMP, + .io_type = IODEV_MISC, + .link = LINKDEV_DPRAM, + }, + [12] = { + .name = "cdma_cplog", /* cp log io-device */ + .id = 0x3D, + .format = IPC_RAW, + .io_type = IODEV_MISC, + .link = LINKDEV_DPRAM, + }, + [13] = { + .name = "cdma_router", /* AT commands */ + .id = 0x39, + .format = IPC_RAW, + .io_type = IODEV_MISC, + .link = LINKDEV_DPRAM, + }, +}; + +static struct modem_data cdma_modem_data = { + .name = "cbp7.1", + + .gpio_cp_on = GPIO_PHONE_ON, + .gpio_cp_off = GPIO_VIA_PS_HOLD_OFF, + .gpio_cp_reset = GPIO_CP_RST, + .gpio_pda_active = GPIO_PDA_ACTIVE, + .gpio_phone_active = GPIO_PHONE_ACTIVE, + .gpio_ap_wakeup = GPIO_CP_AP_DPRAM_INT, + .gpio_mbx_intr = GPIO_VIA_DPRAM_INT_N, + + .modem_net = CDMA_NETWORK, + .modem_type = VIA_CBP71, + .link_type = LINKDEV_DPRAM, + + .num_iodevs = ARRAY_SIZE(cdma_io_devices), + .iodevs = cdma_io_devices, + + .clear_intr = idpram_clr_intr, + .ota_reset = p8_lte_ota_reset, + .sfr_init = idpram_sfr_init, + .align = 1, /* Adjust the IPC raw and Multi Raw HDLC buffer offsets */ +}; + +static struct resource cdma_modem_res[] = { + [0] = { + .name = "dpram", + .start = IDPRAM_PHY_START, + .end = IDPRAM_PHY_END, + .flags = IORESOURCE_MEM, + }, + [1] = { + .name = "dpram_irq", + .start = IRQ_MODEM_IF, + .end = IRQ_MODEM_IF, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device cdma_modem = { + .name = "modem_if", + .id = 1, + .num_resources = ARRAY_SIZE(cdma_modem_res), + .resource = cdma_modem_res, + .dev = { + .platform_data = &cdma_modem_data, + }, +}; +static int p8_lte_ota_reset(void) +{ + unsigned gpio_cp_rst = cdma_modem_data.gpio_cp_reset; + unsigned gpio_cp_on = cdma_modem_data.gpio_cp_on; + unsigned int *magickey_va; + int i; + + pr_err("[MODEM_IF] %s Modem OTA reset\n", __func__); + magickey_va = ioremap_nocache(IDPRAM_PHY_START, sizeof(unsigned int)); + if (!magickey_va) { + pr_err("%s: ioremap fail\n", __func__); + return -ENOMEM; + } + + gpio_set_value(gpio_cp_on, 1); + msleep(100); + gpio_set_value(gpio_cp_rst, 0); + + for (i = 0; i < 3; i++) { + *magickey_va = MAGIC_DMDL; + if (*magickey_va == MAGIC_DMDL) { + pr_err("magic key is ok!"); + break; + } + } + + msleep(500); + gpio_set_value(gpio_cp_rst, 1); + for (i = 0; i < 3; i++) { + *magickey_va = MAGIC_DMDL; + if (*magickey_va == MAGIC_DMDL) { + pr_err("magic key is ok!"); + break; + } + } + + iounmap(magickey_va); + + return 0; +} +static void config_cdma_modem_gpio(void) +{ + int err; + unsigned gpio_cp_on = cdma_modem_data.gpio_cp_on; + unsigned gpio_cp_off = cdma_modem_data.gpio_cp_off; + unsigned gpio_cp_rst = cdma_modem_data.gpio_cp_reset; + unsigned gpio_pda_active = cdma_modem_data.gpio_pda_active; + unsigned gpio_phone_active = cdma_modem_data.gpio_phone_active; + unsigned gpio_ap_wakeup = cdma_modem_data.gpio_ap_wakeup; + + pr_info("MIF: <%s>\n", __func__); + + if (gpio_cp_on) { + err = gpio_request(gpio_cp_on, "VIACP_ON"); + if (err) + pr_err("fail to request gpio %s\n", "VIACP_ON"); + else + gpio_direction_output(gpio_cp_on, 0); + } + + if (gpio_cp_rst) { + err = gpio_request(gpio_cp_rst, "VAICP_RST"); + if (err) + pr_err("fail to request gpio %s\n", "VIACP_RST"); + else + gpio_direction_output(gpio_cp_rst, 0); + } + + if (gpio_cp_off) { + err = gpio_request(gpio_cp_off, "VAICP_OFF"); + if (err) + pr_err("fail to request gpio %s\n", "VIACP_OFF"); + else + gpio_direction_output(gpio_cp_off, 1); + } + + if (gpio_pda_active) { + err = gpio_request(gpio_pda_active, "PDA_ACTIVE"); + if (err) + pr_err("fail to request gpio %s\n", "PDA_ACTIVE"); + else + gpio_direction_output(gpio_pda_active, 0); + } + + if (gpio_phone_active) { + err = gpio_request(gpio_phone_active, "PHONE_ACTIVE"); + if (err) { + pr_err("fail to request gpio %s\n", "PHONE_ACTIVE"); + } else { + s3c_gpio_cfgpin(gpio_phone_active, S3C_GPIO_SFN(0xF)); + s3c_gpio_setpull(gpio_phone_active, S3C_GPIO_PULL_NONE); + } + } + if (gpio_ap_wakeup) { + err = gpio_request(GPIO_CP_AP_DPRAM_INT, "HOST_WAKEUP"); + if (err) { + pr_err("fail to request gpio %s\n", "HOST_WAKEUP"); + } else { + s3c_gpio_cfgpin(GPIO_CP_AP_DPRAM_INT, \ + S3C_GPIO_SFN(0xF)); + s3c_gpio_setpull(GPIO_CP_AP_DPRAM_INT, \ + S3C_GPIO_PULL_NONE); + } + } + +} + +/* lte target platform data */ +static struct modem_io_t lte_io_devices[] = { + [0] = { + .name = "lte_ipc0", + .id = 0x1, + .format = IPC_FMT, + .io_type = IODEV_MISC, + .link = LINKDEV_USB, + }, + [1] = { + .name = "lte_rmnet0", + .id = 0x2A, + .format = IPC_RAW, + .io_type = IODEV_NET, + .link = LINKDEV_USB, + }, + [2] = { + .name = "lte_rfs0", + .id = 0x0, + .format = IPC_RFS, + .io_type = IODEV_MISC, + .link = LINKDEV_USB, + }, + [3] = { + .name = "lte_boot0", + .id = 0x0, + .format = IPC_BOOT, + .io_type = IODEV_MISC, + .link = LINKDEV_USB, + }, + [4] = { + .name = "lte_rmnet1", + .id = 0x2B, + .format = IPC_RAW, + .io_type = IODEV_NET, + .link = LINKDEV_USB, + }, + [5] = { + .name = "lte_rmnet2", + .id = 0x2C, + .format = IPC_RAW, + .io_type = IODEV_NET, + .link = LINKDEV_USB, + }, + [6] = { + .name = "lte_rmnet3", + .id = 0x2D, + .format = IPC_RAW, + .io_type = IODEV_NET, + .link = LINKDEV_USB, + }, + [7] = { + .name = "lte_multipdp", + .id = 0x1, + .format = IPC_MULTI_RAW, + .io_type = IODEV_DUMMY, + .link = LINKDEV_USB, + }, + [8] = { + .name = "lte_rmnet4", /* DM Port io-device */ + .id = 0x3F, + .format = IPC_RAW, + .io_type = IODEV_MISC, + .link = LINKDEV_USB, + }, + [9] = { + .name = "lte_ramdump0", + .id = 0x0, + .format = IPC_RAMDUMP, + .io_type = IODEV_MISC, + .link = LINKDEV_USB, + }, +}; + +static struct modemlink_pm_data lte_link_pm_data = { + .name = "lte_link_pm", + + .gpio_link_enable = 0, + .gpio_link_active = GPIO_AP2LTE_STATUS, + .gpio_link_hostwake = GPIO_LTE2AP_WAKEUP, + .gpio_link_slavewake = GPIO_AP2LTE_WAKEUP, + + /* + .port_enable = host_port_enable, + .freqlock = ATOMIC_INIT(0), + .cpufreq_lock = exynos_cpu_frequency_lock, + .cpufreq_unlock = exynos_cpu_frequency_unlock, + */ +}; + +static struct modem_data lte_modem_data = { + .name = "cmc220", + .gpio_cp_on = GPIO_220_PMIC_PWRON, + .gpio_reset_req_n = 0, + .gpio_cp_reset = GPIO_CMC_RST, + .gpio_pda_active = 0,/*NOT YET CONNECTED*/ + .gpio_phone_active = GPIO_LTE_ACTIVE, + .gpio_cp_dump_int = GPIO_LTE_ACTIVE,/*TO BE CHECKED*/ + .gpio_cp_warm_reset = 0, + /*.gpio_cp_off = GPIO_220_PMIC_PWRHOLD_OFF,*/ +#ifdef CONFIG_LTE_MODEM_CMC220 + .gpio_cp_off = GPIO_LTE_PS_HOLD_OFF, + .gpio_slave_wakeup = GPIO_AP2LTE_WAKEUP, + .gpio_host_wakeup = GPIO_LTE2AP_WAKEUP, + .gpio_host_active = GPIO_AP2LTE_STATUS, +#endif + .modem_type = SEC_CMC220, + .link_type = LINKDEV_USB, + .modem_net = LTE_NETWORK, + + .num_iodevs = ARRAY_SIZE(lte_io_devices), + .iodevs = lte_io_devices, + + .link_pm_data = <e_link_pm_data, +}; + +static struct resource lte_modem_res[] = { + [0] = { + .name = "lte_phone_active", + /* phone active irq */ + .start = IRQ_LTE_ACTIVE, + .end = IRQ_LTE_ACTIVE, + .flags = IORESOURCE_IRQ, + }, + [1] = { + .name = "lte_host_wakeup", + /* host wakeup irq */ + .start = IRQ_LTE2AP_WAKEUP, + .end = IRQ_LTE2AP_WAKEUP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device lte_modem_wake = { + .name = "modem_lte_wake", + .id = -1, +}; + +static struct platform_device lte_modem = { + .name = "modem_if", + .id = 2, + .num_resources = ARRAY_SIZE(lte_modem_res), + .resource = lte_modem_res, + .dev = { + .platform_data = <e_modem_data, + }, +}; + +static void lte_modem_cfg_gpio(void) +{ + unsigned gpio_cp_on = lte_modem_data.gpio_cp_on; + unsigned gpio_cp_rst = lte_modem_data.gpio_cp_reset; + unsigned gpio_phone_active = lte_modem_data.gpio_phone_active; +#ifdef CONFIG_LTE_MODEM_CMC220 + unsigned gpio_cp_off = lte_modem_data.gpio_cp_off; + unsigned gpio_slave_wakeup = lte_modem_data.gpio_slave_wakeup; + unsigned gpio_host_wakeup = lte_modem_data.gpio_host_wakeup; + unsigned gpio_host_active = lte_modem_data.gpio_host_active; +#endif + + if (gpio_cp_on) { + gpio_request(gpio_cp_on, "LTE_ON"); + gpio_direction_output(gpio_cp_on, 0); + s3c_gpio_setpull(gpio_cp_on, S3C_GPIO_PULL_NONE); + } + + if (gpio_cp_rst) { + gpio_request(gpio_cp_rst, "LTE_RST"); + gpio_direction_output(gpio_cp_rst, 0); + s3c_gpio_setpull(gpio_cp_rst, S3C_GPIO_PULL_NONE); + } + + if (gpio_phone_active) { + gpio_request(gpio_phone_active, "LTE_ACTIVE"); + gpio_direction_input(gpio_phone_active); + s3c_gpio_setpull(gpio_phone_active, S3C_GPIO_PULL_DOWN); + s3c_gpio_cfgpin(gpio_phone_active, S3C_GPIO_SFN(0xF)); + } + +#ifdef CONFIG_LTE_MODEM_CMC220 + if (gpio_cp_off) { + gpio_request(gpio_cp_off, "LTE_OFF"); + gpio_direction_output(gpio_cp_off, 1); + s3c_gpio_setpull(gpio_cp_off, S3C_GPIO_PULL_NONE); + } + + if (gpio_slave_wakeup) { + gpio_request(gpio_slave_wakeup, "LTE_SLAVE_WAKEUP"); + gpio_direction_output(gpio_slave_wakeup, 0); + s3c_gpio_setpull(gpio_slave_wakeup, S3C_GPIO_PULL_NONE); + } + + if (gpio_host_wakeup) { + gpio_request(gpio_host_wakeup, "LTE_HOST_WAKEUP"); + gpio_direction_input(gpio_host_wakeup); + s3c_gpio_setpull(gpio_host_wakeup, S3C_GPIO_PULL_DOWN); + s3c_gpio_cfgpin(gpio_host_wakeup, S3C_GPIO_SFN(0xF)); + } + + if (gpio_host_active) { + gpio_request(gpio_host_active, "LTE_HOST_ACTIVE"); + gpio_direction_output(gpio_host_active, 1); + s3c_gpio_setpull(gpio_host_active, S3C_GPIO_PULL_NONE); + } +#endif +} + +void set_host_states(struct platform_device *pdev, int type) +{ + int spin = 20; + + if (!type) { + gpio_direction_output(lte_modem_data.gpio_host_active, type); + return; + } + + if (gpio_get_value(lte_modem_data.gpio_host_wakeup)) { + gpio_direction_output(lte_modem_data.gpio_host_active, type); + mdelay(10); + while (spin--) { + if (!gpio_get_value(lte_modem_data.gpio_host_wakeup)) + break; + mdelay(10); + } + } else { + pr_err("mif: host wakeup is low\n"); + } +} + +int get_cp_active_state(void) +{ + return gpio_get_value(lte_modem_data.gpio_phone_active); +} + +void set_hsic_lpa_states(int states) +{ + int val = gpio_get_value(lte_modem_data.gpio_cp_reset); + + pr_info("mif: %s: states = %d\n", __func__, states); + + if (val) { + switch (states) { + case STATE_HSIC_LPA_ENTER: + /* + gpio_set_value(lte_modem_data.gpio_link_active, 0); + gpio_set_value(umts_modem_data.gpio_pda_active, 0); + pr_info(LOG_TAG "set hsic lpa enter: " + "active state (%d)" ", pda active (%d)\n", + gpio_get_value( + lte_modem_data.gpio_link_active), + gpio_get_value(umts_modem_data.gpio_pda_active) + ); + */ + break; + case STATE_HSIC_LPA_WAKE: + /* + gpio_set_value(umts_modem_data.gpio_pda_active, 1); + pr_info(LOG_TAG "set hsic lpa wake: " + "pda active (%d)\n", + gpio_get_value(umts_modem_data.gpio_pda_active) + ); + */ + break; + case STATE_HSIC_LPA_PHY_INIT: + /* + gpio_set_value(umts_modem_data.gpio_pda_active, 1); + gpio_set_value(lte_modem_data.gpio_link_slavewake, + 1); + pr_info(LOG_TAG "set hsic lpa phy init: " + "slave wake-up (%d)\n", + gpio_get_value( + lte_modem_data.gpio_link_slavewake) + ); + */ + break; + } + } +} + +/* lte_modem_wake must be registered before the ehci driver */ +void __init modem_p8ltevzw_init(void) +{ + lte_modem_wake.dev.platform_data = <e_modem_data; + platform_device_register(<e_modem_wake); +} + +static int __init init_modem(void) +{ + pr_err("[MDM] <%s>\n", __func__); + + /* interanl dpram gpio configure */ + idpram_gpio_init(); + idpram_init(); + config_cdma_modem_gpio(); + platform_device_register(&cdma_modem); + + /* lte gpios configuration */ + lte_modem_cfg_gpio(); + platform_device_register(<e_modem); + + return 0; +} +late_initcall(init_modem); |