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
powerpc
platforms
embedded6xx
ls_uart.c
Go to the documentation of this file.
1
/*
2
* AVR power-management chip interface for the Buffalo Linkstation /
3
* Kurobox Platform.
4
*
5
* Author: 2006 (c) G. Liakhovetski
6
*
[email protected]
7
*
8
* This file is licensed under the terms of the GNU General Public License
9
* version 2. This program is licensed "as is" without any warranty of
10
* any kind, whether express or implied.
11
*/
12
#include <
linux/workqueue.h
>
13
#include <linux/string.h>
14
#include <
linux/delay.h
>
15
#include <
linux/serial_reg.h
>
16
#include <
linux/serial_8250.h
>
17
#include <asm/io.h>
18
#include <asm/prom.h>
19
#include <asm/termbits.h>
20
21
#include "
mpc10x.h
"
22
23
static
void
__iomem
*avr_addr;
24
static
unsigned
long
avr_clock;
25
26
static
struct
work_struct
wd_work;
27
28
static
void
wd_stop(
struct
work_struct
*
unused
)
29
{
30
const
char
string
[] =
"AAAAFFFFJJJJ>>>>VVVV>>>>ZZZZVVVVKKKK"
;
31
int
i
= 0, rescue = 8;
32
int
len
=
strlen
(
string
);
33
34
while
(rescue--) {
35
int
j
;
36
char
lsr =
in_8
(avr_addr +
UART_LSR
);
37
38
if
(lsr & (
UART_LSR_THRE
|
UART_LSR_TEMT
)) {
39
for
(j = 0; j < 16 && i < len; j++, i++)
40
out_8
(avr_addr +
UART_TX
,
string
[i]);
41
if
(i == len) {
42
/* Read "OK" back: 4ms for the last "KKKK"
43
plus a couple bytes back */
44
msleep
(7);
45
printk
(
"linkstation: disarming the AVR watchdog: "
);
46
while
(
in_8
(avr_addr +
UART_LSR
) &
UART_LSR_DR
)
47
printk
(
"%c"
,
in_8
(avr_addr +
UART_RX
));
48
break
;
49
}
50
}
51
msleep
(17);
52
}
53
printk
(
"\n"
);
54
}
55
56
#define AVR_QUOT(clock) ((clock) + 8 * 9600) / (16 * 9600)
57
58
void
avr_uart_configure
(
void
)
59
{
60
unsigned
char
cval =
UART_LCR_WLEN8
;
61
unsigned
int
quot =
AVR_QUOT
(avr_clock);
62
63
if
(!avr_addr || !avr_clock)
64
return
;
65
66
out_8
(avr_addr +
UART_LCR
, cval);
/* initialise UART */
67
out_8
(avr_addr +
UART_MCR
, 0);
68
out_8
(avr_addr +
UART_IER
, 0);
69
70
cval |=
UART_LCR_STOP
|
UART_LCR_PARITY
|
UART_LCR_EPAR
;
71
72
out_8
(avr_addr +
UART_LCR
, cval);
/* Set character format */
73
74
out_8
(avr_addr +
UART_LCR
, cval |
UART_LCR_DLAB
);
/* set DLAB */
75
out_8
(avr_addr +
UART_DLL
, quot & 0xff);
/* LS of divisor */
76
out_8
(avr_addr +
UART_DLM
, quot >> 8);
/* MS of divisor */
77
out_8
(avr_addr +
UART_LCR
, cval);
/* reset DLAB */
78
out_8
(avr_addr +
UART_FCR
,
UART_FCR_ENABLE_FIFO
);
/* enable FIFO */
79
}
80
81
void
avr_uart_send
(
const
char
c
)
82
{
83
if
(!avr_addr || !avr_clock)
84
return
;
85
86
out_8
(avr_addr +
UART_TX
, c);
87
out_8
(avr_addr +
UART_TX
, c);
88
out_8
(avr_addr +
UART_TX
, c);
89
out_8
(avr_addr +
UART_TX
, c);
90
}
91
92
static
void
__init
ls_uart_init(
void
)
93
{
94
local_irq_disable
();
95
96
#ifndef CONFIG_SERIAL_8250
97
out_8
(avr_addr +
UART_FCR
,
UART_FCR_ENABLE_FIFO
);
/* enable FIFO */
98
out_8
(avr_addr +
UART_FCR
,
UART_FCR_ENABLE_FIFO
|
99
UART_FCR_CLEAR_RCVR
|
UART_FCR_CLEAR_XMIT
);
/* clear FIFOs */
100
out_8
(avr_addr +
UART_FCR
, 0);
101
out_8
(avr_addr +
UART_IER
, 0);
102
103
/* Clear up interrupts */
104
(
void
)
in_8
(avr_addr +
UART_LSR
);
105
(
void
)
in_8
(avr_addr +
UART_RX
);
106
(
void
)
in_8
(avr_addr +
UART_IIR
);
107
(
void
)
in_8
(avr_addr +
UART_MSR
);
108
#endif
109
avr_uart_configure
();
110
111
local_irq_enable
();
112
}
113
114
static
int
__init
ls_uarts_init(
void
)
115
{
116
struct
device_node
*avr;
117
phys_addr_t
phys_addr
;
118
int
len;
119
120
avr =
of_find_node_by_path
(
"/soc10x/serial@80004500"
);
121
if
(!avr)
122
return
-
EINVAL
;
123
124
avr_clock = *(
u32
*)
of_get_property
(avr,
"clock-frequency"
, &len);
125
phys_addr = ((
u32
*)
of_get_property
(avr,
"reg"
, &len))[0];
126
127
if
(!avr_clock || !phys_addr)
128
return
-
EINVAL
;
129
130
avr_addr =
ioremap
(phys_addr, 32);
131
if
(!avr_addr)
132
return
-
EFAULT
;
133
134
ls_uart_init();
135
136
INIT_WORK
(&wd_work, wd_stop);
137
schedule_work
(&wd_work);
138
139
return
0;
140
}
141
142
machine_late_initcall
(linkstation, ls_uarts_init);
Generated on Thu Jan 10 2013 13:15:30 for Linux Kernel by
1.8.2