Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
mips
pmc-sierra
msp71xx
msp_serial.c
Go to the documentation of this file.
1
/*
2
* The setup file for serial related hardware on PMC-Sierra MSP processors.
3
*
4
* Copyright 2005 PMC-Sierra, Inc.
5
*
6
* This program is free software; you can redistribute it and/or modify it
7
* under the terms of the GNU General Public License as published by the
8
* Free Software Foundation; either version 2 of the License, or (at your
9
* option) any later version.
10
*
11
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
12
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
13
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
14
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
15
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
17
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
18
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
19
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
20
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21
*
22
* You should have received a copy of the GNU General Public License along
23
* with this program; if not, write to the Free Software Foundation, Inc.,
24
* 675 Mass Ave, Cambridge, MA 02139, USA.
25
*/
26
27
#include <linux/serial.h>
28
#include <linux/serial_core.h>
29
#include <
linux/serial_reg.h
>
30
#include <linux/slab.h>
31
32
#include <asm/bootinfo.h>
33
#include <asm/io.h>
34
#include <asm/processor.h>
35
#include <asm/serial.h>
36
#include <
linux/serial_8250.h
>
37
38
#include <
msp_prom.h
>
39
#include <
msp_int.h
>
40
#include <
msp_regs.h
>
41
42
struct
msp_uart_data
{
43
int
last_lcr
;
44
};
45
46
static
void
msp_serial_out(
struct
uart_port
*
p
,
int
offset
,
int
value
)
47
{
48
struct
msp_uart_data
*
d
= p->
private_data
;
49
50
if
(offset ==
UART_LCR
)
51
d->
last_lcr
=
value
;
52
53
offset <<= p->
regshift
;
54
writeb
(value, p->
membase
+ offset);
55
}
56
57
static
unsigned
int
msp_serial_in(
struct
uart_port
*
p
,
int
offset
)
58
{
59
offset <<= p->
regshift
;
60
61
return
readb
(p->
membase
+ offset);
62
}
63
64
static
int
msp_serial_handle_irq(
struct
uart_port
*
p
)
65
{
66
struct
msp_uart_data
*
d
= p->
private_data
;
67
unsigned
int
iir
=
readb
(p->
membase
+ (
UART_IIR
<< p->
regshift
));
68
69
if
(
serial8250_handle_irq
(p, iir)) {
70
return
1;
71
}
else
if
((iir &
UART_IIR_BUSY
) == UART_IIR_BUSY) {
72
/*
73
* The DesignWare APB UART has an Busy Detect (0x07) interrupt
74
* meaning an LCR write attempt occurred while the UART was
75
* busy. The interrupt must be cleared by reading the UART
76
* status register (USR) and the LCR re-written.
77
*
78
* Note: MSP reserves 0x20 bytes of address space for the UART
79
* and the USR is mapped in a separate block at an offset of
80
* 0xc0 from the start of the UART.
81
*/
82
(
void
)
readb
(p->
membase
+ 0xc0);
83
writeb
(d->
last_lcr
, p->
membase
+ (
UART_LCR
<< p->
regshift
));
84
85
return
1;
86
}
87
88
return
0;
89
}
90
91
void
__init
msp_serial_setup
(
void
)
92
{
93
char
*
s
;
94
char
*endp;
95
struct
uart_port
up;
96
unsigned
int
uartclk
;
97
98
memset
(&up, 0,
sizeof
(up));
99
100
/* Check if clock was specified in environment */
101
s =
prom_getenv
(
"uartfreqhz"
);
102
if
(!(s && *s && (uartclk =
simple_strtoul
(s, &endp, 10)) && *endp == 0))
103
uartclk =
MSP_BASE_BAUD
;
104
ppfinit
(
"UART clock set to %d\n"
, uartclk);
105
106
/* Initialize first serial port */
107
up.
mapbase
=
MSP_UART0_BASE
;
108
up.
membase
=
ioremap_nocache
(up.
mapbase
,
MSP_UART_REG_LEN
);
109
up.
irq
=
MSP_INT_UART0
;
110
up.
uartclk
=
uartclk
;
111
up.
regshift
= 2;
112
up.
iotype
=
UPIO_MEM
;
113
up.
flags
=
ASYNC_BOOT_AUTOCONF
|
ASYNC_SKIP_TEST
;
114
up.
type
=
PORT_16550A
;
115
up.
line
= 0;
116
up.
serial_out
= msp_serial_out;
117
up.
serial_in
= msp_serial_in;
118
up.
handle_irq
= msp_serial_handle_irq;
119
up.
private_data
= kzalloc(
sizeof
(
struct
msp_uart_data
),
GFP_KERNEL
);
120
if
(!up.
private_data
) {
121
pr_err
(
"failed to allocate uart private data\n"
);
122
return
;
123
}
124
if
(
early_serial_setup
(&up)) {
125
kfree
(up.
private_data
);
126
pr_err
(
"Early serial init of port 0 failed\n"
);
127
}
128
129
/* Initialize the second serial port, if one exists */
130
switch
(
mips_machtype
) {
131
case
MACH_MSP4200_EVAL
:
132
case
MACH_MSP4200_GW
:
133
case
MACH_MSP4200_FPGA
:
134
case
MACH_MSP7120_EVAL
:
135
case
MACH_MSP7120_GW
:
136
case
MACH_MSP7120_FPGA
:
137
/* Enable UART1 on MSP4200 and MSP7120 */
138
*
GPIO_CFG2_REG
= 0x00002299;
139
break
;
140
141
default
:
142
return
;
/* No second serial port, good-bye. */
143
}
144
145
up.
mapbase
=
MSP_UART1_BASE
;
146
up.
membase
=
ioremap_nocache
(up.
mapbase
,
MSP_UART_REG_LEN
);
147
up.
irq
=
MSP_INT_UART1
;
148
up.
line
= 1;
149
up.
private_data
= (
void
*)
UART1_STATUS_REG
;
150
if
(
early_serial_setup
(&up)) {
151
kfree
(up.
private_data
);
152
pr_err
(
"Early serial init of port 1 failed\n"
);
153
}
154
}
Generated on Thu Jan 10 2013 13:12:05 for Linux Kernel by
1.8.2