aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-exynos/board-t0cu-duos-modems.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-exynos/board-t0cu-duos-modems.c')
-rw-r--r--arch/arm/mach-exynos/board-t0cu-duos-modems.c1160
1 files changed, 1160 insertions, 0 deletions
diff --git a/arch/arm/mach-exynos/board-t0cu-duos-modems.c b/arch/arm/mach-exynos/board-t0cu-duos-modems.c
new file mode 100644
index 0000000..30e93ca
--- /dev/null
+++ b/arch/arm/mach-exynos/board-t0cu-duos-modems.c
@@ -0,0 +1,1160 @@
+/* linux/arch/arm/mach-xxxx/board-t0cu-duos-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.
+ */
+
+/* Modem configuraiton for T0_CU (P-Q + ESC6270)*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <mach/gpio-exynos4.h>
+#include <plat/gpio-cfg.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+
+#include <linux/platform_data/modem.h>
+#include <mach/sec_modem.h>
+
+#if defined(CONFIG_LINK_DEVICE_PLD)
+#include <linux/spi/spi.h>
+#include <mach/pld_pdata.h>
+#endif
+
+#if defined(CONFIG_GSM_MODEM_ESC6270)
+#include <linux/interrupt.h>
+#include <linux/io.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>
+
+#define SROM_CS0_BASE 0x04000000
+#define SROM_WIDTH 0x01000000
+
+#if defined(CONFIG_LINK_DEVICE_PLD)
+#define SROM_NUM_ADDR_BITS 15
+#else
+#define SROM_NUM_ADDR_BITS 14
+#endif
+
+/*
+ * For SROMC Configuration:
+ * SROMC_ADDR_BYTE enable for byte access
+ */
+#define SROMC_DATA_16 0x1
+#define SROMC_ADDR_BYTE 0x2
+#define SROMC_WAIT_EN 0x4
+#define SROMC_BYTE_EN 0x8
+#define SROMC_MASK 0xF
+
+/* Memory attributes */
+enum sromc_attr {
+ MEM_DATA_BUS_8BIT = 0x00000000,
+ MEM_DATA_BUS_16BIT = 0x00000001,
+ MEM_BYTE_ADDRESSABLE = 0x00000002,
+ MEM_WAIT_EN = 0x00000004,
+ MEM_BYTE_EN = 0x00000008,
+
+};
+
+/* DPRAM configuration */
+struct sromc_cfg {
+ enum sromc_attr attr;
+ unsigned size;
+ unsigned csn; /* CSn # */
+ unsigned addr; /* Start address (physical) */
+ unsigned end; /* End address (physical) */
+};
+
+/* DPRAM access timing configuration */
+struct sromc_access_cfg {
+ u32 tacs; /* Address set-up before CSn */
+ u32 tcos; /* Chip selection set-up before OEn */
+ u32 tacc; /* Access cycle */
+ u32 tcoh; /* Chip selection hold on OEn */
+ u32 tcah; /* Address holding time after CSn */
+ u32 tacp; /* Page mode access cycle at Page mode */
+ u32 pmc; /* Page Mode config */
+};
+
+/* For MDM6600 EDPRAM (External DPRAM) */
+#if defined(CONFIG_LINK_DEVICE_PLD)
+#define MSM_EDPRAM_SIZE 0x10000 /* 8 KB (virtual)*/
+#else
+#define MSM_EDPRAM_SIZE 0x4000 /* 16 KB */
+#endif
+
+
+#define INT_MASK_REQ_ACK_F 0x0020
+#define INT_MASK_REQ_ACK_R 0x0010
+#define INT_MASK_RES_ACK_F 0x0008
+#define INT_MASK_RES_ACK_R 0x0004
+#define INT_MASK_SEND_F 0x0002
+#define INT_MASK_SEND_R 0x0001
+
+#define INT_MASK_REQ_ACK_RFS 0x0400 /* Request RES_ACK_RFS */
+#define INT_MASK_RES_ACK_RFS 0x0200 /* Response of REQ_ACK_RFS */
+#define INT_MASK_SEND_RFS 0x0100 /* Indicate sending RFS data */
+
+
+#if (MSM_EDPRAM_SIZE == 0x4000)
+/*
+ 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 MSM_DP_FMT_TX_BUFF_SZ 2044
+#define MSM_DP_RAW_TX_BUFF_SZ 6128
+#define MSM_DP_FMT_RX_BUFF_SZ 2044
+#define MSM_DP_RAW_RX_BUFF_SZ 6128
+
+#define MAX_MSM_EDPRAM_IPC_DEV 2 /* FMT, RAW */
+
+struct msm_edpram_ipc_cfg {
+ u16 magic;
+ u16 access;
+
+ u16 fmt_tx_head;
+ u16 fmt_tx_tail;
+ u8 fmt_tx_buff[MSM_DP_FMT_TX_BUFF_SZ];
+
+ u16 raw_tx_head;
+ u16 raw_tx_tail;
+ u8 raw_tx_buff[MSM_DP_RAW_TX_BUFF_SZ];
+
+ u16 fmt_rx_head;
+ u16 fmt_rx_tail;
+ u8 fmt_rx_buff[MSM_DP_FMT_RX_BUFF_SZ];
+
+ u16 raw_rx_head;
+ u16 raw_rx_tail;
+ u8 raw_rx_buff[MSM_DP_RAW_RX_BUFF_SZ];
+
+ u8 padding[16];
+ u16 mbx_ap2cp;
+ u16 mbx_cp2ap;
+};
+
+
+/*
+------------------
+Buffer : 15KByte
+------------------
+Reserved: 1014Byte
+------------------
+SIZE: 2Byte
+------------------
+TAG: 2Byte
+------------------
+COUNT: 2Byte
+------------------
+AP -> CP Intr : 2Byte
+------------------
+CP -> AP Intr : 2Byte
+------------------
+*/
+#define DP_BOOT_CLEAR_OFFSET 4
+#define DP_BOOT_RSRVD_OFFSET 0x3C00
+#define DP_BOOT_SIZE_OFFSET 0x3FF6
+#define DP_BOOT_TAG_OFFSET 0x3FF8
+#define DP_BOOT_COUNT_OFFSET 0x3FFA
+
+#define DP_BOOT_FRAME_SIZE_LIMIT 0x3C00 /* 15KB = 15360byte = 0x3C00 */
+
+#elif (MSM_EDPRAM_SIZE == 0x10000)
+
+/*
+ mbx_ap2cp + 0x0
+ magic_code +
+ access_enable +
+ padding +
+ mbx_cp2ap + 0x1000
+ magic_code +
+ access_enable +
+ padding +
+ fmt_tx_head + fmt_tx_tail + fmt_tx_buff + 0x2000
+ raw_tx_head + raw_tx_tail + raw_tx_buff +
+ fmt_rx_head + fmt_rx_tail + fmt_rx_buff + 0x3000
+ raw_rx_head + raw_rx_tail + raw_rx_buff +
+ = 2 +
+ 4094 +
+ 2 +
+ 4094 +
+ 2 +
+ 2 +
+ 2 + 2 + 1020 +
+ 2 + 2 + 3064 +
+ 2 + 2 + 1020 +
+ 2 + 2 + 3064
+ */
+
+#define MSM_DP_FMT_TX_BUFF_SZ 1024
+#define MSM_DP_RAW_TX_BUFF_SZ 3072
+#define MSM_DP_FMT_RX_BUFF_SZ 1024
+#define MSM_DP_RAW_RX_BUFF_SZ 3072
+
+#define MAX_MSM_EDPRAM_IPC_DEV 2 /* FMT, RAW */
+
+struct msm_edpram_ipc_cfg {
+ u16 mbx_ap2cp;
+ u16 magic_ap2cp;
+ u16 access_ap2cp;
+ u16 fmt_tx_head;
+ u16 raw_tx_head;
+ u16 fmt_rx_tail;
+ u16 raw_rx_tail;
+ u16 temp1;
+ u8 padding1[4080];
+
+ u16 mbx_cp2ap;
+ u16 magic_cp2ap;
+ u16 access_cp2ap;
+ u16 fmt_tx_tail;
+ u16 raw_tx_tail;
+ u16 fmt_rx_head;
+ u16 raw_rx_head;
+ u16 temp2;
+ u8 padding2[4080];
+
+ u8 fmt_tx_buff[MSM_DP_FMT_TX_BUFF_SZ];
+ u8 raw_tx_buff[MSM_DP_RAW_TX_BUFF_SZ];
+ u8 fmt_rx_buff[MSM_DP_FMT_RX_BUFF_SZ];
+ u8 raw_rx_buff[MSM_DP_RAW_RX_BUFF_SZ];
+
+ u8 padding3[16384];
+
+ u16 address_buffer;
+};
+
+#define DP_BOOT_CLEAR_OFFSET 0
+#define DP_BOOT_RSRVD_OFFSET 0
+#define DP_BOOT_SIZE_OFFSET 0x2
+#define DP_BOOT_TAG_OFFSET 0x4
+#define DP_BOOT_COUNT_OFFSET 0x6
+
+#define DP_BOOT_FRAME_SIZE_LIMIT 0x1000 /* 15KB = 15360byte = 0x3C00 */
+
+#else
+/*
+------------------
+Buffer : 31KByte
+------------------
+Reserved: 1014Byte
+------------------
+SIZE: 2Byte
+------------------
+TAG: 2Byte
+------------------
+COUNT: 2Byte
+------------------
+AP -> CP Intr : 2Byte
+------------------
+CP -> AP Intr : 2Byte
+------------------
+*/
+#define DP_BOOT_CLEAR_OFFSET 4
+#define DP_BOOT_RSRVD_OFFSET 0x7C00
+#define DP_BOOT_SIZE_OFFSET 0x7FF6
+#define DP_BOOT_TAG_OFFSET 0x7FF8
+#define DP_BOOT_COUNT_OFFSET 0x7FFA
+
+#define DP_BOOT_FRAME_SIZE_LIMIT 0x7C00 /* 31KB = 31744byte = 0x7C00 */
+#endif
+
+static struct dpram_ipc_map gsm_ipc_map;
+
+#if defined(CONFIG_LINK_DEVICE_PLD)
+static struct sromc_cfg gsm_edpram_cfg = {
+ .attr = (MEM_DATA_BUS_8BIT),
+ .size = 0x10000,
+};
+#else
+static struct sromc_cfg gsm_edpram_cfg = {
+ .attr = (MEM_DATA_BUS_16BIT | MEM_WAIT_EN | MEM_BYTE_EN),
+ .size = MSM_EDPRAM_SIZE,
+};
+#endif
+
+static struct sromc_access_cfg gsm_edpram_access_cfg[] = {
+ [DPRAM_SPEED_LOW] = {
+ .tacs = 0x2 << 28,
+ .tcos = 0x2 << 24,
+ .tacc = 0x3 << 16,
+ .tcoh = 0x2 << 12,
+ .tcah = 0x2 << 8,
+ .tacp = 0x2 << 4,
+ .pmc = 0x0 << 0,
+ },
+};
+
+static struct modemlink_dpram_control gsm_edpram_ctrl = {
+ .dp_type = EXT_DPRAM,
+
+ .dpram_irq = ESC_DPRAM_INT_IRQ,
+ .dpram_irq_flags = IRQF_TRIGGER_FALLING,
+
+ .max_ipc_dev = IPC_RFS,
+ .ipc_map = &gsm_ipc_map,
+
+ .boot_size_offset = DP_BOOT_SIZE_OFFSET,
+ .boot_tag_offset = DP_BOOT_TAG_OFFSET,
+ .boot_count_offset = DP_BOOT_COUNT_OFFSET,
+ .max_boot_frame_size = DP_BOOT_FRAME_SIZE_LIMIT,
+
+#if defined(CONFIG_LINK_DEVICE_PLD)
+ .aligned = 1,
+#endif
+};
+
+/*
+** GSM target platform data
+*/
+#if defined(CONFIG_LINK_DEVICE_PLD)
+static struct modem_io_t gsm_io_devices[] = {
+ [0] = {
+ .name = "gsm_ipc0",
+ .id = 0x01,
+ .format = IPC_FMT,
+ .io_type = IODEV_MISC,
+ .links = LINKTYPE(LINKDEV_PLD),
+ },
+ [1] = {
+ .name = "gsm_rfs0",
+ .id = 0x28,
+ .format = IPC_RAW,
+ .io_type = IODEV_MISC,
+ .links = LINKTYPE(LINKDEV_PLD),
+ },
+ [2] = {
+ .name = "gsm_boot0",
+ .id = 0x1,
+ .format = IPC_BOOT,
+ .io_type = IODEV_MISC,
+ .links = LINKTYPE(LINKDEV_PLD),
+ },
+ [3] = {
+ .name = "gsm_multi_pdp",
+ .id = 0x1,
+ .format = IPC_MULTI_RAW,
+ .io_type = IODEV_DUMMY,
+ .links = LINKTYPE(LINKDEV_PLD),
+ },
+ [4] = {
+ .name = "gsm_rmnet0",
+ .id = 0x2A,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .links = LINKTYPE(LINKDEV_PLD),
+ },
+ [5] = {
+ .name = "gsm_rmnet1",
+ .id = 0x2B,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .links = LINKTYPE(LINKDEV_PLD),
+ },
+ [6] = {
+ .name = "gsm_rmnet2",
+ .id = 0x2C,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .links = LINKTYPE(LINKDEV_PLD),
+ },
+ [7] = {
+ .name = "gsm_router",
+ .id = 0x39,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .links = LINKTYPE(LINKDEV_PLD),
+ },
+ [8] = {
+ .name = "gsm_csd",
+ .id = 0x21,
+ .format = IPC_RAW,
+ .io_type = IODEV_MISC,
+ .links = LINKTYPE(LINKDEV_PLD),
+ },
+ [9] = {
+ .name = "gsm_ramdump0",
+ .id = 0x1,
+ .format = IPC_RAMDUMP,
+ .io_type = IODEV_MISC,
+ .links = LINKTYPE(LINKDEV_PLD),
+ },
+ [10] = {
+ .name = "gsm_loopback0",
+ .id = 0x3F,
+ .format = IPC_RAW,
+ .io_type = IODEV_MISC,
+ .links = LINKTYPE(LINKDEV_PLD),
+ },
+};
+#else
+static struct modem_io_t gsm_io_devices[] = {
+ [0] = {
+ .name = "gsm_ipc0",
+ .id = 0x01,
+ .format = IPC_FMT,
+ .io_type = IODEV_MISC,
+ .links = LINKTYPE(LINKDEV_DPRAM),
+ },
+ [1] = {
+ .name = "gsm_rfs0",
+ .id = 0x28,
+ .format = IPC_RAW,
+ .io_type = IODEV_MISC,
+ .links = LINKTYPE(LINKDEV_DPRAM),
+ },
+ [2] = {
+ .name = "gsm_boot0",
+ .id = 0x1,
+ .format = IPC_BOOT,
+ .io_type = IODEV_MISC,
+ .links = LINKTYPE(LINKDEV_DPRAM),
+ },
+ [3] = {
+ .name = "gsm_multi_pdp",
+ .id = 0x1,
+ .format = IPC_MULTI_RAW,
+ .io_type = IODEV_DUMMY,
+ .links = LINKTYPE(LINKDEV_DPRAM),
+ },
+ [4] = {
+ .name = "gsm_rmnet0",
+ .id = 0x2A,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .links = LINKTYPE(LINKDEV_DPRAM),
+ },
+ [5] = {
+ .name = "gsm_rmnet1",
+ .id = 0x2B,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .links = LINKTYPE(LINKDEV_DPRAM),
+ },
+ [6] = {
+ .name = "gsm_rmnet2",
+ .id = 0x2C,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .links = LINKTYPE(LINKDEV_DPRAM),
+ },
+ [7] = {
+ .name = "gsm_router",
+ .id = 0x39,
+ .format = IPC_RAW,
+ .io_type = IODEV_NET,
+ .links = LINKTYPE(LINKDEV_DPRAM),
+ },
+ [8] = {
+ .name = "gsm_csd",
+ .id = 0x21,
+ .format = IPC_RAW,
+ .io_type = IODEV_MISC,
+ .links = LINKTYPE(LINKDEV_DPRAM),
+ },
+ [9] = {
+ .name = "gsm_ramdump0",
+ .id = 0x1,
+ .format = IPC_RAMDUMP,
+ .io_type = IODEV_MISC,
+ .links = LINKTYPE(LINKDEV_DPRAM),
+ },
+ [10] = {
+ .name = "gsm_loopback0",
+ .id = 0x3F,
+ .format = IPC_RAW,
+ .io_type = IODEV_MISC,
+ .links = LINKTYPE(LINKDEV_DPRAM),
+ },
+};
+#endif
+
+static struct modem_data gsm_modem_data = {
+ .name = "esc6270",
+
+ .gpio_cp_on = GPIO_CP2_MSM_PWRON,
+ .gpio_cp_off = 0,
+ .gpio_reset_req_n = 0, /* GPIO_CP_MSM_PMU_RST, */
+ .gpio_cp_reset = GPIO_CP2_MSM_RST,
+ .gpio_pda_active = 0,
+ .gpio_phone_active = GPIO_ESC_PHONE_ACTIVE,
+ .gpio_flm_uart_sel = GPIO_BOOT_SW_SEL_CP2,
+
+ .gpio_dpram_int = GPIO_ESC_DPRAM_INT,
+
+ .gpio_cp_dump_int = 0,
+ .gpio_cp_warm_reset = 0,
+
+#if defined(CONFIG_LINK_DEVICE_PLD)
+ .gpio_fpga1_creset = GPIO_FPGA1_CRESET,
+ .gpio_fpga1_cdone = GPIO_FPGA1_CDONE,
+ .gpio_fpga1_rst_n = GPIO_FPGA1_RST_N,
+ .gpio_fpga1_cs_n = GPIO_FPGA1_CS_N,
+#endif
+
+ .use_handover = false,
+
+ .modem_net = CDMA_NETWORK,
+ .modem_type = QC_ESC6270,
+#if defined(CONFIG_LINK_DEVICE_PLD)
+ .link_types = LINKTYPE(LINKDEV_PLD),
+#else
+ .link_types = LINKTYPE(LINKDEV_DPRAM),
+#endif
+
+ .link_name = "esc6270_edpram",
+ .dpram_ctl = &gsm_edpram_ctrl,
+
+ .ipc_version = SIPC_VER_41,
+
+ .num_iodevs = ARRAY_SIZE(gsm_io_devices),
+ .iodevs = gsm_io_devices,
+};
+
+static struct resource gsm_modem_res[] = {
+ [0] = {
+ .name = "cp_active_irq",
+ .start = ESC_PHONE_ACTIVE_IRQ,
+ .end = ESC_PHONE_ACTIVE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ [1] = {
+ .name = "dpram_irq",
+ .start = ESC_DPRAM_INT_IRQ,
+ .end = ESC_DPRAM_INT_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device gsm_modem = {
+ .name = "modem_if",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(gsm_modem_res),
+ .resource = gsm_modem_res,
+ .dev = {
+ .platform_data = &gsm_modem_data,
+ },
+};
+
+static void config_dpram_port_gpio(void)
+{
+ int addr_bits = SROM_NUM_ADDR_BITS;
+
+ pr_info("[MDM] <%s> address line = %d bits\n", __func__, addr_bits);
+
+ /*
+ ** Config DPRAM address/data GPIO pins
+ */
+
+ /* Set GPIO for dpram address */
+ switch (addr_bits) {
+ case 0:
+ break;
+
+ case 13 ... 14:
+ s3c_gpio_cfgrange_nopull(EXYNOS4_GPY3(0), EXYNOS4_GPIO_Y3_NR,
+ S3C_GPIO_SFN(2));
+ s3c_gpio_cfgrange_nopull(EXYNOS4_GPY4(0),
+ addr_bits - EXYNOS4_GPIO_Y3_NR,
+ S3C_GPIO_SFN(2));
+ pr_info("[MDM] <%s> last data gpio EXYNOS4_GPY4(0) ~ %d\n",
+ __func__, addr_bits - EXYNOS4_GPIO_Y3_NR);
+ break;
+
+ case 15:
+ s3c_gpio_cfgrange_nopull(EXYNOS4_GPY3(0), EXYNOS4_GPIO_Y3_NR,
+ S3C_GPIO_SFN(2));
+ s3c_gpio_cfgrange_nopull(EXYNOS4_GPY4(0), EXYNOS4_GPIO_Y4_NR,
+ S3C_GPIO_SFN(2));
+ pr_info("[MDM] <%s> last data gpio EXYNOS4_GPY4(0) ~ %d\n",
+ __func__, EXYNOS4_GPIO_Y4_NR);
+ break;
+
+ default:
+ pr_err("[MDM/E] <%s> Invalid addr_bits!!!\n", __func__);
+ return;
+ }
+
+ /* Set GPIO for dpram data - 16bit */
+#if defined(CONFIG_LINK_DEVICE_PLD)
+ s3c_gpio_cfgrange_nopull(EXYNOS4_GPY5(0), 8, S3C_GPIO_SFN(2));
+#elif defined(CONFIG_LINK_DEVICE_DPRAM)
+ s3c_gpio_cfgrange_nopull(EXYNOS4_GPY5(0), 8, S3C_GPIO_SFN(2));
+ s3c_gpio_cfgrange_nopull(EXYNOS4_GPY6(0), 8, S3C_GPIO_SFN(2));
+#endif
+
+ /* Setup SROMC CSn pins */
+ s3c_gpio_cfgpin(GPIO_DPRAM_CSN1, S3C_GPIO_SFN(2));
+
+#if defined(CONFIG_GSM_MODEM_ESC6270)
+ s3c_gpio_cfgpin(GPIO_DPRAM_CSN0, S3C_GPIO_SFN(2));
+#endif
+
+ /* Config OEn, WEn */
+ s3c_gpio_cfgrange_nopull(GPIO_DPRAM_REN, 2, S3C_GPIO_SFN(2));
+
+ /* Config LBn, UBn */
+ s3c_gpio_cfgrange_nopull(GPIO_DPRAM_LBN, 2, S3C_GPIO_SFN(2));
+
+ /* Config BUSY */
+#if !defined(CONFIG_LINK_DEVICE_PLD)
+ s3c_gpio_cfgpin(GPIO_DPRAM_BUSY, S3C_GPIO_SFN(2));
+#endif
+}
+
+
+static void init_sromc(void)
+{
+ struct clk *clk = NULL;
+
+ /* SROMC clk enable */
+ clk = clk_get(NULL, "sromc");
+ if (!clk) {
+ pr_err("[MDM/E] <%s> SROMC clock gate fail\n", __func__);
+ return;
+ }
+ clk_enable(clk);
+}
+
+static void setup_sromc(unsigned csn, struct sromc_cfg *cfg,
+ struct sromc_access_cfg *acc_cfg)
+{
+ unsigned bw = 0;
+ unsigned bc = 0;
+ void __iomem *bank_sfr = S5P_SROM_BC0 + (4 * csn);
+
+ pr_err("[MDM] <%s> SROMC settings for CS%d...\n", __func__, csn);
+
+ bw = __raw_readl(S5P_SROM_BW);
+ bc = __raw_readl(bank_sfr);
+ pr_err("[MDM] <%s> Old SROMC settings = BW(0x%08X), BC%d(0x%08X)\n",
+ __func__, bw, csn, bc);
+
+ /* Set the BW control field for the CSn */
+ bw &= ~(SROMC_MASK << (csn * 4));
+
+ if (cfg->attr & MEM_DATA_BUS_16BIT)
+ bw |= (SROMC_DATA_16 << (csn * 4));
+
+ if (cfg->attr & MEM_WAIT_EN)
+ bw |= (SROMC_WAIT_EN << (csn * 4));
+
+ if (cfg->attr & MEM_BYTE_EN)
+ bw |= (SROMC_BYTE_EN << (csn * 4));
+
+ writel(bw, S5P_SROM_BW);
+
+ /* Set SROMC memory access timing for the CSn */
+ bc = acc_cfg->tacs | acc_cfg->tcos | acc_cfg->tacc |
+ acc_cfg->tcoh | acc_cfg->tcah | acc_cfg->tacp | acc_cfg->pmc;
+
+ writel(bc, bank_sfr);
+
+ /* Verify SROMC settings */
+ bw = __raw_readl(S5P_SROM_BW);
+ bc = __raw_readl(bank_sfr);
+ pr_err("[MDM] <%s> New SROMC settings = BW(0x%08X), BC%d(0x%08X)\n",
+ __func__, bw, csn, bc);
+}
+
+
+void config_gsm_modem_gpio(void)
+{
+ int err = 0;
+ unsigned gpio_cp_on = gsm_modem_data.gpio_cp_on;
+ unsigned gpio_cp_off = gsm_modem_data.gpio_cp_off;
+ unsigned gpio_rst_req_n = gsm_modem_data.gpio_reset_req_n;
+ unsigned gpio_cp_rst = gsm_modem_data.gpio_cp_reset;
+ unsigned gpio_pda_active = gsm_modem_data.gpio_pda_active;
+ unsigned gpio_phone_active = gsm_modem_data.gpio_phone_active;
+ unsigned gpio_flm_uart_sel = gsm_modem_data.gpio_flm_uart_sel;
+ unsigned gpio_dpram_int = gsm_modem_data.gpio_dpram_int;
+
+#if defined(CONFIG_LINK_DEVICE_PLD)
+ unsigned gpio_fpga1_creset = gsm_modem_data.gpio_fpga1_creset;
+ unsigned gpio_fpga1_cdone = gsm_modem_data.gpio_fpga1_cdone;
+ unsigned gpio_fpga1_rst_n = gsm_modem_data.gpio_fpga1_rst_n;
+ unsigned gpio_fpga1_cs_n = gsm_modem_data.gpio_fpga1_cs_n;
+#endif
+
+ pr_err("[MODEMS] <%s>\n", __func__);
+
+ if (gpio_pda_active) {
+ err = gpio_request(gpio_pda_active, "PDA_ACTIVE");
+ if (err) {
+ pr_err("fail to request gpio %s, gpio %d, errno %d\n",
+ "PDA_ACTIVE", gpio_pda_active, err);
+ } else {
+ gpio_direction_output(gpio_pda_active, 1);
+ s3c_gpio_setpull(gpio_pda_active, S3C_GPIO_PULL_NONE);
+ gpio_set_value(gpio_pda_active, 0);
+ }
+ }
+
+ if (gpio_phone_active) {
+ err = gpio_request(gpio_phone_active, "ESC_ACTIVE");
+ if (err) {
+ pr_err("fail to request gpio %s, gpio %d, errno %d\n",
+ "ESC_ACTIVE", gpio_phone_active, err);
+ } else {
+ s3c_gpio_cfgpin(gpio_phone_active, S3C_GPIO_SFN(0xF));
+ s3c_gpio_setpull(gpio_phone_active, S3C_GPIO_PULL_NONE);
+ irq_set_irq_type(gpio_phone_active, IRQ_TYPE_EDGE_BOTH);
+ }
+ }
+
+ if (gpio_flm_uart_sel) {
+ err = gpio_request(gpio_flm_uart_sel, "BOOT_SW_SEL2");
+ if (err) {
+ pr_err("fail to request gpio %s, gpio %d, errno %d\n",
+ "BOOT_SW_SEL2", gpio_flm_uart_sel, err);
+ } else {
+ gpio_direction_output(gpio_flm_uart_sel, 1);
+ s3c_gpio_setpull(gpio_flm_uart_sel, S3C_GPIO_PULL_NONE);
+ gpio_set_value(gpio_flm_uart_sel, 1);
+ }
+ }
+
+ if (gpio_cp_on) {
+ err = gpio_request(gpio_cp_on, "ESC_ON");
+ if (err) {
+ pr_err("fail to request gpio %s, gpio %d, errno %d\n",
+ "ESC_ON", gpio_cp_on, err);
+ } else {
+ gpio_direction_output(gpio_cp_on, 0);
+ s3c_gpio_setpull(gpio_cp_on, S3C_GPIO_PULL_NONE);
+ s5p_gpio_set_drvstr(gpio_cp_on, S5P_GPIO_DRVSTR_LV1);
+ gpio_set_value(gpio_cp_on, 0);
+ }
+ }
+
+ if (gpio_cp_off) {
+ err = gpio_request(gpio_cp_off, "ESC_OFF");
+ if (err) {
+ pr_err("fail to request gpio %s, gpio %d, errno %d\n",
+ "ESC_OFF", (gpio_cp_off), err);
+ } else {
+ gpio_direction_output(gpio_cp_off, 1);
+ s3c_gpio_setpull(gpio_cp_off, S3C_GPIO_PULL_NONE);
+ gpio_set_value(gpio_cp_off, 1);
+ }
+ }
+
+ if (gpio_rst_req_n) {
+ err = gpio_request(gpio_rst_req_n, "ESC_RST_REQ");
+ if (err) {
+ pr_err("fail to request gpio %s, gpio %d, errno %d\n",
+ "ESC_RST_REQ", gpio_rst_req_n, err);
+ } else {
+ gpio_direction_output(gpio_rst_req_n, 1);
+ s3c_gpio_setpull(gpio_rst_req_n, S3C_GPIO_PULL_NONE);
+ }
+ gpio_set_value(gpio_rst_req_n, 0);
+ }
+
+ if (gpio_cp_rst) {
+ err = gpio_request(gpio_cp_rst, "ESC_RST");
+ if (err) {
+ pr_err("fail to request gpio %s, gpio %d, errno %d\n",
+ "ESC_RST", gpio_cp_rst, err);
+ } else {
+ gpio_direction_output(gpio_cp_rst, 0);
+ s3c_gpio_setpull(gpio_cp_rst, S3C_GPIO_PULL_NONE);
+ s5p_gpio_set_drvstr(gpio_cp_rst, S5P_GPIO_DRVSTR_LV4);
+ }
+ gpio_set_value(gpio_cp_rst, 0);
+ }
+
+ if (gpio_dpram_int) {
+ err = gpio_request(gpio_dpram_int, "ESC_DPRAM_INT");
+ if (err) {
+ pr_err("fail to request gpio %s, gpio %d, errno %d\n",
+ "ESC_DPRAM_INT", gpio_dpram_int, err);
+ } else {
+ /* Configure as a wake-up source */
+ s3c_gpio_cfgpin(gpio_dpram_int, S3C_GPIO_SFN(0xF));
+ s3c_gpio_setpull(gpio_dpram_int, S3C_GPIO_PULL_NONE);
+ }
+ }
+
+ err = gpio_request(EXYNOS4_GPA1(4), "AP_CP2_UART_RXD");
+ if (err) {
+ pr_err("fail to request gpio %s, gpio %d, errno %d\n",
+ "AP_CP2_UART_RXD", EXYNOS4_GPA1(4), err);
+ } else {
+ s3c_gpio_cfgpin(EXYNOS4_GPA1(4), S3C_GPIO_SFN(0x2));
+ s3c_gpio_setpull(EXYNOS4_GPA1(4), S3C_GPIO_PULL_NONE);
+ }
+
+ err = gpio_request(EXYNOS4_GPA1(5), "AP_CP2_UART_TXD");
+ if (err) {
+ pr_err("fail to request gpio %s, gpio %d, errno %d\n",
+ "AP_CP2_UART_TXD", EXYNOS4_GPA1(5), err);
+ } else {
+ s3c_gpio_cfgpin(EXYNOS4_GPA1(5), S3C_GPIO_SFN(0x2));
+ s3c_gpio_setpull(EXYNOS4_GPA1(5), S3C_GPIO_PULL_NONE);
+ }
+
+#if defined(CONFIG_LINK_DEVICE_PLD)
+ if (gpio_fpga1_creset) {
+ err = gpio_request(gpio_fpga1_creset, "FPGA1_CRESET");
+ if (err) {
+ pr_err("fail to request gpio %s, gpio %d, errno %d\n",
+ "FPGA1_CRESET", gpio_fpga1_creset, err);
+ } else {
+ gpio_direction_output(gpio_fpga1_creset, 0);
+ s3c_gpio_setpull(gpio_fpga1_creset, S3C_GPIO_PULL_NONE);
+ }
+ }
+
+ if (gpio_fpga1_cdone) {
+ err = gpio_request(gpio_fpga1_cdone, "FPGA1_CDONE");
+ if (err) {
+ pr_err("fail to request gpio %s, gpio %d, errno %d\n",
+ "FPGA1_CDONE", gpio_fpga1_cdone, err);
+ } else {
+ s3c_gpio_cfgpin(gpio_fpga1_cdone, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(gpio_fpga1_cdone, S3C_GPIO_PULL_NONE);
+ }
+ }
+
+ if (gpio_fpga1_rst_n) {
+ err = gpio_request(gpio_fpga1_rst_n, "FPGA1_RST");
+ if (err) {
+ pr_err("fail to request gpio %s, gpio %d, errno %d\n",
+ "FPGA1_RST", gpio_fpga1_rst_n, err);
+ } else {
+ gpio_direction_output(gpio_fpga1_rst_n, 0);
+ s3c_gpio_setpull(gpio_fpga1_rst_n, S3C_GPIO_PULL_NONE);
+ }
+ }
+
+ if (gpio_fpga1_cs_n) {
+ err = gpio_request(gpio_fpga1_cs_n, "SPI_CS2_1");
+ if (err) {
+ pr_err("fail to request gpio %s, gpio %d, errno %d\n",
+ "SPI_CS2_1", gpio_fpga1_cs_n, err);
+ } else {
+ gpio_direction_output(gpio_fpga1_cs_n, 0);
+ s3c_gpio_setpull(gpio_fpga1_cs_n, S3C_GPIO_PULL_NONE);
+ }
+ }
+#endif
+
+}
+
+static u8 *gsm_edpram_remap_mem_region(struct sromc_cfg *cfg)
+{
+ int dp_addr = 0;
+ int dp_size = 0;
+ u8 __iomem *dp_base = NULL;
+ struct msm_edpram_ipc_cfg *ipc_map = NULL;
+ struct dpram_ipc_device *dev = NULL;
+
+ dp_addr = cfg->addr;
+ dp_size = cfg->size;
+ dp_base = (u8 *)ioremap_nocache(dp_addr, dp_size);
+ if (!dp_base) {
+ pr_err("[MDM] <%s> dpram base ioremap fail\n", __func__);
+ return NULL;
+ }
+ pr_info("[MDM] <%s> DPRAM VA=0x%08X\n", __func__, (int)dp_base);
+
+ gsm_edpram_ctrl.dp_base = (u8 __iomem *)dp_base;
+ gsm_edpram_ctrl.dp_size = dp_size;
+
+ /* Map for IPC */
+ ipc_map = (struct msm_edpram_ipc_cfg *)dp_base;
+
+#if defined(CONFIG_LINK_DEVICE_PLD)
+ /* Magic code and access enable fields */
+ gsm_ipc_map.magic_ap2cp = (u16 __iomem *) &ipc_map->magic_ap2cp;
+ gsm_ipc_map.access_ap2cp = (u16 __iomem *) &ipc_map->access_ap2cp;
+
+ gsm_ipc_map.magic_cp2ap = (u16 __iomem *) &ipc_map->magic_cp2ap;
+ gsm_ipc_map.access_cp2ap = (u16 __iomem *) &ipc_map->access_cp2ap;
+
+ gsm_ipc_map.address_buffer = (u16 __iomem *) &ipc_map->address_buffer;
+#else
+ /* Magic code and access enable fields */
+ gsm_ipc_map.magic = (u16 __iomem *) &ipc_map->magic;
+ gsm_ipc_map.access = (u16 __iomem *) &ipc_map->access;
+#endif
+
+ /* FMT */
+ dev = &gsm_ipc_map.dev[IPC_FMT];
+
+ strcpy(dev->name, "FMT");
+ dev->id = IPC_FMT;
+
+ dev->txq.head = (u16 __iomem *)&ipc_map->fmt_tx_head;
+ dev->txq.tail = (u16 __iomem *)&ipc_map->fmt_tx_tail;
+ dev->txq.buff = (u8 __iomem *)&ipc_map->fmt_tx_buff[0];
+ dev->txq.size = MSM_DP_FMT_TX_BUFF_SZ;
+
+ dev->rxq.head = (u16 __iomem *)&ipc_map->fmt_rx_head;
+ dev->rxq.tail = (u16 __iomem *)&ipc_map->fmt_rx_tail;
+ dev->rxq.buff = (u8 __iomem *)&ipc_map->fmt_rx_buff[0];
+ dev->rxq.size = MSM_DP_FMT_RX_BUFF_SZ;
+
+ dev->mask_req_ack = INT_MASK_REQ_ACK_F;
+ dev->mask_res_ack = INT_MASK_RES_ACK_F;
+ dev->mask_send = INT_MASK_SEND_F;
+
+ /* RAW */
+ dev = &gsm_ipc_map.dev[IPC_RAW];
+
+ strcpy(dev->name, "RAW");
+ dev->id = IPC_RAW;
+
+ dev->txq.head = (u16 __iomem *)&ipc_map->raw_tx_head;
+ dev->txq.tail = (u16 __iomem *)&ipc_map->raw_tx_tail;
+ dev->txq.buff = (u8 __iomem *)&ipc_map->raw_tx_buff[0];
+ dev->txq.size = MSM_DP_RAW_TX_BUFF_SZ;
+
+ dev->rxq.head = (u16 __iomem *)&ipc_map->raw_rx_head;
+ dev->rxq.tail = (u16 __iomem *)&ipc_map->raw_rx_tail;
+ dev->rxq.buff = (u8 __iomem *)&ipc_map->raw_rx_buff[0];
+ dev->rxq.size = MSM_DP_RAW_RX_BUFF_SZ;
+
+ dev->mask_req_ack = INT_MASK_REQ_ACK_R;
+ dev->mask_res_ack = INT_MASK_RES_ACK_R;
+ dev->mask_send = INT_MASK_SEND_R;
+
+ /* Mailboxes */
+ gsm_ipc_map.mbx_ap2cp = (u16 __iomem *)&ipc_map->mbx_ap2cp;
+ gsm_ipc_map.mbx_cp2ap = (u16 __iomem *)&ipc_map->mbx_cp2ap;
+
+ return dp_base;
+}
+#endif
+
+#if defined(CONFIG_LINK_DEVICE_PLD)
+#define PLD_BLOCK_SIZE 0x8000
+
+static struct spi_device *p_spi;
+
+static int pld_spi_probe(struct spi_device *spi)
+{
+ int ret = 0;
+
+ mif_err("pld spi proble.\n");
+
+ p_spi = spi;
+ p_spi->mode = SPI_MODE_0;
+ p_spi->bits_per_word = 32;
+
+ ret = spi_setup(p_spi);
+ if (ret != 0) {
+ mif_err("spi_setup ERROR : %d\n", ret);
+ return ret;
+ }
+
+ dev_info(&p_spi->dev, "(%d) spi probe Done.\n", __LINE__);
+
+ return ret;
+}
+
+static int pld_spi_remove(struct spi_device *spi)
+{
+ return 0;
+}
+
+static struct spi_driver pld_spi_driver = {
+ .probe = pld_spi_probe,
+ .remove = __devexit_p(pld_spi_remove),
+ .driver = {
+ .name = "modem_if_spi",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int config_spi_dev_init(void)
+{
+ int ret = 0;
+
+ ret = spi_register_driver(&pld_spi_driver);
+ if (ret < 0) {
+ pr_info("spi_register_driver() fail : %d\n", ret);
+ return ret;
+ }
+
+ pr_info("[%s] Done\n", __func__);
+ return 0;
+}
+
+int spi_tx_rx_sync(u8 *tx_d, u8 *rx_d, unsigned len)
+{
+ struct spi_transfer t;
+ struct spi_message msg;
+
+ memset(&t, 0, sizeof t);
+
+ t.len = len;
+
+ t.tx_buf = tx_d;
+ t.rx_buf = rx_d;
+
+ t.cs_change = 0;
+
+ t.bits_per_word = 8;
+ t.speed_hz = 12000000;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&t, &msg);
+
+ return spi_sync(p_spi, &msg);
+}
+
+static int pld_send_fgpa_bin(void)
+{
+ int retval = 0;
+ char *tx_b, *rx_b;
+
+ unsigned gpio_fpga1_creset = gsm_modem_data.gpio_fpga1_creset;
+ unsigned gpio_fpga1_cdone = gsm_modem_data.gpio_fpga1_cdone;
+ unsigned gpio_fpga1_rst_n = gsm_modem_data.gpio_fpga1_rst_n;
+ unsigned gpio_fpga1_cs_n = gsm_modem_data.gpio_fpga1_cs_n;
+
+ char dummy_data[8] = "abcdefg";
+
+ mif_info("sizeofpld : 0%d ", sizeof(fpga_bin));
+
+ if (gpio_fpga1_cs_n) {
+ s3c_gpio_cfgpin(gpio_fpga1_cs_n, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(gpio_fpga1_cs_n, S3C_GPIO_PULL_NONE);
+ gpio_direction_output(gpio_fpga1_cs_n, 0);
+ }
+
+ msleep(20);
+
+ if (gpio_fpga1_creset) {
+ gpio_direction_output(gpio_fpga1_creset, 1);
+ s3c_gpio_setpull(gpio_fpga1_creset, S3C_GPIO_PULL_NONE);
+ }
+
+ msleep(20);
+
+ tx_b = kmalloc(PLD_BLOCK_SIZE*2, GFP_ATOMIC);
+ if (!tx_b) {
+ mif_err("(%d) tx_b kmalloc fail.",
+ __LINE__);
+ return -ENOMEM;
+ }
+ memset(tx_b, 0, PLD_BLOCK_SIZE*2);
+ memcpy(tx_b, fpga_bin, sizeof(fpga_bin));
+
+ rx_b = kmalloc(PLD_BLOCK_SIZE*2, GFP_ATOMIC);
+ if (!rx_b) {
+ mif_err("(%d) rx_b kmalloc fail.",
+ __LINE__);
+ retval = -ENOMEM;
+ goto err;
+ }
+ memset(rx_b, 0, PLD_BLOCK_SIZE*2);
+
+ retval = spi_tx_rx_sync(tx_b, rx_b, sizeof(fpga_bin));
+ if (retval != 0) {
+ mif_err("(%d) spi sync error : %d\n",
+ __LINE__, retval);
+ goto err;
+ }
+
+ memset(tx_b, 0, PLD_BLOCK_SIZE*2);
+ memcpy(tx_b, dummy_data, sizeof(dummy_data));
+
+ retval = spi_tx_rx_sync(tx_b, rx_b, sizeof(dummy_data));
+ if (retval != 0) {
+ mif_err("(%d) spi sync error : %d\n",
+ __LINE__, retval);
+ goto err;
+ }
+
+ msleep(20);
+
+ mif_info("PLD_CDone1[%d]\n",
+ gpio_get_value(gpio_fpga1_cdone));
+
+ if (gpio_fpga1_rst_n) {
+ gpio_direction_output(gpio_fpga1_rst_n, 1);
+ s3c_gpio_setpull(gpio_fpga1_rst_n, S3C_GPIO_PULL_NONE);
+ }
+
+err:
+ kfree(tx_b);
+ kfree(rx_b);
+
+ return retval;
+
+}
+#endif
+
+static int __init init_modem(void)
+{
+#if defined(CONFIG_GSM_MODEM_ESC6270)
+ struct sromc_cfg *cfg = NULL;
+ struct sromc_access_cfg *acc_cfg = NULL;
+
+ int ret;
+ pr_info(LOG_TAG "init_modem, system_rev = %d\n", system_rev);
+
+ gsm_edpram_cfg.csn = 0;
+ gsm_edpram_cfg.addr = SROM_CS0_BASE + (SROM_WIDTH * gsm_edpram_cfg.csn);
+ gsm_edpram_cfg.end = gsm_edpram_cfg.addr + gsm_edpram_cfg.size - 1;
+
+ config_dpram_port_gpio();
+ config_gsm_modem_gpio();
+
+#if defined(CONFIG_LINK_DEVICE_PLD)
+ config_spi_dev_init();
+ pld_send_fgpa_bin();
+#endif
+
+ init_sromc();
+ cfg = &gsm_edpram_cfg;
+ acc_cfg = &gsm_edpram_access_cfg[DPRAM_SPEED_LOW];
+ setup_sromc(cfg->csn, cfg, acc_cfg);
+
+ if (!gsm_edpram_remap_mem_region(&gsm_edpram_cfg))
+ return -1;
+
+ platform_device_register(&gsm_modem);
+#endif
+
+ return ret;
+}
+late_initcall(init_modem);