]> git.zerfleddert.de Git - ms2-kexec/commitdiff
more non-working serial stuff
authorMichael Gernoth <michael@gernoth.net>
Thu, 26 May 2011 12:03:24 +0000 (14:03 +0200)
committerMichael Gernoth <michael@gernoth.net>
Thu, 26 May 2011 12:03:24 +0000 (14:03 +0200)
.gitignore
Makefile
board-mapphone-emu_uart.c [new file with mode: 0644]
hs_cons.c
omap2_serial.c

index 0f4c01a35e809f8c7b54de1548ecd2e5281683ca..fb191eca765300dc145ae52d40db2c05f40dd73e 100644 (file)
@@ -1,4 +1,5 @@
 .abort-ev7.o.cmd
 .abort-ev7.o.cmd
+.board-mapphone-emu_uart.o.cmd
 .cache-v7.o.cmd
 .copypage-v6.o.cmd
 .core.o.cmd
 .cache-v7.o.cmd
 .copypage-v6.o.cmd
 .core.o.cmd
@@ -7,6 +8,8 @@
 .headphone_cons.ko.cmd
 .headphone_cons.mod.o.cmd
 .headphone_cons.o.cmd
 .headphone_cons.ko.cmd
 .headphone_cons.mod.o.cmd
 .headphone_cons.o.cmd
+.headphone_cons.o.d
+.hs_cons.o.cmd
 .idmap.o.cmd
 .kexec.o.cmd
 .kexec_load.ko.cmd
 .idmap.o.cmd
 .kexec.o.cmd
 .kexec_load.ko.cmd
@@ -14,6 +17,8 @@
 .kexec_load.o.cmd
 .machine_kexec.o.cmd
 .mmu.o.cmd
 .kexec_load.o.cmd
 .machine_kexec.o.cmd
 .mmu.o.cmd
+.omap-hs-serial.o.cmd
+.omap2_serial.o.cmd
 .pabort-v7.o.cmd
 .proc-v7.o.cmd
 .relocate_kernel.o.cmd
 .pabort-v7.o.cmd
 .proc-v7.o.cmd
 .relocate_kernel.o.cmd
@@ -22,6 +27,7 @@
 .tmp_versions/
 Module.symvers
 abort-ev7.o
 .tmp_versions/
 Module.symvers
 abort-ev7.o
+board-mapphone-emu_uart.o
 cache-v7.o
 copypage-v6.o
 core.o
 cache-v7.o
 copypage-v6.o
 core.o
@@ -31,6 +37,7 @@ headphone_cons.ko
 headphone_cons.mod.c
 headphone_cons.mod.o
 headphone_cons.o
 headphone_cons.mod.c
 headphone_cons.mod.o
 headphone_cons.o
+hs_cons.o
 idmap.o
 kexec.o
 kexec_load.ko
 idmap.o
 kexec.o
 kexec_load.ko
@@ -40,6 +47,8 @@ kexec_load.o
 machine_kexec.o
 mmu.o
 modules.order
 machine_kexec.o
 mmu.o
 modules.order
+omap-hs-serial.o
+omap2_serial.o
 pabort-v7.o
 proc-v7.o
 relocate_kernel.o
 pabort-v7.o
 proc-v7.o
 relocate_kernel.o
index ef4b8810c42398c61d3a1a55bd409bf22ea3d531..a2b7f0e67c7633d50af3d5799aa9d9d30731680d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@ EXTRA_CFLAGS += -DCONFIG_KEXEC -Wall -DSYS_CALL_TABLE=0x$(SYS_CALL_TABLE) -DKERN
 obj-m += kexec_load.o headphone_cons.o
 kexec_load-objs := kexec.o machine_kexec.o mmu.o sys.o core.o relocate_kernel.o \
        proc-v7.o tlb-v7.o cache-v7.o abort-ev7.o pabort-v7.o copypage-v6.o driver_sys.o
 obj-m += kexec_load.o headphone_cons.o
 kexec_load-objs := kexec.o machine_kexec.o mmu.o sys.o core.o relocate_kernel.o \
        proc-v7.o tlb-v7.o cache-v7.o abort-ev7.o pabort-v7.o copypage-v6.o driver_sys.o
