Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mpsc.c
Go to the documentation of this file.
1 /*
2  * MPSC/UART driver for the Marvell mv64360, mv64460, ...
3  *
4  * Author: Mark A. Greer <[email protected]>
5  *
6  * 2007 (c) MontaVista Software, Inc. This file is licensed under
7  * the terms of the GNU General Public License version 2. This program
8  * is licensed "as is" without any warranty of any kind, whether express
9  * or implied.
10  */
11 
12 #include <stdarg.h>
13 #include <stddef.h>
14 #include "types.h"
15 #include "string.h"
16 #include "stdio.h"
17 #include "io.h"
18 #include "ops.h"
19 
20 
21 #define MPSC_CHR_1 0x000c
22 
23 #define MPSC_CHR_2 0x0010
24 #define MPSC_CHR_2_TA (1<<7)
25 #define MPSC_CHR_2_TCS (1<<9)
26 #define MPSC_CHR_2_RA (1<<23)
27 #define MPSC_CHR_2_CRD (1<<25)
28 #define MPSC_CHR_2_EH (1<<31)
29 
30 #define MPSC_CHR_4 0x0018
31 #define MPSC_CHR_4_Z (1<<29)
32 
33 #define MPSC_CHR_5 0x001c
34 #define MPSC_CHR_5_CTL1_INTR (1<<12)
35 #define MPSC_CHR_5_CTL1_VALID (1<<15)
36 
37 #define MPSC_CHR_10 0x0030
38 
39 #define MPSC_INTR_CAUSE 0x0000
40 #define MPSC_INTR_CAUSE_RCC (1<<6)
41 #define MPSC_INTR_MASK 0x0080
42 
43 #define SDMA_SDCM 0x0008
44 #define SDMA_SDCM_AR (1<<15)
45 #define SDMA_SDCM_AT (1<<31)
46 
47 static volatile char *mpsc_base;
48 static volatile char *mpscintr_base;
49 static u32 chr1, chr2;
50 
51 static int mpsc_open(void)
52 {
53  chr1 = in_le32((u32 *)(mpsc_base + MPSC_CHR_1)) & 0x00ff0000;
54  chr2 = in_le32((u32 *)(mpsc_base + MPSC_CHR_2)) & ~(MPSC_CHR_2_TA
56  | MPSC_CHR_2_EH);
57  out_le32((u32 *)(mpsc_base + MPSC_CHR_4), MPSC_CHR_4_Z);
58  out_le32((u32 *)(mpsc_base + MPSC_CHR_5),
60  out_le32((u32 *)(mpsc_base + MPSC_CHR_2), chr2 | MPSC_CHR_2_EH);
61  return 0;
62 }
63 
64 static void mpsc_putc(unsigned char c)
65 {
66  while (in_le32((u32 *)(mpsc_base + MPSC_CHR_2)) & MPSC_CHR_2_TCS);
67 
68  out_le32((u32 *)(mpsc_base + MPSC_CHR_1), chr1 | c);
69  out_le32((u32 *)(mpsc_base + MPSC_CHR_2), chr2 | MPSC_CHR_2_TCS);
70 }
71 
72 static unsigned char mpsc_getc(void)
73 {
74  u32 cause = 0;
75  unsigned char c;
76 
77  while (!(cause & MPSC_INTR_CAUSE_RCC))
78  cause = in_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE));
79 
80  c = in_8((u8 *)(mpsc_base + MPSC_CHR_10 + 2));
81  out_8((u8 *)(mpsc_base + MPSC_CHR_10 + 2), c);
82  out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE),
83  cause & ~MPSC_INTR_CAUSE_RCC);
84 
85  return c;
86 }
87 
88 static u8 mpsc_tstc(void)
89 {
90  return (u8)((in_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE))
91  & MPSC_INTR_CAUSE_RCC) != 0);
92 }
93 
94 static void mpsc_stop_dma(volatile char *sdma_base)
95 {
97  out_le32((u32 *)(sdma_base + SDMA_SDCM), SDMA_SDCM_AR | SDMA_SDCM_AT);
98 
99  while ((in_le32((u32 *)(sdma_base + SDMA_SDCM))
100  & (SDMA_SDCM_AR | SDMA_SDCM_AT)) != 0)
101  udelay(100);
102 }
103 
104 static volatile char *mpsc_get_virtreg_of_phandle(void *devp, char *prop)
105 {
106  void *v;
107  int n;
108 
109  n = getprop(devp, prop, &v, sizeof(v));
110  if (n != sizeof(v))
111  goto err_out;
112 
113  devp = find_node_by_linuxphandle((u32)v);
114  if (devp == NULL)
115  goto err_out;
116 
117  n = getprop(devp, "virtual-reg", &v, sizeof(v));
118  if (n == sizeof(v))
119  return v;
120 
121 err_out:
122  return NULL;
123 }
124 
125 int mpsc_console_init(void *devp, struct serial_console_data *scdp)
126 {
127  void *v;
128  int n, reg_set;
129  volatile char *sdma_base;
130 
131  n = getprop(devp, "virtual-reg", &v, sizeof(v));
132  if (n != sizeof(v))
133  goto err_out;
134  mpsc_base = v;
135 
136  sdma_base = mpsc_get_virtreg_of_phandle(devp, "sdma");
137  if (sdma_base == NULL)
138  goto err_out;
139 
140  mpscintr_base = mpsc_get_virtreg_of_phandle(devp, "mpscintr");
141  if (mpscintr_base == NULL)
142  goto err_out;
143 
144  n = getprop(devp, "cell-index", &v, sizeof(v));
145  if (n != sizeof(v))
146  goto err_out;
147  reg_set = (int)v;
148 
149  mpscintr_base += (reg_set == 0) ? 0x4 : 0xc;
150 
151  /* Make sure the mpsc ctlrs are shutdown */
152  out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE), 0);
153  out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE), 0);
154  out_le32((u32 *)(mpscintr_base + MPSC_INTR_MASK), 0);
155  out_le32((u32 *)(mpscintr_base + MPSC_INTR_MASK), 0);
156 
157  mpsc_stop_dma(sdma_base);
158 
159  scdp->open = mpsc_open;
160  scdp->putc = mpsc_putc;
161  scdp->getc = mpsc_getc;
162  scdp->tstc = mpsc_tstc;
163  scdp->close = NULL;
164 
165  return 0;
166 
167 err_out:
168  return -1;
169 }