]> git.zerfleddert.de Git - ms2-kexec/blob - board-mapphone-emu_uart.c
more non-working serial stuff
[ms2-kexec] / board-mapphone-emu_uart.c
1 /*
2 * board-mapphone-emu_uart.c
3 *
4 * Copyright (C) 2009 Motorola, Inc.
5 *
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.
10 *
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.
15 *
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
19 */
20
21 /* Date Author Comment
22 * =========== ============== ==============================================
23 * Jun-26-2009 Motorola Initial revision.
24 */
25
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>
36 #include <linux/io.h>
37
38 #include <linux/spi/spi.h>
39 #include <plat/system.h>
40 #include <linux/irq.h>
41
42 #include <plat/dma.h>
43 #include <plat/clock.h>
44 #include <plat/board-mapphone-emu_uart.h>
45 #include <plat/hardware.h>
46 #include <plat/omap34xx.h>
47
48 /*
49 * Register definitions for CPCAP related SPI register
50 */
51 #define OMAP2_MCSPI_MAX_FREQ 48000000
52
53 #define OMAP2_MCSPI_REVISION 0x00
54 #define OMAP2_MCSPI_SYSCONFIG 0x10
55 #define OMAP2_MCSPI_SYSSTATUS 0x14
56 #define OMAP2_MCSPI_IRQSTATUS 0x18
57 #define OMAP2_MCSPI_IRQENABLE 0x1c
58 #define OMAP2_MCSPI_WAKEUPENABLE 0x20
59 #define OMAP2_MCSPI_SYST 0x24
60 #define OMAP2_MCSPI_MODULCTRL 0x28
61
62 /* per-channel banks, 0x14 bytes each, first is: */
63 #define OMAP2_MCSPI_CHCONF0 0x2c
64 #define OMAP2_MCSPI_CHSTAT0 0x30
65 #define OMAP2_MCSPI_CHCTRL0 0x34
66 #define OMAP2_MCSPI_TX0 0x38
67 #define OMAP2_MCSPI_RX0 0x3c
68
69 /* per-register bitmasks: */
70
71 #define OMAP2_MCSPI_SYSCONFIG_AUTOIDLE (1 << 0)
72 #define OMAP2_MCSPI_SYSCONFIG_SOFTRESET (1 << 1)
73 #define OMAP2_AFTR_RST_SET_MASTER (0 << 2)
74
75 #define OMAP2_MCSPI_SYSSTATUS_RESETDONE (1 << 0)
76 #define OMAP2_MCSPI_SYS_CON_LVL_1 1
77 #define OMAP2_MCSPI_SYS_CON_LVL_2 2
78
79 #define OMAP2_MCSPI_MODULCTRL_SINGLE (1 << 0)
80 #define OMAP2_MCSPI_MODULCTRL_MS (1 << 2)
81 #define OMAP2_MCSPI_MODULCTRL_STEST (1 << 3)
82
83 #define OMAP2_MCSPI_CHCONF_PHA (1 << 0)
84 #define OMAP2_MCSPI_CHCONF_POL (1 << 1)
85 #define OMAP2_MCSPI_CHCONF_CLKD_MASK (0x0f << 2)
86 #define OMAP2_MCSPI_CHCONF_EPOL (1 << 6)
87 #define OMAP2_MCSPI_CHCONF_WL_MASK (0x1f << 7)
88 #define OMAP2_MCSPI_CHCONF_TRM_RX_ONLY (0x01 << 12)
89 #define OMAP2_MCSPI_CHCONF_TRM_TX_ONLY (0x02 << 12)
90 #define OMAP2_MCSPI_CHCONF_TRM_MASK (0x03 << 12)
91 #define OMAP2_MCSPI_CHCONF_TRM_TXRX (~OMAP2_MCSPI_CHCONF_TRM_MASK)
92 #define OMAP2_MCSPI_CHCONF_DMAW (1 << 14)
93 #define OMAP2_MCSPI_CHCONF_DMAR (1 << 15)
94 #define OMAP2_MCSPI_CHCONF_DPE0 (1 << 16)
95 #define OMAP2_MCSPI_CHCONF_DPE1 (1 << 17)
96 #define OMAP2_MCSPI_CHCONF_IS (1 << 18)
97 #define OMAP2_MCSPI_CHCONF_TURBO (1 << 19)
98 #define OMAP2_MCSPI_CHCONF_FORCE (1 << 20)
99 #define OMAP2_MCSPI_CHCONF_TCS0 (1 << 25)
100 #define OMAP2_MCSPI_CHCONF_TCS1 (1 << 26)
101 #define OMAP2_MCSPI_CHCONF_TCS_MASK (0x03 << 25)
102
103 #define OMAP2_MCSPI_SYSCFG_WKUP (1 << 2)
104 #define OMAP2_MCSPI_SYSCFG_IDL (2 << 3)
105 #define OMAP2_MCSPI_SYSCFG_CLK (2 << 8)
106 #define OMAP2_MCSPI_WAKEUP_EN (1 << 1)
107 #define OMAP2_MCSPI_IRQ_WKS (1 << 16)
108 #define OMAP2_MCSPI_CHSTAT_RXS (1 << 0)
109 #define OMAP2_MCSPI_CHSTAT_TXS (1 << 1)
110 #define OMAP2_MCSPI_CHSTAT_EOT (1 << 2)
111
112 #define OMAP2_MCSPI_CHCTRL_EN (1 << 0)
113 #define OMAP2_MCSPI_MODE_IS_MASTER 0
114 #define OMAP2_MCSPI_MODE_IS_SLAVE 1
115 #define OMAP_MCSPI_WAKEUP_ENABLE 1
116
117 /*mcspi base address: (0x48098000)1st SPI, (0x4809A00) 2nd SPI*/
118 #define OMAP_MCSPI_BASE 0x48098000
119
120 #define WORD_LEN 32
121 #define CLOCK_DIV 12 /* 2^(12)=4096 48000000/4096<19200 */
122
123 #define LEVEL1 1
124 #define LEVEL2 2
125 #define WRITE_CPCAP 1
126 #define READ_CPCAP 0
127
128 #define CM_ICLKEN1_CORE 0x48004A10
129 #define CM_FCLKEN1_CORE 0x48004A00
130 #define OMAP2_MCSPI_EN_MCSPI1 (1 << 18)
131
132 #define RESET_FAIL 1
133 #define RAW_MOD_REG_BIT(val, mask, set) do { \
134 if (set) \
135 val |= mask; \
136 else \
137 val &= ~mask; \
138 } while (0)
139
140 struct cpcap_dev {
141 u16 address;
142 u16 value;
143 u32 result;
144 int access_flag;
145 };
146
147 static char tx[4];
148 static bool emu_uart_is_active = FALSE;
149
150 /* Although SPI driver is provided through linux system as implemented above,
151 * it can not cover some special situation.
152 *
153 * During Debug phase, OMAP may need to acess CPCAP by SPI
154 * to configure or check related register when boot up is not finished.
155 * However, at this time, spi driver integrated in linux system may not
156 * be initialized properly.
157 *
158 * So we provode the following SPI driver with common API for access capcap
159 * by SPI directly, i.e. we will skip the linux system driver,
160 * but access SPI hardware directly to configure read/write specially for
161 * cpcap access.
162 *
163 * So developer should be very careful to use these APIs:
164 *
165 * read_cpcap_register_raw()
166 * write_cpcap_register_raw()
167 *
168 * Pay attention: Only use them when boot up phase.
169 * Rasons are as follows:
170 * 1. Although we provide protection on these two APIs for concurrency and
171 * race conditions, it may impact the performance of system
172 * because it will mask all interrupts during access.
173 * 2. Calling these APIs will reset all SPI registers, and may make previous
174 * data lost during run time.
175 *
176 * So, if developer wants to access CPCAP after boot up is finished,
177 * we suggest they should use poweric interface.
178 *
179 */
180 static inline void raw_writel_reg(u32 value, u32 reg)
181 {
182 unsigned int absolute_reg = (u32)OMAP_MCSPI_BASE + reg;
183 #if defined(LOCAL_DEVELOPER_DEBUG)
184 printk(KERN_ERR " raw write reg =0x%x value=0x%x \n", absolute_reg,
185 value);
186 #endif
187 omap_writel(value, absolute_reg);
188 }
189
190 static inline u32 raw_readl_reg(u32 reg)
191 {
192 u32 result;
193 unsigned int absolute_reg = (u32)OMAP_MCSPI_BASE + reg;
194 result = omap_readl(absolute_reg);
195 #if defined(LOCAL_DEVELOPER_DEBUG)
196 printk(KERN_ERR " raw read reg =0x%x result =0x%x \n",
197 absolute_reg, result);
198 #endif
199 return result;
200 }
201
202 static void raw_omap_mcspi_wakeup_enable(int level)
203 {
204 u32 result;
205
206 /* configure SYSCONFIG register... */
207 if (level == LEVEL1) {
208 result = raw_readl_reg(OMAP2_MCSPI_SYSCONFIG);
209 result =
210 result | OMAP2_MCSPI_SYSCFG_WKUP |
211 OMAP2_MCSPI_SYSCFG_IDL | OMAP2_MCSPI_SYSCFG_CLK |
212 OMAP2_MCSPI_SYSCONFIG_AUTOIDLE;
213 raw_writel_reg(result, OMAP2_MCSPI_SYSCONFIG);
214 }
215
216 if (level == LEVEL2) {
217 result = raw_readl_reg(OMAP2_MCSPI_SYSCONFIG);
218 result =
219 result | OMAP2_MCSPI_SYSCFG_WKUP |
220 OMAP2_MCSPI_SYSCFG_IDL |
221 OMAP2_MCSPI_SYSCONFIG_AUTOIDLE;
222 RAW_MOD_REG_BIT(result, OMAP2_MCSPI_SYSCFG_CLK, 0);
223 raw_writel_reg(result, OMAP2_MCSPI_SYSCONFIG);
224 }
225
226 /* configure wakeupenable register... */
227 raw_writel_reg(OMAP2_MCSPI_WAKEUP_EN, OMAP2_MCSPI_WAKEUPENABLE);
228
229 /* configure enable interrupt register... */
230 result = raw_readl_reg(OMAP2_MCSPI_IRQENABLE);
231 result = result | OMAP2_MCSPI_IRQ_WKS;
232 raw_writel_reg(result, OMAP2_MCSPI_IRQENABLE);
233 }
234
235 static void raw_omap2_mcspi_set_master_mode(void)
236 {
237 u32 result;
238
239 /* configure MCSPI_MODULCTRL register... */
240 result = raw_readl_reg(OMAP2_MCSPI_MODULCTRL);
241
242 RAW_MOD_REG_BIT(result, OMAP2_MCSPI_MODULCTRL_STEST, 0);
243 RAW_MOD_REG_BIT(result, OMAP2_MCSPI_MODULCTRL_MS,
244 OMAP2_MCSPI_MODE_IS_MASTER);
245 RAW_MOD_REG_BIT(result, OMAP2_MCSPI_MODULCTRL_SINGLE, 1);
246
247 raw_writel_reg(result, OMAP2_MCSPI_MODULCTRL);
248 }
249
250 static void raw_omap2_mcspi_channel_config(void)
251 {
252 u32 result;
253
254 /* select channel 0... otherwise 0x14*channel_num */
255 result = raw_readl_reg(OMAP2_MCSPI_CHCONF0);
256
257 /* TCS Chip select Timing(2.5 clock cycles) */
258 result &= ~(OMAP2_MCSPI_CHCONF_TCS_MASK);
259 result |= OMAP2_MCSPI_CHCONF_TCS1;
260
261 /* configure master mode... */
262 result &= ~OMAP2_MCSPI_CHCONF_IS;
263 result &= ~OMAP2_MCSPI_CHCONF_DPE1;
264 result |= OMAP2_MCSPI_CHCONF_DPE0;
265
266 /* configure wordlength */
267 result &= ~OMAP2_MCSPI_CHCONF_WL_MASK;
268 result |= (WORD_LEN - 1) << 7;
269
270 /* configure active high */
271 result &= ~OMAP2_MCSPI_CHCONF_EPOL;
272
273 /* set clock divisor */
274 result &= ~OMAP2_MCSPI_CHCONF_CLKD_MASK;
275 result |= CLOCK_DIV << 2;
276
277 /* configure mode polarity=0 phase=0 */
278 result &= ~OMAP2_MCSPI_CHCONF_POL;
279 result &= ~OMAP2_MCSPI_CHCONF_PHA;
280
281 raw_writel_reg(result, OMAP2_MCSPI_CHCONF0);
282
283 }
284
285 static void raw_mcspi_setup(void)
286 {
287 raw_omap_mcspi_wakeup_enable(LEVEL1);
288 raw_omap2_mcspi_set_master_mode();
289 raw_omap2_mcspi_channel_config();
290 raw_omap_mcspi_wakeup_enable(LEVEL2);
291 }
292
293 static int raw_mcspi_reset(void)
294 {
295 unsigned long timeout;
296 u32 tmp;
297
298 raw_omap_mcspi_wakeup_enable(LEVEL1);
299
300 raw_writel_reg(OMAP2_MCSPI_SYSCONFIG_SOFTRESET,
301 OMAP2_MCSPI_SYSCONFIG);
302
303 timeout = jiffies + msecs_to_jiffies(1000);
304
305 do {
306 tmp = raw_readl_reg(OMAP2_MCSPI_SYSSTATUS);
307 if (time_after(jiffies, timeout)) {
308 printk(KERN_ERR "SPI Error: Reset is time out!\n");
309 return -RESET_FAIL;
310 }
311 } while (!(tmp & OMAP2_MCSPI_SYSSTATUS_RESETDONE));
312
313 /*configure all modules in reset master mode */
314 raw_writel_reg(OMAP2_AFTR_RST_SET_MASTER, OMAP2_MCSPI_MODULCTRL);
315
316 /* call wakeup function to set sysconfig as per pm activity */
317 raw_omap_mcspi_wakeup_enable(LEVEL1);
318 raw_omap_mcspi_wakeup_enable(LEVEL2);
319
320 return 0;
321 }
322
323 static void raw_omap2_mcspi_force_cs(int enable_tag)
324 {
325 u32 result;
326 result = raw_readl_reg(OMAP2_MCSPI_CHCONF0);
327 /*
328 * Manual spim_csx assertion to keep spim_csx for channel x active
329 * RW 0x0 between SPI words (single channel master mode only).
330 */
331 RAW_MOD_REG_BIT(result, OMAP2_MCSPI_CHCONF_FORCE, enable_tag);
332 raw_writel_reg(result, OMAP2_MCSPI_CHCONF0);
333 }
334
335 static void raw_omap2_mcspi_set_enable(int enable)
336 {
337 u32 result;
338
339 result = enable ? OMAP2_MCSPI_CHCTRL_EN : 0;
340 raw_writel_reg(result, OMAP2_MCSPI_CHCTRL0);
341 }
342
343
344 static int raw_mcspi_wait_for_reg_bit(unsigned long reg, unsigned long bit)
345 {
346 unsigned long timeout;
347
348 timeout = jiffies + msecs_to_jiffies(1000);
349
350 while (!(raw_readl_reg(reg) & bit)) {
351 if (time_after(jiffies, timeout))
352 return -1;
353 }
354
355 return 0;
356 }
357
358 static void parser_cpcap(struct cpcap_dev *dev)
359 {
360 if (dev->access_flag == WRITE_CPCAP) {
361 tx[3] = ((dev->address >> 6) & 0x000000FF) | 0x80;
362 tx[2] = (dev->address << 2) & 0x000000FF;
363 tx[1] = (dev->value >> 8) & 0x000000FF;
364 tx[0] = dev->value & 0x000000FF;
365 } else {
366 tx[3] = ((dev->address >> 6) & 0x000000FF);
367 tx[2] = (dev->address << 2) & 0x000000FF;
368 tx[1] = 1;
369 tx[0] = 1;
370 }
371 }
372
373 static void raw_omap2_mcspi_txrx_pio(struct cpcap_dev *dev)
374 {
375 u32 result;
376 u32 tx_32bit;
377
378 /* config tranmission mode --- tx rx together */
379 result = raw_readl_reg(OMAP2_MCSPI_CHCONF0);
380 result &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
381 raw_writel_reg(result, OMAP2_MCSPI_CHCONF0);
382
383 /* enable the mcspi port! */
384 raw_omap2_mcspi_set_enable(1);
385
386 parser_cpcap(dev);
387
388 memcpy((void *)&tx_32bit, (void *)tx, 4);
389
390 if (raw_mcspi_wait_for_reg_bit(OMAP2_MCSPI_CHSTAT0,
391 OMAP2_MCSPI_CHSTAT_TXS) < 0) {
392 printk(KERN_ERR "SPI Error: TXS timed out\n");
393 goto out;
394 }
395 raw_writel_reg(tx_32bit, OMAP2_MCSPI_TX0);
396
397 if (raw_mcspi_wait_for_reg_bit(OMAP2_MCSPI_CHSTAT0,
398 OMAP2_MCSPI_CHSTAT_RXS) < 0) {
399 printk(KERN_ERR "SPI Error: RXS timed out\n");
400 goto out;
401 }
402
403 result = raw_readl_reg(OMAP2_MCSPI_RX0);
404
405 dev->result = result;
406
407 out:
408 /* disable the mcspi port! */
409 raw_omap2_mcspi_set_enable(0);
410 }
411
412 static void raw_mcspi_run(struct cpcap_dev *dev)
413 {
414 raw_omap_mcspi_wakeup_enable(LEVEL1);
415 raw_omap2_mcspi_set_master_mode();
416 raw_omap2_mcspi_channel_config();
417 raw_omap2_mcspi_force_cs(1);
418 raw_omap2_mcspi_txrx_pio(dev);
419 raw_omap2_mcspi_force_cs(0);
420 raw_omap_mcspi_wakeup_enable(LEVEL2);
421 }
422
423 static void raw_omap_mcspi_enable_IFclock(void)
424 {
425 u32 result;
426
427 result = omap_readl(CM_FCLKEN1_CORE);
428 RAW_MOD_REG_BIT(result, OMAP2_MCSPI_EN_MCSPI1, 1);
429 omap_writel(result, CM_FCLKEN1_CORE);
430
431 result = omap_readl(CM_ICLKEN1_CORE);
432 RAW_MOD_REG_BIT(result, OMAP2_MCSPI_EN_MCSPI1, 1);
433 omap_writel(result, CM_ICLKEN1_CORE);
434
435 }
436
437 /*
438 * write_cpcap_register_raw is for cpcap spi write directly
439 * @return 0 on success; less than zero on failure.
440 */
441 static int write_cpcap_register_raw(u16 addr, u16 val)
442 {
443 int result;
444 unsigned long intr_flags;
445 struct cpcap_dev cpcap_write;
446
447 #ifdef CONFIG_EMU_UART_DEBUG
448 if (is_emu_uart_active() && (addr == 897 || addr == 411))
449 return 0;
450 #endif
451
452 local_irq_save(intr_flags);
453 raw_omap_mcspi_enable_IFclock();
454
455 result = raw_mcspi_reset();
456 if (result < 0) {
457 local_irq_restore(intr_flags);
458 printk(KERN_ERR "reset failed !\n");
459 return result;
460 }
461
462 raw_mcspi_setup();
463
464 cpcap_write.address = addr;
465 cpcap_write.value = val;
466 cpcap_write.access_flag = WRITE_CPCAP;
467 raw_mcspi_run(&cpcap_write);
468
469 local_irq_restore(intr_flags);
470
471 return result;
472 }
473
474 /*
475 * read_cpcap_register_raw is for cpcap spi read directly,
476 * read result is in val
477 * @return 0 on success; less than zero on failure.
478 */
479 static int read_cpcap_register_raw(u16 addr, u16 *val)
480 {
481 int result;
482 unsigned long intr_flag;
483 struct cpcap_dev cpcap_read;
484
485 local_irq_save(intr_flag);
486 raw_omap_mcspi_enable_IFclock();
487
488 result = raw_mcspi_reset();
489 if (result < 0) {
490 local_irq_restore(intr_flag);
491 printk(KERN_ERR "reset failed !\n");
492 return result;
493 }
494
495 raw_mcspi_setup();
496
497 cpcap_read.address = addr;
498 cpcap_read.access_flag = READ_CPCAP;
499 raw_mcspi_run(&cpcap_read);
500 *val = cpcap_read.result;
501
502 local_irq_restore(intr_flag);
503
504 return result;
505 }
506
507 /*
508 * Check if the writting is allowed. If MiniUSB port has already been
509 * configured as UART3, we should ignore some SCM register writting.
510 */
511 int is_emu_uart_iomux_reg(unsigned short offset)
512 {
513 if ((emu_uart_is_active) && \
514 ((offset >= 0x1A2 && offset < 0x1BA) || (offset == 0x19E)))
515 return 1;
516 else
517 return 0;
518 }
519
520 bool is_emu_uart_active(void)
521 {
522 return emu_uart_is_active;
523 }
524
525 static void write_omap_mux_register(u16 offset, u8 mode, u8 input_en)
526 {
527 u16 tmp_val, reg_val;
528 u32 reg = OMAP343X_CTRL_BASE + offset;
529
530 reg_val = mode | (input_en << 8);
531 tmp_val = omap_readw(reg) & ~(0x0007 | (1 << 8));
532 reg_val = reg_val | tmp_val;
533 omap_writew(reg_val, reg);
534 }
535
536 void activate_emu_uart(void)
537 {
538 int i;
539 u16 tmp = 0;
540
541 read_cpcap_register_raw(18, &tmp);
542 printk(KERN_ALERT "Reading CPCAP vendor_version: 0x%04X\n", tmp);
543 /*
544 * Step 1:
545 * Configure OMAP SCM to set all ULPI pin of USB OTG to SAFE MODE
546 */
547 for (i = 0; i < 0x18; i += 2)
548 write_omap_mux_register(0x1A2 + i, 7, 0);
549
550 /*
551 * Step 2:
552 * Configure CPCAP to route UART3 to USB port; Switch VBUSIN to supply
553 * UART/USB transeiver and set VBUS standby mode 3
554 */
555 write_cpcap_register_raw(897, 0x0101);
556 write_cpcap_register_raw(411, 0x014C);
557
558 /* Step 3:
559 * Configure OMAP SCM to set ULPI port as UART3 function
560 */
561 /*
562 * Set UART3 RX pin in safe mode
563 */
564 write_omap_mux_register(0x19E, 7, 0);
565 /*
566 * Route UART3 TX to ULPIDATA0, RX to ULPIDATA1
567 */
568 write_omap_mux_register(0x1AA, 2, 0);
569 write_omap_mux_register(0x1AC, 2, 1);
570
571 emu_uart_is_active = TRUE;
572 printk
573 (KERN_ALERT "WARNING: MiniUSB port works in UART3 mode,"
574 "the USB functionality UNAVAILABLE!\n");
575
576 }
Impressum, Datenschutz