-headphone_cons-objs := hs_cons.o omap2_serial.o omap-hs-serial.o
+headphone_cons-objs := hs_cons.o omap2_serial.o omap-hs-serial.o board-mapphone-emu_uart.o
 
 all:
        PATH=$(CROSS_PATH):$(PATH) CROSS_COMPILE=$(CROSS_COMPILE) ARCH=$(ARCH) make -C $(KDIR) M=$(PWD) modules
 
 all:
        PATH=$(CROSS_PATH):$(PATH) CROSS_COMPILE=$(CROSS_COMPILE) ARCH=$(ARCH) make -C $(KDIR) M=$(PWD) modules
diff --git a/board-mapphone-emu_uart.c b/board-mapphone-emu_uart.c
new file mode 100644 (file)
index 0000000..ba209c0
--- /dev/null
@@ -0,0 +1,576 @@
+/*
+ * board-mapphone-emu_uart.c
+ *
+ * Copyright (C) 2009 Motorola, Inc.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* Date         Author          Comment
+ * ===========  ==============  ==============================================
+ * Jun-26-2009  Motorola       Initial revision.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <linux/spi/spi.h>
+#include <plat/system.h>
+#include <linux/irq.h>
+
+#include <plat/dma.h>
+#include <plat/clock.h>
+#include <plat/board-mapphone-emu_uart.h>
+#include <plat/hardware.h>
+#include <plat/omap34xx.h>
+
+/*
+ * Register definitions for CPCAP related SPI register
+ */
+#define OMAP2_MCSPI_MAX_FREQ           48000000
+
+#define OMAP2_MCSPI_REVISION           0x00
+#define OMAP2_MCSPI_SYSCONFIG          0x10
+#define OMAP2_MCSPI_SYSSTATUS          0x14
+#define OMAP2_MCSPI_IRQSTATUS          0x18
+#define OMAP2_MCSPI_IRQENABLE          0x1c
+#define OMAP2_MCSPI_WAKEUPENABLE       0x20
+#define OMAP2_MCSPI_SYST               0x24
+#define OMAP2_MCSPI_MODULCTRL          0x28
+
+/* per-channel banks, 0x14 bytes each, first is: */
+#define OMAP2_MCSPI_CHCONF0            0x2c
+#define OMAP2_MCSPI_CHSTAT0            0x30
+#define OMAP2_MCSPI_CHCTRL0            0x34
+#define OMAP2_MCSPI_TX0                        0x38
+#define OMAP2_MCSPI_RX0                        0x3c
+
+/* per-register bitmasks: */
+
+#define OMAP2_MCSPI_SYSCONFIG_AUTOIDLE (1 << 0)
+#define OMAP2_MCSPI_SYSCONFIG_SOFTRESET        (1 << 1)
+#define OMAP2_AFTR_RST_SET_MASTER      (0 << 2)
+
+#define OMAP2_MCSPI_SYSSTATUS_RESETDONE        (1 << 0)
+#define OMAP2_MCSPI_SYS_CON_LVL_1 1
+#define OMAP2_MCSPI_SYS_CON_LVL_2 2
+
+#define OMAP2_MCSPI_MODULCTRL_SINGLE   (1 << 0)
+#define OMAP2_MCSPI_MODULCTRL_MS       (1 << 2)
+#define OMAP2_MCSPI_MODULCTRL_STEST    (1 << 3)
+
+#define OMAP2_MCSPI_CHCONF_PHA         (1 << 0)
+#define OMAP2_MCSPI_CHCONF_POL         (1 << 1)
+#define OMAP2_MCSPI_CHCONF_CLKD_MASK   (0x0f << 2)
+#define OMAP2_MCSPI_CHCONF_EPOL                (1 << 6)
+#define OMAP2_MCSPI_CHCONF_WL_MASK     (0x1f << 7)
+#define OMAP2_MCSPI_CHCONF_TRM_RX_ONLY (0x01 << 12)
+#define OMAP2_MCSPI_CHCONF_TRM_TX_ONLY (0x02 << 12)
+#define OMAP2_MCSPI_CHCONF_TRM_MASK    (0x03 << 12)
+#define OMAP2_MCSPI_CHCONF_TRM_TXRX    (~OMAP2_MCSPI_CHCONF_TRM_MASK)
+#define OMAP2_MCSPI_CHCONF_DMAW                (1 << 14)
+#define OMAP2_MCSPI_CHCONF_DMAR                (1 << 15)
+#define OMAP2_MCSPI_CHCONF_DPE0                (1 << 16)
+#define OMAP2_MCSPI_CHCONF_DPE1                (1 << 17)
+#define OMAP2_MCSPI_CHCONF_IS          (1 << 18)
+#define OMAP2_MCSPI_CHCONF_TURBO       (1 << 19)
+#define OMAP2_MCSPI_CHCONF_FORCE       (1 << 20)
+#define OMAP2_MCSPI_CHCONF_TCS0                (1 << 25)
+#define OMAP2_MCSPI_CHCONF_TCS1                (1 << 26)
+#define OMAP2_MCSPI_CHCONF_TCS_MASK    (0x03 << 25)
+
+#define OMAP2_MCSPI_SYSCFG_WKUP                (1 << 2)
+#define OMAP2_MCSPI_SYSCFG_IDL         (2 << 3)
+#define OMAP2_MCSPI_SYSCFG_CLK         (2 << 8)
+#define OMAP2_MCSPI_WAKEUP_EN          (1 << 1)
+#define OMAP2_MCSPI_IRQ_WKS            (1 << 16)
+#define OMAP2_MCSPI_CHSTAT_RXS         (1 << 0)
+#define OMAP2_MCSPI_CHSTAT_TXS         (1 << 1)
+#define OMAP2_MCSPI_CHSTAT_EOT         (1 << 2)
+
+#define OMAP2_MCSPI_CHCTRL_EN          (1 << 0)
+#define OMAP2_MCSPI_MODE_IS_MASTER     0
+#define OMAP2_MCSPI_MODE_IS_SLAVE      1
+#define OMAP_MCSPI_WAKEUP_ENABLE       1
+
+/*mcspi base address: (0x48098000)1st SPI, (0x4809A00) 2nd SPI*/
+#define OMAP_MCSPI_BASE        0x48098000
+
+#define WORD_LEN            32
+#define CLOCK_DIV           12 /* 2^(12)=4096  48000000/4096<19200 */
+
+#define LEVEL1              1
+#define LEVEL2              2
+#define WRITE_CPCAP         1
+#define READ_CPCAP          0
+
+#define CM_ICLKEN1_CORE  0x48004A10
+#define CM_FCLKEN1_CORE  0x48004A00
+#define OMAP2_MCSPI_EN_MCSPI1   (1 << 18)
+
+#define  RESET_FAIL      1
+#define RAW_MOD_REG_BIT(val, mask, set) do { \
+    if (set) \
+               val |= mask; \
+    else \
+                val &= ~mask; \
+} while (0)
+
+struct cpcap_dev {
+       u16 address;
+       u16 value;
+       u32 result;
+       int access_flag;
+};
+
+static char tx[4];
+static bool emu_uart_is_active = FALSE;
+
+/*   Although SPI driver is provided through linux system as implemented above,
+ *   it can not cover some special situation.
+ *
+ *   During Debug phase, OMAP may need to acess CPCAP by SPI
+ *   to configure or check related register when boot up is not finished.
+ *   However, at this time, spi driver integrated in linux system may not
+ *   be initialized properly.
+ *
+ *   So we provode the following SPI driver with common API for access capcap
+ *   by SPI directly, i.e. we will skip the linux system driver,
+ *   but access SPI hardware directly to configure read/write specially for
+ *   cpcap access.
+ *
+ *   So developer should be very careful to use these APIs:
+ *
+ *        read_cpcap_register_raw()
+ *        write_cpcap_register_raw()
+ *
+ *   Pay attention: Only use them when boot up phase.
+ *   Rasons are as follows:
+ *   1. Although we provide protection on these two APIs for concurrency and
+ *      race conditions, it may impact the performance of system
+ *      because it will mask all interrupts during access.
+ *   2. Calling these APIs will reset all SPI registers, and may make previous
+ *      data lost during run time.
+ *
+ *      So, if developer wants to access CPCAP after boot up is finished,
+ *      we suggest they should use poweric interface.
+ *
+ */
+static inline void raw_writel_reg(u32 value, u32 reg)
+{
+       unsigned int absolute_reg = (u32)OMAP_MCSPI_BASE + reg;
+#if defined(LOCAL_DEVELOPER_DEBUG)
+       printk(KERN_ERR " raw write reg =0x%x value=0x%x \n", absolute_reg,
+              value);
+#endif
+       omap_writel(value, absolute_reg);
+}
+
+static inline u32 raw_readl_reg(u32 reg)
+{
+       u32 result;
+       unsigned int absolute_reg = (u32)OMAP_MCSPI_BASE + reg;
+       result = omap_readl(absolute_reg);
+#if defined(LOCAL_DEVELOPER_DEBUG)
+       printk(KERN_ERR " raw read reg =0x%x result =0x%x  \n",
+              absolute_reg, result);
+#endif
+       return result;
+}
+
+static void raw_omap_mcspi_wakeup_enable(int level)
+{
+       u32 result;
+
+       /* configure SYSCONFIG register...  */
+       if (level == LEVEL1) {
+               result = raw_readl_reg(OMAP2_MCSPI_SYSCONFIG);
+               result =
+                   result | OMAP2_MCSPI_SYSCFG_WKUP |
+                   OMAP2_MCSPI_SYSCFG_IDL | OMAP2_MCSPI_SYSCFG_CLK |
+                   OMAP2_MCSPI_SYSCONFIG_AUTOIDLE;
+               raw_writel_reg(result, OMAP2_MCSPI_SYSCONFIG);
+       }
+
+       if (level == LEVEL2) {
+               result = raw_readl_reg(OMAP2_MCSPI_SYSCONFIG);
+               result =
+                   result | OMAP2_MCSPI_SYSCFG_WKUP |
+                   OMAP2_MCSPI_SYSCFG_IDL |
+                   OMAP2_MCSPI_SYSCONFIG_AUTOIDLE;
+               RAW_MOD_REG_BIT(result, OMAP2_MCSPI_SYSCFG_CLK, 0);
+               raw_writel_reg(result, OMAP2_MCSPI_SYSCONFIG);
+       }
+
+       /* configure wakeupenable register...  */
+       raw_writel_reg(OMAP2_MCSPI_WAKEUP_EN, OMAP2_MCSPI_WAKEUPENABLE);
+
+       /* configure enable interrupt register... */
+       result = raw_readl_reg(OMAP2_MCSPI_IRQENABLE);
+       result = result | OMAP2_MCSPI_IRQ_WKS;
+       raw_writel_reg(result, OMAP2_MCSPI_IRQENABLE);
+}
+
+static void raw_omap2_mcspi_set_master_mode(void)
+{
+       u32 result;
+
+       /* configure MCSPI_MODULCTRL register... */
+       result = raw_readl_reg(OMAP2_MCSPI_MODULCTRL);
+
+       RAW_MOD_REG_BIT(result, OMAP2_MCSPI_MODULCTRL_STEST, 0);
+       RAW_MOD_REG_BIT(result, OMAP2_MCSPI_MODULCTRL_MS,
+                       OMAP2_MCSPI_MODE_IS_MASTER);
+       RAW_MOD_REG_BIT(result, OMAP2_MCSPI_MODULCTRL_SINGLE, 1);
+
+       raw_writel_reg(result, OMAP2_MCSPI_MODULCTRL);
+}
+
+static void raw_omap2_mcspi_channel_config(void)
+{
+       u32 result;
+
+       /* select channel 0... otherwise 0x14*channel_num */
+       result = raw_readl_reg(OMAP2_MCSPI_CHCONF0);
+
+       /* TCS Chip select Timing(2.5 clock cycles) */
+       result &= ~(OMAP2_MCSPI_CHCONF_TCS_MASK);
+       result |= OMAP2_MCSPI_CHCONF_TCS1;
+
+       /* configure master mode... */
+       result &= ~OMAP2_MCSPI_CHCONF_IS;
+       result &= ~OMAP2_MCSPI_CHCONF_DPE1;
+       result |= OMAP2_MCSPI_CHCONF_DPE0;
+
+       /* configure wordlength  */
+       result &= ~OMAP2_MCSPI_CHCONF_WL_MASK;
+       result |= (WORD_LEN - 1) << 7;
+
+       /*  configure active high  */
+       result &= ~OMAP2_MCSPI_CHCONF_EPOL;
+
+       /* set clock divisor  */
+       result &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK;
+       result |= CLOCK_DIV << 2;
+
+       /* configure mode  polarity=0 phase=0  */
+       result &= ~OMAP2_MCSPI_CHCONF_POL;
+       result &= ~OMAP2_MCSPI_CHCONF_PHA;
+
+       raw_writel_reg(result, OMAP2_MCSPI_CHCONF0);
+
+}
+
+static void raw_mcspi_setup(void)
+{
+       raw_omap_mcspi_wakeup_enable(LEVEL1);
+       raw_omap2_mcspi_set_master_mode();
+       raw_omap2_mcspi_channel_config();
+       raw_omap_mcspi_wakeup_enable(LEVEL2);
+}
+
+static int raw_mcspi_reset(void)
+{
+       unsigned long timeout;
+       u32 tmp;
+
+       raw_omap_mcspi_wakeup_enable(LEVEL1);
+
+       raw_writel_reg(OMAP2_MCSPI_SYSCONFIG_SOFTRESET,
+                     OMAP2_MCSPI_SYSCONFIG);
+
+       timeout = jiffies + msecs_to_jiffies(1000);
+
+       do {
+               tmp = raw_readl_reg(OMAP2_MCSPI_SYSSTATUS);
+               if (time_after(jiffies, timeout)) {
+                       printk(KERN_ERR "SPI Error: Reset is time out!\n");
+                       return -RESET_FAIL;
+               }
+       } while (!(tmp & OMAP2_MCSPI_SYSSTATUS_RESETDONE));
+
+       /*configure all modules in  reset master mode */
+       raw_writel_reg(OMAP2_AFTR_RST_SET_MASTER, OMAP2_MCSPI_MODULCTRL);
+
+       /* call wakeup function to set sysconfig as per pm activity */
+       raw_omap_mcspi_wakeup_enable(LEVEL1);
+       raw_omap_mcspi_wakeup_enable(LEVEL2);
+
+       return 0;
+}
+
+static void raw_omap2_mcspi_force_cs(int enable_tag)
+{
+       u32 result;
+       result = raw_readl_reg(OMAP2_MCSPI_CHCONF0);
+       /*
+        * Manual spim_csx assertion to keep spim_csx for channel x active
+        * RW 0x0 between SPI words (single channel master mode only).
+        */
+       RAW_MOD_REG_BIT(result, OMAP2_MCSPI_CHCONF_FORCE, enable_tag);
+       raw_writel_reg(result, OMAP2_MCSPI_CHCONF0);
+}
+
+static void raw_omap2_mcspi_set_enable(int enable)
+{
+       u32 result;
+
+       result = enable ? OMAP2_MCSPI_CHCTRL_EN : 0;
+       raw_writel_reg(result, OMAP2_MCSPI_CHCTRL0);
+}
+
+
+static int raw_mcspi_wait_for_reg_bit(unsigned long reg, unsigned long bit)
+{
+       unsigned long timeout;
+
+       timeout = jiffies + msecs_to_jiffies(1000);
+
+       while (!(raw_readl_reg(reg) & bit)) {
+               if (time_after(jiffies, timeout))
+                       return -1;
+       }
+
+       return 0;
+}
+
+static void parser_cpcap(struct cpcap_dev *dev)
+{
+       if (dev->access_flag == WRITE_CPCAP) {
+               tx[3] = ((dev->address >> 6) & 0x000000FF) | 0x80;
+               tx[2] = (dev->address << 2) & 0x000000FF;
+               tx[1] = (dev->value >> 8) & 0x000000FF;
+               tx[0] = dev->value & 0x000000FF;
+       } else {
+               tx[3] = ((dev->address >> 6) & 0x000000FF);
+               tx[2] = (dev->address << 2) & 0x000000FF;
+               tx[1] = 1;
+               tx[0] = 1;
+       }
+}
+
+static void raw_omap2_mcspi_txrx_pio(struct cpcap_dev *dev)
+{
+       u32 result;
+       u32 tx_32bit;
+
+       /* config tranmission mode --- tx rx together */
+       result = raw_readl_reg(OMAP2_MCSPI_CHCONF0);
+       result &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
+       raw_writel_reg(result, OMAP2_MCSPI_CHCONF0);
+
+       /* enable the mcspi port! */
+       raw_omap2_mcspi_set_enable(1);
+
+       parser_cpcap(dev);
+
+       memcpy((void *)&tx_32bit, (void *)tx, 4);
+
+       if (raw_mcspi_wait_for_reg_bit(OMAP2_MCSPI_CHSTAT0,
+                                      OMAP2_MCSPI_CHSTAT_TXS) < 0) {
+               printk(KERN_ERR "SPI Error: TXS timed out\n");
+               goto out;
+       }
+       raw_writel_reg(tx_32bit, OMAP2_MCSPI_TX0);
+
+       if (raw_mcspi_wait_for_reg_bit(OMAP2_MCSPI_CHSTAT0,
+                                      OMAP2_MCSPI_CHSTAT_RXS) < 0) {
+               printk(KERN_ERR "SPI Error: RXS timed out\n");
+               goto out;
+       }
+
+       result = raw_readl_reg(OMAP2_MCSPI_RX0);
+
+       dev->result = result;
+
+out:
+       /* disable the mcspi port! */
+       raw_omap2_mcspi_set_enable(0);
+}
+
+static void raw_mcspi_run(struct cpcap_dev *dev)
+{
+       raw_omap_mcspi_wakeup_enable(LEVEL1);
+       raw_omap2_mcspi_set_master_mode();
+       raw_omap2_mcspi_channel_config();
+       raw_omap2_mcspi_force_cs(1);
+       raw_omap2_mcspi_txrx_pio(dev);
+       raw_omap2_mcspi_force_cs(0);
+       raw_omap_mcspi_wakeup_enable(LEVEL2);
+}
+
+static void raw_omap_mcspi_enable_IFclock(void)
+{
+       u32 result;
+
+       result = omap_readl(CM_FCLKEN1_CORE);
+       RAW_MOD_REG_BIT(result, OMAP2_MCSPI_EN_MCSPI1, 1);
+       omap_writel(result, CM_FCLKEN1_CORE);
+
+       result = omap_readl(CM_ICLKEN1_CORE);
+       RAW_MOD_REG_BIT(result, OMAP2_MCSPI_EN_MCSPI1, 1);
+       omap_writel(result, CM_ICLKEN1_CORE);
+
+}
+
+/*
+ * write_cpcap_register_raw is for cpcap spi write directly
+ * @return 0 on success; less than zero on failure.
+ */
+static int write_cpcap_register_raw(u16 addr, u16 val)
+{
+       int result;
+       unsigned long intr_flags;
+       struct cpcap_dev cpcap_write;
+
+#ifdef CONFIG_EMU_UART_DEBUG
+       if (is_emu_uart_active() && (addr == 897 || addr == 411))
+               return 0;
+#endif
+
+       local_irq_save(intr_flags);
+       raw_omap_mcspi_enable_IFclock();
+
+       result = raw_mcspi_reset();
+       if (result < 0) {
+               local_irq_restore(intr_flags);
+               printk(KERN_ERR "reset failed !\n");
+               return result;
+       }
+
+       raw_mcspi_setup();
+
+       cpcap_write.address = addr;
+       cpcap_write.value = val;
+       cpcap_write.access_flag = WRITE_CPCAP;
+       raw_mcspi_run(&cpcap_write);
+
+       local_irq_restore(intr_flags);
+
+       return result;
+}
+
+/*
+ *  read_cpcap_register_raw is for cpcap spi read directly,
+ *  read result is in val
+ *  @return 0 on success; less than zero on failure.
+ */
+static int read_cpcap_register_raw(u16 addr, u16 *val)
+{
+       int result;
+       unsigned long intr_flag;
+       struct cpcap_dev cpcap_read;
+
+       local_irq_save(intr_flag);
+       raw_omap_mcspi_enable_IFclock();
+
+       result = raw_mcspi_reset();
+       if (result < 0) {
+               local_irq_restore(intr_flag);
+               printk(KERN_ERR "reset failed !\n");
+               return result;
+       }
+
+       raw_mcspi_setup();
+
+       cpcap_read.address = addr;
+       cpcap_read.access_flag = READ_CPCAP;
+       raw_mcspi_run(&cpcap_read);
+       *val = cpcap_read.result;
+
+       local_irq_restore(intr_flag);
+
+       return result;
+}
+
+/*
+ * Check if the writting is allowed. If MiniUSB port has already been
+ * configured as UART3, we should ignore some SCM register writting.
+ */
+int is_emu_uart_iomux_reg(unsigned short offset)
+{
+       if ((emu_uart_is_active) && \
+           ((offset >= 0x1A2 && offset < 0x1BA) || (offset == 0x19E)))
+               return 1;
+       else
+               return 0;
+}
+
+bool is_emu_uart_active(void)
+{
+       return emu_uart_is_active;
+}
+
+static void write_omap_mux_register(u16 offset, u8 mode, u8 input_en)
+{
+       u16 tmp_val, reg_val;
+       u32 reg = OMAP343X_CTRL_BASE + offset;
+
+       reg_val = mode | (input_en << 8);
+       tmp_val = omap_readw(reg) & ~(0x0007 | (1 << 8));
+       reg_val = reg_val | tmp_val;
+       omap_writew(reg_val, reg);
+}
+
+void activate_emu_uart(void)
+{
+       int i;
+       u16 tmp = 0;
+
+       read_cpcap_register_raw(18, &tmp);
+       printk(KERN_ALERT "Reading CPCAP vendor_version: 0x%04X\n", tmp);
+       /*
+        * Step 1:
+        * Configure OMAP SCM to set all ULPI pin of USB OTG to SAFE MODE
+        */
+       for (i = 0; i < 0x18; i += 2)
+               write_omap_mux_register(0x1A2 + i, 7, 0);
+
+       /*
+        * Step 2:
+        * Configure CPCAP to route UART3 to USB port; Switch VBUSIN to supply
+        * UART/USB transeiver and set VBUS standby mode 3
+        */
+       write_cpcap_register_raw(897, 0x0101);
+       write_cpcap_register_raw(411, 0x014C);
+
+       /* Step 3:
+        * Configure OMAP SCM to set ULPI port as UART3 function
+        */
+       /*
+        * Set UART3 RX pin in safe mode
+        */
+       write_omap_mux_register(0x19E, 7, 0);
+       /*
+        * Route UART3 TX to ULPIDATA0, RX to ULPIDATA1
+        */
+       write_omap_mux_register(0x1AA, 2, 0);
+       write_omap_mux_register(0x1AC, 2, 1);
+
+       emu_uart_is_active = TRUE;
+       printk
+           (KERN_ALERT "WARNING: MiniUSB port works in UART3 mode,"
+            "the USB functionality UNAVAILABLE!\n");
+
+}
index 8ca5b801ce23d42d4db9910f12f8d59a5bb0bf79..9c1f47ddd3e8424e276503a3df2dac5c858e7cb2 100644 (file)
--- a/hs_cons.c
+++ b/hs_cons.c
@@ -34,6 +34,7 @@ static int (*add_preferred_console)(char *, int, char*) = (int (*)(char*, int, c
 void my_omap_serial_init(int wake_gpio_strobe, unsigned int wake_strobe_enable_mask);
 int my_omap_hs_init(void);
 int my_serial_omap_init(void);
 void my_omap_serial_init(int wake_gpio_strobe, unsigned int wake_strobe_enable_mask);
 int my_omap_hs_init(void);
 int my_serial_omap_init(void);
+void activate_emu_uart(void);
 
 #define MAPPHONE_BPWAKE_STROBE_GPIO    157
 
 
 #define MAPPHONE_BPWAKE_STROBE_GPIO    157
 
@@ -57,9 +58,11 @@ static int __init headphone_cons_init(void)
        my_omap_hs_init();
 
        /* route kernel uart out headset jack */
        my_omap_hs_init();
 
        /* route kernel uart out headset jack */
-       gpio_direction_output(hs_switch, 0);
+       gpio_set_value(hs_switch, 0);
        printk(KERN_INFO "headset_uart_switch: %d, value: %d\n", hs_switch, gpio_get_value(hs_switch));
 
        printk(KERN_INFO "headset_uart_switch: %d, value: %d\n", hs_switch, gpio_get_value(hs_switch));
 
+       //activate_emu_uart();
+
        //add_preferred_console("ttyS", 2, "115200");
        return 0;
 }
        //add_preferred_console("ttyS", 2, "115200");
        return 0;
 }
