2 * board-mapphone-emu_uart.c
4 * Copyright (C) 2009 Motorola, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 /* Date Author Comment
22 * =========== ============== ==============================================
23 * Jun-26-2009 Motorola Initial revision.
26 #include <linux/kernel.h>
27 #include <linux/init.h>
28 #include <linux/interrupt.h>
29 #include <linux/module.h>
30 #include <linux/device.h>
31 #include <linux/delay.h>
32 #include <linux/dma-mapping.h>
33 #include <linux/platform_device.h>
34 #include <linux/err.h>
35 #include <linux/clk.h>
38 #include <linux/spi/spi.h>
39 #include <plat/system.h>
40 #include <linux/irq.h>
43 #include <plat/clock.h>
44 #include <plat/board-mapphone-emu_uart.h>
45 #include <plat/hardware.h>
46 #include <plat/omap34xx.h>
48 #include <linux/spi/cpcap.h>
49 #include <linux/spi/cpcap-regbits.h>
52 * Register definitions for CPCAP related SPI register
54 #define OMAP2_MCSPI_MAX_FREQ 48000000
56 #define OMAP2_MCSPI_REVISION 0x00
57 #define OMAP2_MCSPI_SYSCONFIG 0x10
58 #define OMAP2_MCSPI_SYSSTATUS 0x14
59 #define OMAP2_MCSPI_IRQSTATUS 0x18
60 #define OMAP2_MCSPI_IRQENABLE 0x1c
61 #define OMAP2_MCSPI_WAKEUPENABLE 0x20
62 #define OMAP2_MCSPI_SYST 0x24
63 #define OMAP2_MCSPI_MODULCTRL 0x28
65 /* per-channel banks, 0x14 bytes each, first is: */
66 #define OMAP2_MCSPI_CHCONF0 0x2c
67 #define OMAP2_MCSPI_CHSTAT0 0x30
68 #define OMAP2_MCSPI_CHCTRL0 0x34
69 #define OMAP2_MCSPI_TX0 0x38
70 #define OMAP2_MCSPI_RX0 0x3c
72 /* per-register bitmasks: */
74 #define OMAP2_MCSPI_SYSCONFIG_AUTOIDLE (1 << 0)
75 #define OMAP2_MCSPI_SYSCONFIG_SOFTRESET (1 << 1)
76 #define OMAP2_AFTR_RST_SET_MASTER (0 << 2)
78 #define OMAP2_MCSPI_SYSSTATUS_RESETDONE (1 << 0)
79 #define OMAP2_MCSPI_SYS_CON_LVL_1 1
80 #define OMAP2_MCSPI_SYS_CON_LVL_2 2
82 #define OMAP2_MCSPI_MODULCTRL_SINGLE (1 << 0)
83 #define OMAP2_MCSPI_MODULCTRL_MS (1 << 2)
84 #define OMAP2_MCSPI_MODULCTRL_STEST (1 << 3)
86 #define OMAP2_MCSPI_CHCONF_PHA (1 << 0)
87 #define OMAP2_MCSPI_CHCONF_POL (1 << 1)
88 #define OMAP2_MCSPI_CHCONF_CLKD_MASK (0x0f << 2)
89 #define OMAP2_MCSPI_CHCONF_EPOL (1 << 6)
90 #define OMAP2_MCSPI_CHCONF_WL_MASK (0x1f << 7)
91 #define OMAP2_MCSPI_CHCONF_TRM_RX_ONLY (0x01 << 12)
92 #define OMAP2_MCSPI_CHCONF_TRM_TX_ONLY (0x02 << 12)
93 #define OMAP2_MCSPI_CHCONF_TRM_MASK (0x03 << 12)
94 #define OMAP2_MCSPI_CHCONF_TRM_TXRX (~OMAP2_MCSPI_CHCONF_TRM_MASK)
95 #define OMAP2_MCSPI_CHCONF_DMAW (1 << 14)
96 #define OMAP2_MCSPI_CHCONF_DMAR (1 << 15)
97 #define OMAP2_MCSPI_CHCONF_DPE0 (1 << 16)
98 #define OMAP2_MCSPI_CHCONF_DPE1 (1 << 17)
99 #define OMAP2_MCSPI_CHCONF_IS (1 << 18)
100 #define OMAP2_MCSPI_CHCONF_TURBO (1 << 19)
101 #define OMAP2_MCSPI_CHCONF_FORCE (1 << 20)
102 #define OMAP2_MCSPI_CHCONF_TCS0 (1 << 25)
103 #define OMAP2_MCSPI_CHCONF_TCS1 (1 << 26)
104 #define OMAP2_MCSPI_CHCONF_TCS_MASK (0x03 << 25)
106 #define OMAP2_MCSPI_SYSCFG_WKUP (1 << 2)
107 #define OMAP2_MCSPI_SYSCFG_IDL (2 << 3)
108 #define OMAP2_MCSPI_SYSCFG_CLK (2 << 8)
109 #define OMAP2_MCSPI_WAKEUP_EN (1 << 1)
110 #define OMAP2_MCSPI_IRQ_WKS (1 << 16)
111 #define OMAP2_MCSPI_CHSTAT_RXS (1 << 0)
112 #define OMAP2_MCSPI_CHSTAT_TXS (1 << 1)
113 #define OMAP2_MCSPI_CHSTAT_EOT (1 << 2)
115 #define OMAP2_MCSPI_CHCTRL_EN (1 << 0)
116 #define OMAP2_MCSPI_MODE_IS_MASTER 0
117 #define OMAP2_MCSPI_MODE_IS_SLAVE 1
118 #define OMAP_MCSPI_WAKEUP_ENABLE 1
120 /*mcspi base address: (0x48098000)1st SPI, (0x4809A00) 2nd SPI*/
121 #define OMAP_MCSPI_BASE 0x48098000
124 #define CLOCK_DIV 12 /* 2^(12)=4096 48000000/4096<19200 */
128 #define WRITE_CPCAP 1
131 #define CM_ICLKEN1_CORE 0x48004A10
132 #define CM_FCLKEN1_CORE 0x48004A00
133 #define OMAP2_MCSPI_EN_MCSPI1 (1 << 18)
136 #define RAW_MOD_REG_BIT(val, mask, set) do { \
153 static bool emu_uart_is_active
= FALSE
;
155 /* Although SPI driver is provided through linux system as implemented above,
156 * it can not cover some special situation.
158 * During Debug phase, OMAP may need to acess CPCAP by SPI
159 * to configure or check related register when boot up is not finished.
160 * However, at this time, spi driver integrated in linux system may not
161 * be initialized properly.
163 * So we provode the following SPI driver with common API for access capcap
164 * by SPI directly, i.e. we will skip the linux system driver,
165 * but access SPI hardware directly to configure read/write specially for
168 * So developer should be very careful to use these APIs:
170 * read_cpcap_register_raw()
171 * write_cpcap_register_raw()
173 * Pay attention: Only use them when boot up phase.
174 * Rasons are as follows:
175 * 1. Although we provide protection on these two APIs for concurrency and
176 * race conditions, it may impact the performance of system
177 * because it will mask all interrupts during access.
178 * 2. Calling these APIs will reset all SPI registers, and may make previous
179 * data lost during run time.
181 * So, if developer wants to access CPCAP after boot up is finished,
182 * we suggest they should use poweric interface.
186 static inline void raw_writel_reg(u32 value
, u32 reg
)
188 unsigned int absolute_reg
= (u32
)OMAP_MCSPI_BASE
+ reg
;
189 #if defined(LOCAL_DEVELOPER_DEBUG)
190 printk(KERN_ERR
" raw write reg =0x%x value=0x%x \n", absolute_reg
,
193 omap_writel(value
, absolute_reg
);
196 static inline u32
raw_readl_reg(u32 reg
)
199 unsigned int absolute_reg
= (u32
)OMAP_MCSPI_BASE
+ reg
;
200 result
= omap_readl(absolute_reg
);
201 #if defined(LOCAL_DEVELOPER_DEBUG)
202 printk(KERN_ERR
" raw read reg =0x%x result =0x%x \n",
203 absolute_reg
, result
);
208 static void raw_omap_mcspi_wakeup_enable(int level
)
212 /* configure SYSCONFIG register... */
213 if (level
== LEVEL1
) {
214 result
= raw_readl_reg(OMAP2_MCSPI_SYSCONFIG
);
216 result
| OMAP2_MCSPI_SYSCFG_WKUP
|
217 OMAP2_MCSPI_SYSCFG_IDL
| OMAP2_MCSPI_SYSCFG_CLK
|
218 OMAP2_MCSPI_SYSCONFIG_AUTOIDLE
;
219 raw_writel_reg(result
, OMAP2_MCSPI_SYSCONFIG
);
222 if (level
== LEVEL2
) {
223 result
= raw_readl_reg(OMAP2_MCSPI_SYSCONFIG
);
225 result
| OMAP2_MCSPI_SYSCFG_WKUP
|
226 OMAP2_MCSPI_SYSCFG_IDL
|
227 OMAP2_MCSPI_SYSCONFIG_AUTOIDLE
;
228 RAW_MOD_REG_BIT(result
, OMAP2_MCSPI_SYSCFG_CLK
, 0);
229 raw_writel_reg(result
, OMAP2_MCSPI_SYSCONFIG
);
232 /* configure wakeupenable register... */
233 raw_writel_reg(OMAP2_MCSPI_WAKEUP_EN
, OMAP2_MCSPI_WAKEUPENABLE
);
235 /* configure enable interrupt register... */
236 result
= raw_readl_reg(OMAP2_MCSPI_IRQENABLE
);
237 result
= result
| OMAP2_MCSPI_IRQ_WKS
;
238 raw_writel_reg(result
, OMAP2_MCSPI_IRQENABLE
);
241 static void raw_omap2_mcspi_set_master_mode(void)
245 /* configure MCSPI_MODULCTRL register... */
246 result
= raw_readl_reg(OMAP2_MCSPI_MODULCTRL
);
248 RAW_MOD_REG_BIT(result
, OMAP2_MCSPI_MODULCTRL_STEST
, 0);
249 RAW_MOD_REG_BIT(result
, OMAP2_MCSPI_MODULCTRL_MS
,
250 OMAP2_MCSPI_MODE_IS_MASTER
);
251 RAW_MOD_REG_BIT(result
, OMAP2_MCSPI_MODULCTRL_SINGLE
, 1);
253 raw_writel_reg(result
, OMAP2_MCSPI_MODULCTRL
);
256 static void raw_omap2_mcspi_channel_config(void)
260 /* select channel 0... otherwise 0x14*channel_num */
261 result
= raw_readl_reg(OMAP2_MCSPI_CHCONF0
);
263 /* TCS Chip select Timing(2.5 clock cycles) */
264 result
&= ~(OMAP2_MCSPI_CHCONF_TCS_MASK
);
265 result
|= OMAP2_MCSPI_CHCONF_TCS1
;
267 /* configure master mode... */
268 result
&= ~OMAP2_MCSPI_CHCONF_IS
;
269 result
&= ~OMAP2_MCSPI_CHCONF_DPE1
;
270 result
|= OMAP2_MCSPI_CHCONF_DPE0
;
272 /* configure wordlength */
273 result
&= ~OMAP2_MCSPI_CHCONF_WL_MASK
;
274 result
|= (WORD_LEN
- 1) << 7;
276 /* configure active high */
277 result
&= ~OMAP2_MCSPI_CHCONF_EPOL
;
279 /* set clock divisor */
280 result
&= ~OMAP2_MCSPI_CHCONF_CLKD_MASK
;
281 result
|= CLOCK_DIV
<< 2;
283 /* configure mode polarity=0 phase=0 */
284 result
&= ~OMAP2_MCSPI_CHCONF_POL
;
285 result
&= ~OMAP2_MCSPI_CHCONF_PHA
;
287 raw_writel_reg(result
, OMAP2_MCSPI_CHCONF0
);
291 static void raw_mcspi_setup(void)
293 raw_omap_mcspi_wakeup_enable(LEVEL1
);
294 raw_omap2_mcspi_set_master_mode();
295 raw_omap2_mcspi_channel_config();
296 raw_omap_mcspi_wakeup_enable(LEVEL2
);
299 static int raw_mcspi_reset(void)
301 unsigned long timeout
;
304 raw_omap_mcspi_wakeup_enable(LEVEL1
);
306 raw_writel_reg(OMAP2_MCSPI_SYSCONFIG_SOFTRESET
,
307 OMAP2_MCSPI_SYSCONFIG
);
309 timeout
= jiffies
+ msecs_to_jiffies(1000);
312 tmp
= raw_readl_reg(OMAP2_MCSPI_SYSSTATUS
);
313 if (time_after(jiffies
, timeout
)) {
314 printk(KERN_ERR
"SPI Error: Reset is time out!\n");
317 } while (!(tmp
& OMAP2_MCSPI_SYSSTATUS_RESETDONE
));
319 /*configure all modules in reset master mode */
320 raw_writel_reg(OMAP2_AFTR_RST_SET_MASTER
, OMAP2_MCSPI_MODULCTRL
);
322 /* call wakeup function to set sysconfig as per pm activity */
323 raw_omap_mcspi_wakeup_enable(LEVEL1
);
324 raw_omap_mcspi_wakeup_enable(LEVEL2
);
329 static void raw_omap2_mcspi_force_cs(int enable_tag
)
332 result
= raw_readl_reg(OMAP2_MCSPI_CHCONF0
);
334 * Manual spim_csx assertion to keep spim_csx for channel x active
335 * RW 0x0 between SPI words (single channel master mode only).
337 RAW_MOD_REG_BIT(result
, OMAP2_MCSPI_CHCONF_FORCE
, enable_tag
);
338 raw_writel_reg(result
, OMAP2_MCSPI_CHCONF0
);
341 static void raw_omap2_mcspi_set_enable(int enable
)
345 result
= enable
? OMAP2_MCSPI_CHCTRL_EN
: 0;
346 raw_writel_reg(result
, OMAP2_MCSPI_CHCTRL0
);
350 static int raw_mcspi_wait_for_reg_bit(unsigned long reg
, unsigned long bit
)
352 unsigned long timeout
;
354 timeout
= jiffies
+ msecs_to_jiffies(1000);
356 while (!(raw_readl_reg(reg
) & bit
)) {
357 if (time_after(jiffies
, timeout
))
364 static void parser_cpcap(struct cpcap_dev
*dev
)
366 if (dev
->access_flag
== WRITE_CPCAP
) {
367 tx
[3] = ((dev
->address
>> 6) & 0x000000FF) | 0x80;
368 tx
[2] = (dev
->address
<< 2) & 0x000000FF;
369 tx
[1] = (dev
->value
>> 8) & 0x000000FF;
370 tx
[0] = dev
->value
& 0x000000FF;
372 tx
[3] = ((dev
->address
>> 6) & 0x000000FF);
373 tx
[2] = (dev
->address
<< 2) & 0x000000FF;
379 static void raw_omap2_mcspi_txrx_pio(struct cpcap_dev
*dev
)
384 /* config tranmission mode --- tx rx together */
385 result
= raw_readl_reg(OMAP2_MCSPI_CHCONF0
);
386 result
&= ~OMAP2_MCSPI_CHCONF_TRM_MASK
;
387 raw_writel_reg(result
, OMAP2_MCSPI_CHCONF0
);
389 /* enable the mcspi port! */
390 raw_omap2_mcspi_set_enable(1);
394 memcpy((void *)&tx_32bit
, (void *)tx
, 4);
396 if (raw_mcspi_wait_for_reg_bit(OMAP2_MCSPI_CHSTAT0
,
397 OMAP2_MCSPI_CHSTAT_TXS
) < 0) {
398 printk(KERN_ERR
"SPI Error: TXS timed out\n");
401 raw_writel_reg(tx_32bit
, OMAP2_MCSPI_TX0
);
403 if (raw_mcspi_wait_for_reg_bit(OMAP2_MCSPI_CHSTAT0
,
404 OMAP2_MCSPI_CHSTAT_RXS
) < 0) {
405 printk(KERN_ERR
"SPI Error: RXS timed out\n");
409 result
= raw_readl_reg(OMAP2_MCSPI_RX0
);
411 dev
->result
= result
;
414 /* disable the mcspi port! */
415 raw_omap2_mcspi_set_enable(0);
418 static void raw_mcspi_run(struct cpcap_dev
*dev
)
420 raw_omap_mcspi_wakeup_enable(LEVEL1
);
421 raw_omap2_mcspi_set_master_mode();
422 raw_omap2_mcspi_channel_config();
423 raw_omap2_mcspi_force_cs(1);
424 raw_omap2_mcspi_txrx_pio(dev
);
425 raw_omap2_mcspi_force_cs(0);
426 raw_omap_mcspi_wakeup_enable(LEVEL2
);
429 static void raw_omap_mcspi_enable_IFclock(void)
433 result
= omap_readl(CM_FCLKEN1_CORE
);
434 RAW_MOD_REG_BIT(result
, OMAP2_MCSPI_EN_MCSPI1
, 1);
435 omap_writel(result
, CM_FCLKEN1_CORE
);
437 result
= omap_readl(CM_ICLKEN1_CORE
);
438 RAW_MOD_REG_BIT(result
, OMAP2_MCSPI_EN_MCSPI1
, 1);
439 omap_writel(result
, CM_ICLKEN1_CORE
);
444 * write_cpcap_register_raw is for cpcap spi write directly
445 * @return 0 on success; less than zero on failure.
447 static int write_cpcap_register_raw(u16 addr
, u16 val
)
450 unsigned long intr_flags
;
451 struct cpcap_dev cpcap_write
;
453 #ifdef CONFIG_EMU_UART_DEBUG
454 if (is_emu_uart_active() && (addr
== 897 || addr
== 411))
458 local_irq_save(intr_flags
);
459 raw_omap_mcspi_enable_IFclock();
461 result
= raw_mcspi_reset();
463 local_irq_restore(intr_flags
);
464 printk(KERN_ERR
"reset failed !\n");
470 cpcap_write
.address
= addr
;
471 cpcap_write
.value
= val
;
472 cpcap_write
.access_flag
= WRITE_CPCAP
;
473 raw_mcspi_run(&cpcap_write
);
475 local_irq_restore(intr_flags
);
481 * read_cpcap_register_raw is for cpcap spi read directly,
482 * read result is in val
483 * @return 0 on success; less than zero on failure.
485 static int read_cpcap_register_raw(u16 addr
, u16
*val
)
488 unsigned long intr_flag
;
489 struct cpcap_dev cpcap_read
;
491 local_irq_save(intr_flag
);
492 raw_omap_mcspi_enable_IFclock();
494 result
= raw_mcspi_reset();
496 local_irq_restore(intr_flag
);
497 printk(KERN_ERR
"reset failed !\n");
503 cpcap_read
.address
= addr
;
504 cpcap_read
.access_flag
= READ_CPCAP
;
505 raw_mcspi_run(&cpcap_read
);
506 *val
= cpcap_read
.result
;
508 local_irq_restore(intr_flag
);
515 * Check if the writting is allowed. If MiniUSB port has already been
516 * configured as UART3, we should ignore some SCM register writting.
518 int is_emu_uart_iomux_reg(unsigned short offset
)
520 if ((emu_uart_is_active
) && \
521 ((offset
>= 0x1A2 && offset
< 0x1BA) || (offset
== 0x19E)))
527 bool is_emu_uart_active(void)
529 return emu_uart_is_active
;
532 static void write_omap_mux_register(u16 offset
, u8 mode
, u8 input_en
)
534 u16 tmp_val
, reg_val
;
535 u32 reg
= OMAP343X_CTRL_BASE
+ offset
;
537 reg_val
= mode
| (input_en
<< 8);
538 tmp_val
= omap_readw(reg
) & ~(0x0007 | (1 << 8));
539 reg_val
= reg_val
| tmp_val
;
540 omap_writew(reg_val
, reg
);
543 static int find_ms2_dev(struct device
*dev
, void *data
)
545 if (!strncmp((char*)data
, dev_name(dev
), strlen((char*)data
))) {
546 printk(KERN_INFO
"Found it\n");
553 * c01fcb98 T cpcap_regacc_read
554 * c01fcc04 T cpcap_regacc_write
558 static int (*my_cpcap_regacc_read
)(struct cpcap_device
*, enum cpcap_reg
, unsigned short *) =
559 (int (*)(struct cpcap_device
*, enum cpcap_reg
, unsigned short *))0xc01fcb98;
561 static int (*my_cpcap_regacc_write
)(struct cpcap_device
*, enum cpcap_reg
, unsigned short, unsigned short) =
562 (int (*)(struct cpcap_device
*, enum cpcap_reg
, unsigned short, unsigned short))0xc01fcc04;
565 void activate_emu_uart(void)
569 struct device
*cpcap
= NULL
;
570 struct cpcap_device
*cpcap_dev
;
572 printk(KERN_INFO
"Searching for cpcap_usb...\n");
574 cpcap
= device_find_child(&platform_bus
, "cpcap_usb", find_ms2_dev
);
578 cpcap_dev
= cpcap
->platform_data
;
579 if (cpcap_dev
== NULL
)
582 //read_cpcap_register_raw(18, &tmp);
583 my_cpcap_regacc_read(cpcap_dev
, CPCAP_REG_VERSC1
, &tmp
);
584 printk(KERN_ALERT
"Reading CPCAP vendor_version: 0x%04X\n", tmp
);
587 * Configure OMAP SCM to set all ULPI pin of USB OTG to SAFE MODE
589 for (i
= 0; i
< 0x18; i
+= 2)
590 write_omap_mux_register(0x1A2 + i
, 7, 0);
594 * Configure CPCAP to route UART3 to USB port; Switch VBUSIN to supply
595 * UART/USB transeiver and set VBUS standby mode 3
597 //write_cpcap_register_raw(897, 0x0101);
598 //write_cpcap_register_raw(411, 0x014C);
600 * [CPCAP_REG_VUSBC] = {411, 0xFFFF, 0xFFFF},
601 * [CPCAP_REG_USBC2] = {897, 0x0F07, 0xFFFF},
604 my_cpcap_regacc_write(cpcap_dev
, CPCAP_REG_VUSBC
, 0xffff, 0xffff);
605 my_cpcap_regacc_write(cpcap_dev
, CPCAP_REG_USBC2
, 0x0f07, 0xffff);
606 my_cpcap_regacc_write(cpcap_dev
, CPCAP_REG_USBC2
, 0x0101, 0xffff);
607 my_cpcap_regacc_write(cpcap_dev
, CPCAP_REG_VUSBC
, 0x014c, 0xffff);
610 * Configure OMAP SCM to set ULPI port as UART3 function
613 * Set UART3 RX pin in safe mode
615 write_omap_mux_register(0x19E, 7, 0);
617 * Route UART3 TX to ULPIDATA0, RX to ULPIDATA1
619 write_omap_mux_register(0x1AA, 2, 0);
620 write_omap_mux_register(0x1AC, 2, 1);
622 emu_uart_is_active
= TRUE
;
624 (KERN_ALERT
"WARNING: MiniUSB port works in UART3 mode,"
625 "the USB functionality UNAVAILABLE!\n");