aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/c2c/samsung-c2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/c2c/samsung-c2c.c')
-rw-r--r--drivers/misc/c2c/samsung-c2c.c712
1 files changed, 0 insertions, 712 deletions
diff --git a/drivers/misc/c2c/samsung-c2c.c b/drivers/misc/c2c/samsung-c2c.c
deleted file mode 100644
index fe58c3d..0000000
--- a/drivers/misc/c2c/samsung-c2c.c
+++ /dev/null
@@ -1,712 +0,0 @@
-/*
- * Samsung C2C driver
- *
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Author: Kisang Lee <kisang80.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/input.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/miscdevice.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/cma.h>
-#include <linux/sysfs.h>
-#ifdef ENABLE_C2CSTATE_TIMER
-#include <linux/timer.h>
-#endif
-#ifdef CONFIG_C2C_IPC_ENABLE
-#include <linux/vmalloc.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#endif
-#include <asm/mach-types.h>
-
-#include <mach/c2c.h>
-#include <mach/regs-c2c.h>
-#include <mach/regs-pmu.h>
-#include <mach/regs-pmu5.h>
-#include <mach/pmu.h>
-#include <plat/cpu.h>
-
-#include "samsung-c2c.h"
-
-void (*exynos_c2c_request_pwr_mode)(enum c2c_pwr_mode mode);
-
-#ifdef ENABLE_C2CSTATE_TIMER
-struct timer_list c2c_status_timer;
-
-static void c2c_timer_func(unsigned long data)
-{
- /* Check C2C state */
- struct exynos_c2c_platdata *pdata = (struct exynos_c2c_platdata *)data;
- static int old_state = 0xff;
- int current_state = 0;
-
- if (pdata->get_c2c_state() != NULL) {
- current_state = pdata->get_c2c_state();
- if (current_state != old_state) {
- dev_info(c2c_con.c2c_dev, "C2C state is chaged (0x%x --> 0x%x)\n",
- old_state, current_state);
- old_state = current_state;
- }
- }
- c2c_status_timer.expires = jiffies + (HZ/5);
- add_timer(&c2c_status_timer);
-}
-#endif
-
-void c2c_reset_ops(void)
-{
- /* This function will be only used for EVT0 or EVT0.1 */
- u32 set_clk = 0;
-
- if (c2c_con.opp_mode == C2C_OPP100)
- set_clk = c2c_con.clk_opp100;
- else if (c2c_con.opp_mode == C2C_OPP50)
- set_clk = c2c_con.clk_opp50;
- else if (c2c_con.opp_mode == C2C_OPP25)
- set_clk = c2c_con.clk_opp25;
-
- dev_info(c2c_con.c2c_dev, "c2c_reset_ops()\n");
- clk_set_rate(c2c_con.c2c_sclk, (set_clk + 1) * MHZ);
- c2c_set_func_clk(set_clk);
-
- /* First phase - C2C block reset */
- c2c_set_reset(C2C_CLEAR);
- c2c_set_reset(C2C_SET);
- /* Second phase - Clear clock gating */
- c2c_set_clock_gating(C2C_CLEAR);
- /* Third phase - Retention reg */
- c2c_writel(c2c_con.retention_reg, EXYNOS_C2C_IRQ_EN_SET1);
- c2c_writel(set_clk, EXYNOS_C2C_FCLK_FREQ);
- c2c_writel(set_clk, EXYNOS_C2C_RX_MAX_FREQ);
- /* Last phase - Set clock gating */
- c2c_set_clock_gating(C2C_SET);
-}
-
-static ssize_t c2c_ctrl_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- int ret = 0;
- ret = sprintf(buf, "C2C State");
- c2c_set_clock_gating(C2C_CLEAR);
- ret += sprintf(&buf[ret], "SysReg : 0x%x\n",
- readl(c2c_con.c2c_sysreg));
- ret += sprintf(&buf[ret], "Port Config : 0x%x\n",
- c2c_readl(EXYNOS_C2C_PORTCONFIG));
- ret += sprintf(&buf[ret], "FCLK_FREQ : %d\n",
- c2c_readl(EXYNOS_C2C_FCLK_FREQ));
- ret += sprintf(&buf[ret], "RX_MAX_FREQ : %d\n",
- c2c_readl(EXYNOS_C2C_RX_MAX_FREQ));
- ret += sprintf(&buf[ret], "IRQ_EN_SET1 : 0x%x\n",
- c2c_readl(EXYNOS_C2C_IRQ_EN_SET1));
- ret += sprintf(&buf[ret], "Get C2C sclk rate : %ld\n",
- clk_get_rate(c2c_con.c2c_sclk));
- ret += sprintf(&buf[ret], "Get C2C aclk rate : %ld\n",
- clk_get_rate(c2c_con.c2c_aclk));
- c2c_set_clock_gating(C2C_SET);
-
- return ret;
-}
-
-static ssize_t c2c_ctrl_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- int ops_num, opp_val, req_clk;
- sscanf(buf, "%d", &ops_num);
-
- switch (ops_num) {
- case 1:
- c2c_reset_ops();
- break;
- case 2:
- case 3:
- case 4:
- opp_val = ops_num - 1;
- req_clk = 0;
- dev_info(c2c_con.c2c_dev, "Set current OPP mode (%d)\n", opp_val);
-
- if (opp_val == C2C_OPP100)
- req_clk = c2c_con.clk_opp100;
- else if (opp_val == C2C_OPP50)
- req_clk = c2c_con.clk_opp50;
- else if (opp_val == C2C_OPP25)
- req_clk = c2c_con.clk_opp25;
-
- if (opp_val == 0 || req_clk == 1) {
- dev_info(c2c_con.c2c_dev, "This mode is not reserved in OPP mode.\n");
- } else {
- c2c_set_clock_gating(C2C_CLEAR);
- if (c2c_con.opp_mode < opp_val) { /* increase case */
- clk_set_rate(c2c_con.c2c_sclk, (req_clk + 1) * MHZ);
- c2c_writel(req_clk, EXYNOS_C2C_FCLK_FREQ);
- c2c_set_func_clk(req_clk);
- c2c_writel(req_clk, EXYNOS_C2C_RX_MAX_FREQ);
- } else if (c2c_con.opp_mode > opp_val) { /* decrease case */
- c2c_writel(req_clk, EXYNOS_C2C_RX_MAX_FREQ);
- clk_set_rate(c2c_con.c2c_sclk, (req_clk + 1) * MHZ);
- c2c_writel(req_clk, EXYNOS_C2C_FCLK_FREQ);
- c2c_set_func_clk(req_clk);
- } else{
- dev_info(c2c_con.c2c_dev, "Requested same OPP mode\n");
- }
- c2c_con.opp_mode = opp_val;
- c2c_set_clock_gating(C2C_SET);
- }
-
- dev_info(c2c_con.c2c_dev, "Get C2C sclk rate : %ld\n",
- clk_get_rate(c2c_con.c2c_sclk));
- dev_info(c2c_con.c2c_dev, "Get C2C aclk rate : %ld\n",
- clk_get_rate(c2c_con.c2c_aclk));
- break;
- default:
- dev_info(c2c_con.c2c_dev, "Wrong C2C operation number\n");
- dev_info(c2c_con.c2c_dev, "---C2C Operation Number---\n");
- dev_info(c2c_con.c2c_dev, "1. C2C Reset\n");
- dev_info(c2c_con.c2c_dev, "2. Set OPP25\n");
- dev_info(c2c_con.c2c_dev, "3. Set OPP50\n");
- dev_info(c2c_con.c2c_dev, "4. Set OPP100\n");
- }
-
- return count;
-}
-
-static DEVICE_ATTR(c2c_ctrl, 0644, c2c_ctrl_show, c2c_ctrl_store);
-
-int c2c_open(struct inode *inode, struct file *filp)
-{
- /* This function is not needed.(Test Function) */
- dev_info(c2c_con.c2c_dev, "C2C chrdrv Opened.\n");
-
- return 0;
-}
-
-static long c2c_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- c2c_reset_ops();
-
- return 0;
-}
-
-static const struct file_operations c2c_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = c2c_ioctl,
- .open = c2c_open,
-};
-
-static struct miscdevice char_dev = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = C2C_DEV_NAME,
- .fops = &c2c_fops
-};
-
-static int c2c_set_sharedmem(enum c2c_shrdmem_size size, u32 addr)
-{
- dev_info(c2c_con.c2c_dev, "Set BaseAddr(0x%x) and Size(%d)\n",
- addr, 1 << (2 + size));
-
- /* Set DRAM Base Addr & Size */
- c2c_set_shdmem_size(size);
- c2c_set_base_addr((addr >> 22));
-
- return 0;
-}
-
-static void c2c_set_interrupt(u32 genio_num, enum c2c_interrupt set_int)
-{
- u32 cur_int_reg, cur_lev_reg;
-
- cur_int_reg = c2c_readl(EXYNOS_C2C_GENO_INT);
- cur_lev_reg = c2c_readl(EXYNOS_C2C_GENO_LEVEL);
-
- switch (set_int) {
- case C2C_INT_TOGGLE:
- cur_int_reg &= ~(0x1 << genio_num);
- c2c_writel(cur_int_reg, EXYNOS_C2C_GENO_INT);
- break;
- case C2C_INT_HIGH:
- cur_int_reg |= (0x1 << genio_num);
- cur_lev_reg |= (0x1 << genio_num);
- c2c_writel(cur_int_reg, EXYNOS_C2C_GENO_INT);
- c2c_writel(cur_lev_reg, EXYNOS_C2C_GENO_LEVEL);
- break;
- case C2C_INT_LOW:
- cur_int_reg |= (0x1 << genio_num);
- cur_lev_reg &= ~(0x1 << genio_num);
- c2c_writel(cur_int_reg, EXYNOS_C2C_GENO_INT);
- c2c_writel(cur_lev_reg, EXYNOS_C2C_GENO_LEVEL);
- break;
- }
-}
-
-static irqreturn_t c2c_sscm0_irq(int irq, void *data)
-{
- /* TODO : This function will be used other type boards */
- return IRQ_HANDLED;
-}
-
-static irqreturn_t c2c_sscm1_irq(int irq, void *data)
-{
- /* TODO : It is just temporary code. It will be modified. */
- u32 raw_irq, latency_val, opp_val, req_clk;
- raw_irq = c2c_readl(EXYNOS_C2C_IRQ_EN_STAT1);
-
-#ifdef CONFIG_C2C_IPC_ENABLE
- if (raw_irq & 0x1) {
- dev_info(c2c_con.c2c_dev, "IPC interrupt occured : GENO[0]\n");
- if (c2c_con.hd.handler)
- c2c_con.hd.handler(c2c_con.hd.data);
-
- /* Interrupt Clear */
- c2c_writel(0x1, EXYNOS_C2C_IRQ_EN_STAT1);
- }
-#endif
- if ((raw_irq >> C2C_GENIO_OPP_INT) & 1) { /* OPP Change */
- /*
- OPP mode GENI/O bit definition[29:27]
- OPP100 GENI/O[29:28] : 1 1
- OPP50 GENI/O[29:28] : 1 0
- OPP25 GENI/O[29:28] : 0 1
- GENI[27] is only used for making interrupt.
- */
- opp_val = (c2c_readl(EXYNOS_C2C_GENO_STATUS) >> 28) & 3;
- req_clk = 0;
- dev_info(c2c_con.c2c_dev, "OPP interrupt occured (%d)\n", opp_val);
-
- if (opp_val == C2C_OPP100)
- req_clk = c2c_con.clk_opp100;
- else if (opp_val == C2C_OPP50)
- req_clk = c2c_con.clk_opp50;
- else if (opp_val == C2C_OPP25)
- req_clk = c2c_con.clk_opp25;
-
- if (opp_val == 0 || req_clk == 1) {
- dev_info(c2c_con.c2c_dev, "This mode is not reserved in OPP mode.\n");
- } else {
- if (c2c_con.opp_mode < opp_val) { /* increase case */
- clk_set_rate(c2c_con.c2c_sclk, (req_clk + 1) * MHZ);
- c2c_writel(req_clk, EXYNOS_C2C_FCLK_FREQ);
- c2c_set_func_clk(req_clk);
- c2c_writel(req_clk, EXYNOS_C2C_RX_MAX_FREQ);
- } else if (c2c_con.opp_mode > opp_val) { /* decrease case */
- c2c_writel(req_clk, EXYNOS_C2C_RX_MAX_FREQ);
- clk_set_rate(c2c_con.c2c_sclk, (req_clk + 1) * MHZ);
- c2c_writel(req_clk, EXYNOS_C2C_FCLK_FREQ);
- c2c_set_func_clk(req_clk);
- } else{
- dev_info(c2c_con.c2c_dev, "Requested same OPP mode\n");
- }
- c2c_con.opp_mode = opp_val;
- }
-
- /* Interrupt Clear */
- c2c_writel((0x1 << C2C_GENIO_OPP_INT), EXYNOS_C2C_IRQ_EN_STAT1);
- }
-
- /* Memory I/F latency change */
- if ((raw_irq >> C2C_GENIO_LATENCY_INT) & 1) {
- latency_val = (c2c_readl(EXYNOS_C2C_GENO_STATUS) >> 30) & 3;
- switch (latency_val) {
- case 3:
- dev_info(c2c_con.c2c_dev, "Set Min latency\n");
- if (exynos_c2c_request_pwr_mode != NULL)
- exynos_c2c_request_pwr_mode(MIN_LATENCY);
- break;
- case 1:
- dev_info(c2c_con.c2c_dev, "Set Short latency\n");
- if (exynos_c2c_request_pwr_mode != NULL)
- exynos_c2c_request_pwr_mode(SHORT_LATENCY);
- break;
- case 0:
- dev_info(c2c_con.c2c_dev, "Set Max latency\n");
- if (exynos_c2c_request_pwr_mode != NULL)
- exynos_c2c_request_pwr_mode(MAX_LATENCY);
- break;
- }
- /* Interrupt Clear */
- c2c_writel((0x1 << C2C_GENIO_LATENCY_INT), EXYNOS_C2C_IRQ_EN_STAT1);
- }
-
- return IRQ_HANDLED;
-}
-
-static void set_c2c_device(struct platform_device *pdev)
-{
- struct exynos_c2c_platdata *pdata = pdev->dev.platform_data;
- u32 default_clk;
-
- c2c_con.c2c_sysreg = pdata->c2c_sysreg;
- c2c_con.rx_width = pdata->rx_width;
- c2c_con.tx_width = pdata->tx_width;
- c2c_con.clk_opp100 = pdata->clk_opp100;
- c2c_con.clk_opp50 = pdata->clk_opp50;
- c2c_con.clk_opp25 = pdata->clk_opp25;
- c2c_con.opp_mode = pdata->default_opp_mode;
-#ifdef CONFIG_C2C_IPC_ENABLE
- c2c_con.shd_pages = NULL;
- c2c_con.hd.data = NULL;
- c2c_con.hd.handler = NULL;
-#endif
- c2c_con.c2c_sclk = clk_get(&pdev->dev, "sclk_c2c");
- c2c_con.c2c_aclk = clk_get(&pdev->dev, "aclk_c2c");
-
- if (soc_is_exynos4212())
- exynos_c2c_request_pwr_mode = exynos4_c2c_request_pwr_mode;
- else if (soc_is_exynos4412()) {
- exynos_c2c_request_pwr_mode = exynos4_c2c_request_pwr_mode;
- if (samsung_rev() >= EXYNOS4412_REV_1_0)
- writel(C2C_SYSREG_DEFAULT, c2c_con.c2c_sysreg);
- } else if (soc_is_exynos5250())
- exynos_c2c_request_pwr_mode = NULL;
-
- /* Set clock to default mode */
- if (c2c_con.opp_mode == C2C_OPP100)
- default_clk = c2c_con.clk_opp100;
- else if (c2c_con.opp_mode == C2C_OPP50)
- default_clk = c2c_con.clk_opp50;
- else if (c2c_con.opp_mode == C2C_OPP25)
- default_clk = c2c_con.clk_opp25;
- else {
- dev_info(c2c_con.c2c_dev, "Default OPP mode is not selected.\n");
- c2c_con.opp_mode = C2C_OPP50;
- default_clk = c2c_con.clk_opp50;
- }
-
- clk_set_rate(c2c_con.c2c_sclk, (default_clk + 1) * MHZ);
- clk_set_rate(c2c_con.c2c_aclk, ((default_clk / 2) + 1) * MHZ);
-
- dev_info(c2c_con.c2c_dev, "Get C2C sclk rate : %ld\n",
- clk_get_rate(c2c_con.c2c_sclk));
- dev_info(c2c_con.c2c_dev, "Get C2C aclk rate : %ld\n",
- clk_get_rate(c2c_con.c2c_aclk));
- if (pdata->setup_gpio)
- pdata->setup_gpio(pdata->rx_width, pdata->tx_width);
-
- c2c_set_sharedmem(pdata->shdmem_size, pdata->shdmem_addr);
-
- /* Set SYSREG to memdone */
- c2c_set_memdone(C2C_SET);
- c2c_set_clock_gating(C2C_CLEAR);
-
- /* Set C2C clock register to OPP50 */
- c2c_writel(default_clk, EXYNOS_C2C_FCLK_FREQ);
- c2c_writel(default_clk, EXYNOS_C2C_RX_MAX_FREQ);
- c2c_set_func_clk(default_clk);
-
- /* Set C2C buswidth */
- c2c_writel(((pdata->rx_width << 4) | (pdata->tx_width)),
- EXYNOS_C2C_PORTCONFIG);
- c2c_set_tx_buswidth(pdata->tx_width);
- c2c_set_rx_buswidth(pdata->rx_width);
-
- /* Enable all of GENI/O Interrupt */
- c2c_writel((0x1 << C2C_GENIO_OPP_INT), EXYNOS_C2C_IRQ_EN_SET1);
- c2c_con.retention_reg = (0x1 << C2C_GENIO_OPP_INT);
-
- if (exynos_c2c_request_pwr_mode != NULL)
- exynos_c2c_request_pwr_mode(MAX_LATENCY);
-
- c2c_set_interrupt(C2C_GENIO_OPP_INT, C2C_INT_HIGH);
-
- dev_info(c2c_con.c2c_dev, "Port Config : 0x%x\n",
- c2c_readl(EXYNOS_C2C_PORTCONFIG));
- dev_info(c2c_con.c2c_dev, "FCLK_FREQ register : %d\n",
- c2c_readl(EXYNOS_C2C_FCLK_FREQ));
- dev_info(c2c_con.c2c_dev, "RX_MAX_FREQ register : %d\n",
- c2c_readl(EXYNOS_C2C_RX_MAX_FREQ));
- dev_info(c2c_con.c2c_dev, "IRQ_EN_SET1 register : 0x%x\n",
- c2c_readl(EXYNOS_C2C_IRQ_EN_SET1));
-
- c2c_set_clock_gating(C2C_SET);
-}
-
-#ifdef CONFIG_C2C_IPC_ENABLE
-void __iomem *c2c_request_cp_region(unsigned int cp_addr,
- unsigned int size)
-{
- dma_addr_t phy_cpmem;
-
- phy_cpmem = cma_alloc(c2c_con.c2c_dev, "c2c_shdmem", size, 0);
- if (IS_ERR_VALUE(phy_cpmem)) {
- dev_info(c2c_con.c2c_dev, KERN_ERR "C2C CMA Alloc Error!!!");
- return NULL;
- }
-
- return phys_to_virt(phy_cpmem);
-}
-EXPORT_SYMBOL(c2c_request_cp_region);
-
-void c2c_release_cp_region(void *rgn)
-{
- dma_addr_t phy_cpmem;
-
- phy_cpmem = virt_to_phys(rgn);
-
- cma_free(phy_cpmem);
-}
-EXPORT_SYMBOL(c2c_release_cp_region);
-
-void __iomem *c2c_request_sh_region(unsigned int sh_addr,
- unsigned int size)
-{
- int i;
- struct page **pages;
- void *pv;
-
- pages = kmalloc((size >> PAGE_SHIFT) * sizeof(*pages), GFP_KERNEL);
- for (i = 0; i < (size >> PAGE_SHIFT); i++) {
- pages[i] = phys_to_page(sh_addr);
- sh_addr += PAGE_SIZE;
- }
-
- c2c_con.shd_pages = (void *)pages;
-
- pv = vmap(pages, size >> PAGE_SHIFT, VM_MAP,
- pgprot_noncached(PAGE_KERNEL));
-
- return (void __iomem *)pv;
-}
-EXPORT_SYMBOL(c2c_request_sh_region);
-
-void c2c_release_sh_region(void *rgn)
-{
- vunmap(rgn);
- kfree(c2c_con.shd_pages);
- c2c_con.shd_pages = NULL;
-}
-EXPORT_SYMBOL(c2c_release_sh_region);
-
-int c2c_register_handler(void (*handler)(void *), void *data)
-{
- if (!handler)
- return -EINVAL;
-
- c2c_con.hd.data = data;
- c2c_con.hd.handler = handler;
-
- c2c_reset_interrupt();
-
- return 0;
-}
-EXPORT_SYMBOL(c2c_register_handler);
-
-int c2c_unregister_handler(void (*handler)(void *))
-{
- if (!handler || (c2c_con.hd.handler != handler))
- return -EINVAL;
-
- c2c_con.hd.data = NULL;
- c2c_con.hd.handler = NULL;
- return 0;
-}
-EXPORT_SYMBOL(c2c_unregister_handler);
-
-void c2c_send_interrupt(void)
-{
- c2c_writel(c2c_readl(EXYNOS_C2C_GENI_CONTROL) ^ 0x1,
- EXYNOS_C2C_GENI_CONTROL);
-}
-EXPORT_SYMBOL(c2c_send_interrupt);
-
-void c2c_reset_interrupt(void)
-{
- c2c_writel(c2c_readl(EXYNOS_C2C_IRQ_EN_SET1) | 0x1,
- EXYNOS_C2C_IRQ_EN_SET1);
- c2c_con.retention_reg |= 0x1;
-}
-EXPORT_SYMBOL(c2c_reset_interrupt);
-#endif
-
-static int __devinit samsung_c2c_probe(struct platform_device *pdev)
-{
- struct exynos_c2c_platdata *pdata = pdev->dev.platform_data;
- struct resource *res = NULL;
- struct resource *res1 = NULL;
- int sscm_irq0, sscm_irq1;
- int err = 0;
-
- c2c_con.c2c_dev = &pdev->dev;
-
- /* resource for AP's SSCM region */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "no memory resource defined(AP's SSCM)\n");
- return -ENOENT;
- }
- res = request_mem_region(res->start, resource_size(res), pdev->name);
- if (!res) {
- dev_err(&pdev->dev, "failded to request memory resource(AP)\n");
- return -ENOENT;
- }
- pdata->ap_sscm_addr = ioremap(res->start, resource_size(res));
- if (!pdata->ap_sscm_addr) {
- dev_err(&pdev->dev, "failded to request memory resource(AP)\n");
- goto release_ap_sscm;
- }
- c2c_con.ap_sscm_addr = pdata->ap_sscm_addr;
-
- /* resource for CP's SSCM region */
- res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!res1) {
- dev_err(&pdev->dev, "no memory resource defined(AP's SSCM)\n");
- goto unmap_ap_sscm;
- }
- res1 = request_mem_region(res1->start, resource_size(res1), pdev->name);
- if (!res1) {
- dev_err(&pdev->dev, "failded to request memory resource(AP)\n");
- goto unmap_ap_sscm;
- }
- pdata->cp_sscm_addr = ioremap(res1->start, resource_size(res1));
- if (!pdata->cp_sscm_addr) {
- dev_err(&pdev->dev, "failded to request memory resource(CP)\n");
- goto release_cp_sscm;
- }
- c2c_con.cp_sscm_addr = pdata->cp_sscm_addr;
-
- /* Request IRQ */
- sscm_irq0 = platform_get_irq(pdev, 0);
- if (sscm_irq0 < 0) {
- dev_err(&pdev->dev, "no irq specified\n");
- goto unmap_cp_sscm;
- }
- err = request_irq(sscm_irq0, c2c_sscm0_irq, 0, pdev->name, pdev);
- if (err) {
- dev_err(&pdev->dev, "Can't request SSCM0 IRQ\n");
- goto unmap_cp_sscm;
- }
- /* SSCM0 irq will be only used for master(CP) device */
- disable_irq(sscm_irq0);
-
- sscm_irq1 = platform_get_irq(pdev, 1);
- if (sscm_irq1 < 0) {
- dev_err(&pdev->dev, "no irq specified\n");
- goto release_sscm_irq0;
- }
- err = request_irq(sscm_irq1, c2c_sscm1_irq, 1, pdev->name, pdev);
- if (err) {
- dev_err(&pdev->dev, "Can't request SSCM1 IRQ\n");
- goto release_sscm_irq0;
- }
-
- err = misc_register(&char_dev);
- if (err) {
- dev_err(&pdev->dev, "Can't register chrdev!\n");
- goto release_sscm_irq0;
- }
-
- set_c2c_device(pdev);
-
-#ifdef ENABLE_C2CSTATE_TIMER
- /* Timer for debugging to check C2C state */
- init_timer(&c2c_status_timer);
- c2c_status_timer.expires = jiffies + HZ;
- c2c_status_timer.data = (unsigned long)pdata;
- c2c_status_timer.function = &c2c_timer_func;
- add_timer(&c2c_status_timer);
-#endif
-
- /* Create sysfs file for C2C debug */
- err = device_create_file(&pdev->dev, &dev_attr_c2c_ctrl);
- if (err) {
- dev_err(&pdev->dev, "Failed to create sysfs for C2C\n");
- goto release_sscm_irq1;
- }
-
- return 0;
-
-release_sscm_irq1:
- free_irq(sscm_irq1, pdev);
-
-release_sscm_irq0:
- free_irq(sscm_irq0, pdev);
-
-unmap_cp_sscm:
- iounmap(pdata->cp_sscm_addr);
-
-release_cp_sscm:
- release_mem_region(res1->start, resource_size(res1));
-
-unmap_ap_sscm:
- iounmap(pdata->ap_sscm_addr);
-
-release_ap_sscm:
- release_mem_region(res->start, resource_size(res));
-
- return err;
-}
-
-static int __devexit samsung_c2c_remove(struct platform_device *pdev)
-{
- /* TODO */
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int samsung_c2c_suspend(struct platform_device *dev, pm_message_t pm)
-{
- /* TODO */
- return 0;
-}
-
-static int samsung_c2c_resume(struct platform_device *dev)
-{
- struct exynos_c2c_platdata *pdata = dev->dev.platform_data;
-
- if ((soc_is_exynos4212() || soc_is_exynos4412())
- && samsung_rev() == EXYNOS4412_REV_0) {
- /* Set SYSREG */
- c2c_set_sharedmem(pdata->shdmem_size, pdata->shdmem_addr);
- c2c_set_memdone(C2C_SET);
- } else if (soc_is_exynos5250()) {
- /* Set SYSREG */
- c2c_set_sharedmem(pdata->shdmem_size, pdata->shdmem_addr);
- c2c_set_memdone(C2C_SET);
- }
-
- return 0;
-}
-#else
-#define samsung_c2c_suspend NULL
-#define samsung_c2c_resume NULL
-#endif
-
-static struct platform_driver samsung_c2c_driver = {
- .probe = samsung_c2c_probe,
- .remove = __devexit_p(samsung_c2c_remove),
- .suspend = samsung_c2c_suspend,
- .resume = samsung_c2c_resume,
- .driver = {
- .name = "samsung-c2c",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init samsung_c2c_init(void)
-{
- return platform_driver_register(&samsung_c2c_driver);
-}
-module_init(samsung_c2c_init);
-
-static void __exit samsung_c2c_exit(void)
-{
- platform_driver_unregister(&samsung_c2c_driver);
-}
-module_exit(samsung_c2c_exit);
-
-MODULE_DESCRIPTION("Samsung C2C driver");
-MODULE_AUTHOR("Kisang Lee <kisang80.lee@samsung.com>");
-MODULE_LICENSE("GPL");