index afed285527785d703326ea825ac7519ceba65966..1e0e256ae16a07c45d6c2550111d2bde53b614cc 100644 (file)
 
 #define OMAP_CTRL_REGADDR(reg)            (OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE) + (reg))
 
 
 #define OMAP_CTRL_REGADDR(reg)            (OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE) + (reg))
 
+static int (*my_pwrdm_clkdm_state_switch)(struct clockdomain *) = (int (*)(struct clockdomain *))0xc0041370;
+static int (*add_preferred_console)(char *, int, char*) = (int (*)(char*, int, char*))0xc0069208;
+
+
 void omap_ctrl_writew(u16 val, u16 offset)
 {
        __raw_writew(val, OMAP_CTRL_REGADDR(offset));
 void omap_ctrl_writew(u16 val, u16 offset)
 {
        __raw_writew(val, OMAP_CTRL_REGADDR(offset));
@@ -235,6 +239,13 @@ static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
 
        clk_enable(uart->ick);
        clk_enable(uart->fck);
 
        clk_enable(uart->ick);
        clk_enable(uart->fck);
+
+       if (uart->ick->clkdm != NULL)
+               my_pwrdm_clkdm_state_switch(uart->ick->clkdm);
+
+       if (uart->fck->clkdm != NULL)
+               my_pwrdm_clkdm_state_switch(uart->fck->clkdm);
+
        uart->clocked = 1;
 }
 
        uart->clocked = 1;
 }
 
Impressum, Datenschutz