From a18588b161b4489cffb0fad8f06e31c3fb02e75b Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Thu, 26 May 2011 14:03:24 +0200 Subject: [PATCH] more non-working serial stuff --- .gitignore | 9 + Makefile | 2 +- board-mapphone-emu_uart.c | 576 ++++++++++++++++++++++++++++++++++++++ hs_cons.c | 5 +- omap2_serial.c | 11 + 5 files changed, 601 insertions(+), 2 deletions(-) create mode 100644 board-mapphone-emu_uart.c diff --git a/.gitignore b/.gitignore index 0f4c01a..fb191ec 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .abort-ev7.o.cmd +.board-mapphone-emu_uart.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.o.d +.hs_cons.o.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 +.omap-hs-serial.o.cmd +.omap2_serial.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 +board-mapphone-emu_uart.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 +hs_cons.o idmap.o kexec.o kexec_load.ko @@ -40,6 +47,8 @@ kexec_load.o machine_kexec.o mmu.o modules.order +omap-hs-serial.o +omap2_serial.o pabort-v7.o proc-v7.o relocate_kernel.o diff --git a/Makefile b/Makefile index ef4b881..a2b7f0e 100644 --- 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 -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 diff --git a/board-mapphone-emu_uart.c b/board-mapphone-emu_uart.c new file mode 100644 index 0000000..ba209c0 --- /dev/null +++ b/board-mapphone-emu_uart.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * 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"); + +} diff --git a/hs_cons.c b/hs_cons.c index 8ca5b80..9c1f47d 100644 --- 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 activate_emu_uart(void); #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 */ - 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)); + //activate_emu_uart(); + //add_preferred_console("ttyS", 2, "115200"); return 0; } diff --git a/omap2_serial.c b/omap2_serial.c index afed285..1e0e256 100644 --- a/omap2_serial.c +++ b/omap2_serial.c @@ -40,6 +40,10 @@ #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)); @@ -235,6 +239,13 @@ static inline void omap_uart_enable_clocks(struct omap_uart_state *uart) 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; } -- 2.39.2