diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/mips/lasat |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/mips/lasat')
-rw-r--r-- | arch/mips/lasat/Makefile | 14 | ||||
-rw-r--r-- | arch/mips/lasat/at93c.c | 148 | ||||
-rw-r--r-- | arch/mips/lasat/at93c.h | 18 | ||||
-rw-r--r-- | arch/mips/lasat/ds1603.c | 174 | ||||
-rw-r--r-- | arch/mips/lasat/ds1603.h | 33 | ||||
-rw-r--r-- | arch/mips/lasat/image/Makefile | 53 | ||||
-rw-r--r-- | arch/mips/lasat/image/head.S | 31 | ||||
-rw-r--r-- | arch/mips/lasat/image/romscript.normal | 22 | ||||
-rw-r--r-- | arch/mips/lasat/interrupt.c | 160 | ||||
-rw-r--r-- | arch/mips/lasat/lasatIRQ.S | 69 | ||||
-rw-r--r-- | arch/mips/lasat/lasat_board.c | 277 | ||||
-rw-r--r-- | arch/mips/lasat/lasat_models.h | 63 | ||||
-rw-r--r-- | arch/mips/lasat/picvue.c | 240 | ||||
-rw-r--r-- | arch/mips/lasat/picvue.h | 48 | ||||
-rw-r--r-- | arch/mips/lasat/picvue_proc.c | 186 | ||||
-rw-r--r-- | arch/mips/lasat/prom.c | 143 | ||||
-rw-r--r-- | arch/mips/lasat/prom.h | 6 | ||||
-rw-r--r-- | arch/mips/lasat/reset.c | 67 | ||||
-rw-r--r-- | arch/mips/lasat/setup.c | 192 | ||||
-rw-r--r-- | arch/mips/lasat/sysctl.c | 355 | ||||
-rw-r--r-- | arch/mips/lasat/sysctl.h | 24 |
21 files changed, 2323 insertions, 0 deletions
diff --git a/arch/mips/lasat/Makefile b/arch/mips/lasat/Makefile new file mode 100644 index 000000000000..0d5aec436725 --- /dev/null +++ b/arch/mips/lasat/Makefile | |||
@@ -0,0 +1,14 @@ | |||
1 | # | ||
2 | # Makefile for the LASAT specific kernel interface routines under Linux. | ||
3 | # | ||
4 | |||
5 | obj-y += reset.o setup.o prom.o lasat_board.o \ | ||
6 | at93c.o interrupt.o lasatIRQ.o | ||
7 | |||
8 | obj-$(CONFIG_LASAT_SYSCTL) += sysctl.o | ||
9 | obj-$(CONFIG_DS1603) += ds1603.o | ||
10 | obj-$(CONFIG_PICVUE) += picvue.o | ||
11 | obj-$(CONFIG_PICVUE_PROC) += picvue_proc.o | ||
12 | |||
13 | clean: | ||
14 | make -C image clean | ||
diff --git a/arch/mips/lasat/at93c.c b/arch/mips/lasat/at93c.c new file mode 100644 index 000000000000..f6add041ebec --- /dev/null +++ b/arch/mips/lasat/at93c.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * Atmel AT93C46 serial eeprom driver | ||
3 | * | ||
4 | * Brian Murphy <brian.murphy@eicon.com> | ||
5 | * | ||
6 | */ | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/delay.h> | ||
9 | #include <asm/lasat/lasat.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/init.h> | ||
12 | |||
13 | #include "at93c.h" | ||
14 | |||
15 | #define AT93C_ADDR_SHIFT 7 | ||
16 | #define AT93C_ADDR_MAX ((1 << AT93C_ADDR_SHIFT) - 1) | ||
17 | #define AT93C_RCMD (0x6 << AT93C_ADDR_SHIFT) | ||
18 | #define AT93C_WCMD (0x5 << AT93C_ADDR_SHIFT) | ||
19 | #define AT93C_WENCMD 0x260 | ||
20 | #define AT93C_WDSCMD 0x200 | ||
21 | |||
22 | struct at93c_defs *at93c; | ||
23 | |||
24 | static void at93c_reg_write(u32 val) | ||
25 | { | ||
26 | *at93c->reg = val; | ||
27 | } | ||
28 | |||
29 | static u32 at93c_reg_read(void) | ||
30 | { | ||
31 | u32 tmp = *at93c->reg; | ||
32 | return tmp; | ||
33 | } | ||
34 | |||
35 | static u32 at93c_datareg_read(void) | ||
36 | { | ||
37 | u32 tmp = *at93c->rdata_reg; | ||
38 | return tmp; | ||
39 | } | ||
40 | |||
41 | static void at93c_cycle_clk(u32 data) | ||
42 | { | ||
43 | at93c_reg_write(data | at93c->clk); | ||
44 | lasat_ndelay(250); | ||
45 | at93c_reg_write(data & ~at93c->clk); | ||
46 | lasat_ndelay(250); | ||
47 | } | ||
48 | |||
49 | static void at93c_write_databit(u8 bit) | ||
50 | { | ||
51 | u32 data = at93c_reg_read(); | ||
52 | if (bit) | ||
53 | data |= 1 << at93c->wdata_shift; | ||
54 | else | ||
55 | data &= ~(1 << at93c->wdata_shift); | ||
56 | |||
57 | at93c_reg_write(data); | ||
58 | lasat_ndelay(100); | ||
59 | at93c_cycle_clk(data); | ||
60 | } | ||
61 | |||
62 | static unsigned int at93c_read_databit(void) | ||
63 | { | ||
64 | u32 data; | ||
65 | |||
66 | at93c_cycle_clk(at93c_reg_read()); | ||
67 | data = (at93c_datareg_read() >> at93c->rdata_shift) & 1; | ||
68 | return data; | ||
69 | } | ||
70 | |||
71 | static u8 at93c_read_byte(void) | ||
72 | { | ||
73 | int i; | ||
74 | u8 data = 0; | ||
75 | |||
76 | for (i = 0; i<=7; i++) { | ||
77 | data <<= 1; | ||
78 | data |= at93c_read_databit(); | ||
79 | } | ||
80 | return data; | ||
81 | } | ||
82 | |||
83 | static void at93c_write_bits(u32 data, int size) | ||
84 | { | ||
85 | int i; | ||
86 | int shift = size - 1; | ||
87 | u32 mask = (1 << shift); | ||
88 | |||
89 | for (i = 0; i < size; i++) { | ||
90 | at93c_write_databit((data & mask) >> shift); | ||
91 | data <<= 1; | ||
92 | } | ||
93 | } | ||
94 | |||
95 | static void at93c_init_op(void) | ||
96 | { | ||
97 | at93c_reg_write((at93c_reg_read() | at93c->cs) & ~at93c->clk & ~(1 << at93c->rdata_shift)); | ||
98 | lasat_ndelay(50); | ||
99 | } | ||
100 | |||
101 | static void at93c_end_op(void) | ||
102 | { | ||
103 | at93c_reg_write(at93c_reg_read() & ~at93c->cs); | ||
104 | lasat_ndelay(250); | ||
105 | } | ||
106 | |||
107 | static void at93c_wait(void) | ||
108 | { | ||
109 | at93c_init_op(); | ||
110 | while (!at93c_read_databit()) | ||
111 | ; | ||
112 | at93c_end_op(); | ||
113 | }; | ||
114 | |||
115 | static void at93c_disable_wp(void) | ||
116 | { | ||
117 | at93c_init_op(); | ||
118 | at93c_write_bits(AT93C_WENCMD, 10); | ||
119 | at93c_end_op(); | ||
120 | } | ||
121 | |||
122 | static void at93c_enable_wp(void) | ||
123 | { | ||
124 | at93c_init_op(); | ||
125 | at93c_write_bits(AT93C_WDSCMD, 10); | ||
126 | at93c_end_op(); | ||
127 | } | ||
128 | |||
129 | u8 at93c_read(u8 addr) | ||
130 | { | ||
131 | u8 byte; | ||
132 | at93c_init_op(); | ||
133 | at93c_write_bits((addr & AT93C_ADDR_MAX)|AT93C_RCMD, 10); | ||
134 | byte = at93c_read_byte(); | ||
135 | at93c_end_op(); | ||
136 | return byte; | ||
137 | } | ||
138 | |||
139 | void at93c_write(u8 addr, u8 data) | ||
140 | { | ||
141 | at93c_disable_wp(); | ||
142 | at93c_init_op(); | ||
143 | at93c_write_bits((addr & AT93C_ADDR_MAX)|AT93C_WCMD, 10); | ||
144 | at93c_write_bits(data, 8); | ||
145 | at93c_end_op(); | ||
146 | at93c_wait(); | ||
147 | at93c_enable_wp(); | ||
148 | } | ||
diff --git a/arch/mips/lasat/at93c.h b/arch/mips/lasat/at93c.h new file mode 100644 index 000000000000..a912ac2171b0 --- /dev/null +++ b/arch/mips/lasat/at93c.h | |||
@@ -0,0 +1,18 @@ | |||
1 | /* | ||
2 | * Atmel AT93C46 serial eeprom driver | ||
3 | * | ||
4 | * Brian Murphy <brian.murphy@eicon.com> | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | extern struct at93c_defs { | ||
9 | volatile u32 *reg; | ||
10 | volatile u32 *rdata_reg; | ||
11 | int rdata_shift; | ||
12 | int wdata_shift; | ||
13 | u32 cs; | ||
14 | u32 clk; | ||
15 | } *at93c; | ||
16 | |||
17 | u8 at93c_read(u8 addr); | ||
18 | void at93c_write(u8 addr, u8 data); | ||
diff --git a/arch/mips/lasat/ds1603.c b/arch/mips/lasat/ds1603.c new file mode 100644 index 000000000000..7bbf6cf923c9 --- /dev/null +++ b/arch/mips/lasat/ds1603.c | |||
@@ -0,0 +1,174 @@ | |||
1 | /* | ||
2 | * Dallas Semiconductors 1603 RTC driver | ||
3 | * | ||
4 | * Brian Murphy <brian@murphy.dk> | ||
5 | * | ||
6 | */ | ||
7 | #include <linux/kernel.h> | ||
8 | #include <asm/lasat/lasat.h> | ||
9 | #include <linux/delay.h> | ||
10 | #include <asm/lasat/ds1603.h> | ||
11 | |||
12 | #include "ds1603.h" | ||
13 | |||
14 | #define READ_TIME_CMD 0x81 | ||
15 | #define SET_TIME_CMD 0x80 | ||
16 | #define TRIMMER_SET_CMD 0xC0 | ||
17 | #define TRIMMER_VALUE_MASK 0x38 | ||
18 | #define TRIMMER_SHIFT 3 | ||
19 | |||
20 | struct ds_defs *ds1603 = NULL; | ||
21 | |||
22 | /* HW specific register functions */ | ||
23 | static void rtc_reg_write(unsigned long val) | ||
24 | { | ||
25 | *ds1603->reg = val; | ||
26 | } | ||
27 | |||
28 | static unsigned long rtc_reg_read(void) | ||
29 | { | ||
30 | unsigned long tmp = *ds1603->reg; | ||
31 | return tmp; | ||
32 | } | ||
33 | |||
34 | static unsigned long rtc_datareg_read(void) | ||
35 | { | ||
36 | unsigned long tmp = *ds1603->data_reg; | ||
37 | return tmp; | ||
38 | } | ||
39 | |||
40 | static void rtc_nrst_high(void) | ||
41 | { | ||
42 | rtc_reg_write(rtc_reg_read() | ds1603->rst); | ||
43 | } | ||
44 | |||
45 | static void rtc_nrst_low(void) | ||
46 | { | ||
47 | rtc_reg_write(rtc_reg_read() & ~ds1603->rst); | ||
48 | } | ||
49 | |||
50 | static void rtc_cycle_clock(unsigned long data) | ||
51 | { | ||
52 | data |= ds1603->clk; | ||
53 | rtc_reg_write(data); | ||
54 | lasat_ndelay(250); | ||
55 | if (ds1603->data_reversed) | ||
56 | data &= ~ds1603->data; | ||
57 | else | ||
58 | data |= ds1603->data; | ||
59 | data &= ~ds1603->clk; | ||
60 | rtc_reg_write(data); | ||
61 | lasat_ndelay(250 + ds1603->huge_delay); | ||
62 | } | ||
63 | |||
64 | static void rtc_write_databit(unsigned int bit) | ||
65 | { | ||
66 | unsigned long data = rtc_reg_read(); | ||
67 | if (ds1603->data_reversed) | ||
68 | bit = !bit; | ||
69 | if (bit) | ||
70 | data |= ds1603->data; | ||
71 | else | ||
72 | data &= ~ds1603->data; | ||
73 | |||
74 | rtc_reg_write(data); | ||
75 | lasat_ndelay(50 + ds1603->huge_delay); | ||
76 | rtc_cycle_clock(data); | ||
77 | } | ||
78 | |||
79 | static unsigned int rtc_read_databit(void) | ||
80 | { | ||
81 | unsigned int data; | ||
82 | |||
83 | data = (rtc_datareg_read() & (1 << ds1603->data_read_shift)) | ||
84 | >> ds1603->data_read_shift; | ||
85 | rtc_cycle_clock(rtc_reg_read()); | ||
86 | return data; | ||
87 | } | ||
88 | |||
89 | static void rtc_write_byte(unsigned int byte) | ||
90 | { | ||
91 | int i; | ||
92 | |||
93 | for (i = 0; i<=7; i++) { | ||
94 | rtc_write_databit(byte & 1L); | ||
95 | byte >>= 1; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | static void rtc_write_word(unsigned long word) | ||
100 | { | ||
101 | int i; | ||
102 | |||
103 | for (i = 0; i<=31; i++) { | ||
104 | rtc_write_databit(word & 1L); | ||
105 | word >>= 1; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | static unsigned long rtc_read_word(void) | ||
110 | { | ||
111 | int i; | ||
112 | unsigned long word = 0; | ||
113 | unsigned long shift = 0; | ||
114 | |||
115 | for (i = 0; i<=31; i++) { | ||
116 | word |= rtc_read_databit() << shift; | ||
117 | shift++; | ||
118 | } | ||
119 | return word; | ||
120 | } | ||
121 | |||
122 | static void rtc_init_op(void) | ||
123 | { | ||
124 | rtc_nrst_high(); | ||
125 | |||
126 | rtc_reg_write(rtc_reg_read() & ~ds1603->clk); | ||
127 | |||
128 | lasat_ndelay(50); | ||
129 | } | ||
130 | |||
131 | static void rtc_end_op(void) | ||
132 | { | ||
133 | rtc_nrst_low(); | ||
134 | lasat_ndelay(1000); | ||
135 | } | ||
136 | |||
137 | /* interface */ | ||
138 | unsigned long ds1603_read(void) | ||
139 | { | ||
140 | unsigned long word; | ||
141 | rtc_init_op(); | ||
142 | rtc_write_byte(READ_TIME_CMD); | ||
143 | word = rtc_read_word(); | ||
144 | rtc_end_op(); | ||
145 | return word; | ||
146 | } | ||
147 | |||
148 | int ds1603_set(unsigned long time) | ||
149 | { | ||
150 | rtc_init_op(); | ||
151 | rtc_write_byte(SET_TIME_CMD); | ||
152 | rtc_write_word(time); | ||
153 | rtc_end_op(); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | void ds1603_set_trimmer(unsigned int trimval) | ||
159 | { | ||
160 | rtc_init_op(); | ||
161 | rtc_write_byte(((trimval << TRIMMER_SHIFT) & TRIMMER_VALUE_MASK) | ||
162 | | (TRIMMER_SET_CMD)); | ||
163 | rtc_end_op(); | ||
164 | } | ||
165 | |||
166 | void ds1603_disable(void) | ||
167 | { | ||
168 | ds1603_set_trimmer(TRIMMER_DISABLE_RTC); | ||
169 | } | ||
170 | |||
171 | void ds1603_enable(void) | ||
172 | { | ||
173 | ds1603_set_trimmer(TRIMMER_DEFAULT); | ||
174 | } | ||
diff --git a/arch/mips/lasat/ds1603.h b/arch/mips/lasat/ds1603.h new file mode 100644 index 000000000000..55f3b0423c20 --- /dev/null +++ b/arch/mips/lasat/ds1603.h | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | * Dallas Semiconductors 1603 RTC driver | ||
3 | * | ||
4 | * Brian Murphy <brian@murphy.dk> | ||
5 | * | ||
6 | */ | ||
7 | #ifndef __DS1603_H | ||
8 | #define __DS1603_H | ||
9 | |||
10 | struct ds_defs { | ||
11 | volatile u32 *reg; | ||
12 | volatile u32 *data_reg; | ||
13 | u32 rst; | ||
14 | u32 clk; | ||
15 | u32 data; | ||
16 | u32 data_read_shift; | ||
17 | char data_reversed; | ||
18 | u32 huge_delay; | ||
19 | }; | ||
20 | |||
21 | extern struct ds_defs *ds1603; | ||
22 | |||
23 | unsigned long ds1603_read(void); | ||
24 | int ds1603_set(unsigned long); | ||
25 | void ds1603_set_trimmer(unsigned int); | ||
26 | void ds1603_enable(void); | ||
27 | void ds1603_disable(void); | ||
28 | void ds1603_init(struct ds_defs *); | ||
29 | |||
30 | #define TRIMMER_DEFAULT 3 | ||
31 | #define TRIMMER_DISABLE_RTC 0 | ||
32 | |||
33 | #endif | ||
diff --git a/arch/mips/lasat/image/Makefile b/arch/mips/lasat/image/Makefile new file mode 100644 index 000000000000..18b6430f11be --- /dev/null +++ b/arch/mips/lasat/image/Makefile | |||
@@ -0,0 +1,53 @@ | |||
1 | # | ||
2 | # MAKEFILE FOR THE MIPS LINUX BOOTLOADER AND ROM DEBUGGER | ||
3 | # | ||
4 | # i-data Networks | ||
5 | # | ||
6 | # Author: Thomas Horsten <thh@i-data.com> | ||
7 | # | ||
8 | |||
9 | ifndef Version | ||
10 | Version = "$(USER)-test" | ||
11 | endif | ||
12 | |||
13 | MKLASATIMG = mklasatimg | ||
14 | MKLASATIMG_ARCH = mq2,mqpro,sp100,sp200 | ||
15 | KERNEL_IMAGE = $(TOPDIR)/vmlinux | ||
16 | KERNEL_START = $(shell $(NM) $(KERNEL_IMAGE) | grep " _text" | cut -f1 -d\ ) | ||
17 | KERNEL_ENTRY = $(shell $(NM) $(KERNEL_IMAGE) | grep kernel_entry | cut -f1 -d\ ) | ||
18 | |||
19 | LDSCRIPT= -L$(obj) -Tromscript.normal | ||
20 | |||
21 | HEAD_DEFINES := -D_kernel_start=0x$(KERNEL_START) \ | ||
22 | -D_kernel_entry=0x$(KERNEL_ENTRY) \ | ||
23 | -D VERSION="\"$(Version)\"" \ | ||
24 | -D TIMESTAMP=$(shell date +%s) | ||
25 | |||
26 | $(obj)/head.o: $(obj)/head.S $(KERNEL_IMAGE) | ||
27 | $(CC) -fno-pic $(HEAD_DEFINES) -I$(TOPDIR)/include -c -o $@ $< | ||
28 | |||
29 | OBJECTS = head.o kImage.o | ||
30 | |||
31 | rom.sw: $(obj)/rom.sw | ||
32 | |||
33 | $(obj)/rom.sw: $(obj)/rom.bin | ||
34 | $(MKLASATIMG) -o $@ -k $^ -m $(MKLASATIMG_ARCH) | ||
35 | |||
36 | $(obj)/rom.bin: $(obj)/rom | ||
37 | $(OBJCOPY) -O binary -S $^ $@ | ||
38 | |||
39 | # Rule to make the bootloader | ||
40 | $(obj)/rom: $(addprefix $(obj)/,$(OBJECTS)) | ||
41 | $(LD) $(LDFLAGS) $(LDSCRIPT) -o $@ $^ | ||
42 | |||
43 | $(obj)/%.o: $(obj)/%.gz | ||
44 | $(LD) -r -o $@ -b binary $< | ||
45 | |||
46 | $(obj)/%.gz: $(obj)/%.bin | ||
47 | gzip -cf -9 $< > $@ | ||
48 | |||
49 | $(obj)/kImage.bin: $(KERNEL_IMAGE) | ||
50 | $(OBJCOPY) -O binary -S $^ $@ | ||
51 | |||
52 | clean: | ||
53 | rm -f rom rom.bin rom.sw kImage.bin kImage.o | ||
diff --git a/arch/mips/lasat/image/head.S b/arch/mips/lasat/image/head.S new file mode 100644 index 000000000000..426bd7de17bb --- /dev/null +++ b/arch/mips/lasat/image/head.S | |||
@@ -0,0 +1,31 @@ | |||
1 | #include <asm/lasat/head.h> | ||
2 | |||
3 | .text | ||
4 | .section .text.start, "ax" | ||
5 | .set noreorder | ||
6 | .set mips3 | ||
7 | |||
8 | /* Magic words identifying a software image */ | ||
9 | .word LASAT_K_MAGIC0_VAL | ||
10 | .word LASAT_K_MAGIC1_VAL | ||
11 | |||
12 | /* Image header version */ | ||
13 | .word 0x00000002 | ||
14 | |||
15 | /* image start and size */ | ||
16 | .word _image_start | ||
17 | .word _image_size | ||
18 | |||
19 | /* start of kernel and entrypoint in uncompressed image */ | ||
20 | .word _kernel_start | ||
21 | .word _kernel_entry | ||
22 | |||
23 | /* Here we have room for future flags */ | ||
24 | |||
25 | .org 0x40 | ||
26 | reldate: | ||
27 | .word TIMESTAMP | ||
28 | |||
29 | .org 0x50 | ||
30 | release: | ||
31 | .string VERSION | ||
diff --git a/arch/mips/lasat/image/romscript.normal b/arch/mips/lasat/image/romscript.normal new file mode 100644 index 000000000000..ca22336f6c36 --- /dev/null +++ b/arch/mips/lasat/image/romscript.normal | |||
@@ -0,0 +1,22 @@ | |||
1 | OUTPUT_ARCH(mips) | ||
2 | |||
3 | SECTIONS | ||
4 | { | ||
5 | .text : | ||
6 | { | ||
7 | *(.text.start) | ||
8 | } | ||
9 | |||
10 | /* Data in ROM */ | ||
11 | |||
12 | .data ALIGN(0x10) : | ||
13 | { | ||
14 | *(.data) | ||
15 | } | ||
16 | _image_start = ADDR(.data); | ||
17 | _image_size = SIZEOF(.data); | ||
18 | |||
19 | .other : { | ||
20 | *(.*) | ||
21 | } | ||
22 | } | ||
diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c new file mode 100644 index 000000000000..1148a2d20aa7 --- /dev/null +++ b/arch/mips/lasat/interrupt.c | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * Carsten Langgaard, carstenl@mips.com | ||
3 | * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can distribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License (Version 2) as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
12 | * for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
17 | * | ||
18 | * Routines for generic manipulation of the interrupts found on the | ||
19 | * Lasat boards. | ||
20 | */ | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/kernel_stat.h> | ||
26 | |||
27 | #include <asm/bootinfo.h> | ||
28 | #include <asm/irq.h> | ||
29 | #include <asm/lasat/lasatint.h> | ||
30 | #include <asm/gdb-stub.h> | ||
31 | |||
32 | static volatile int *lasat_int_status = NULL; | ||
33 | static volatile int *lasat_int_mask = NULL; | ||
34 | static volatile int lasat_int_mask_shift; | ||
35 | |||
36 | extern asmlinkage void lasatIRQ(void); | ||
37 | |||
38 | void disable_lasat_irq(unsigned int irq_nr) | ||
39 | { | ||
40 | unsigned long flags; | ||
41 | |||
42 | local_irq_save(flags); | ||
43 | *lasat_int_mask &= ~(1 << irq_nr) << lasat_int_mask_shift; | ||
44 | local_irq_restore(flags); | ||
45 | } | ||
46 | |||
47 | void enable_lasat_irq(unsigned int irq_nr) | ||
48 | { | ||
49 | unsigned long flags; | ||
50 | |||
51 | local_irq_save(flags); | ||
52 | *lasat_int_mask |= (1 << irq_nr) << lasat_int_mask_shift; | ||
53 | local_irq_restore(flags); | ||
54 | } | ||
55 | |||
56 | static unsigned int startup_lasat_irq(unsigned int irq) | ||
57 | { | ||
58 | enable_lasat_irq(irq); | ||
59 | |||
60 | return 0; /* never anything pending */ | ||
61 | } | ||
62 | |||
63 | #define shutdown_lasat_irq disable_lasat_irq | ||
64 | |||
65 | #define mask_and_ack_lasat_irq disable_lasat_irq | ||
66 | |||
67 | static void end_lasat_irq(unsigned int irq) | ||
68 | { | ||
69 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) | ||
70 | enable_lasat_irq(irq); | ||
71 | } | ||
72 | |||
73 | static struct hw_interrupt_type lasat_irq_type = { | ||
74 | "Lasat", | ||
75 | startup_lasat_irq, | ||
76 | shutdown_lasat_irq, | ||
77 | enable_lasat_irq, | ||
78 | disable_lasat_irq, | ||
79 | mask_and_ack_lasat_irq, | ||
80 | end_lasat_irq, | ||
81 | NULL | ||
82 | }; | ||
83 | |||
84 | static inline int ls1bit32(unsigned int x) | ||
85 | { | ||
86 | int b = 31, s; | ||
87 | |||
88 | s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s; | ||
89 | s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s; | ||
90 | s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s; | ||
91 | s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s; | ||
92 | s = 1; if (x << 1 == 0) s = 0; b -= s; | ||
93 | |||
94 | return b; | ||
95 | } | ||
96 | |||
97 | static unsigned long (* get_int_status)(void); | ||
98 | |||
99 | static unsigned long get_int_status_100(void) | ||
100 | { | ||
101 | return *lasat_int_status & *lasat_int_mask; | ||
102 | } | ||
103 | |||
104 | static unsigned long get_int_status_200(void) | ||
105 | { | ||
106 | unsigned long int_status; | ||
107 | |||
108 | int_status = *lasat_int_status; | ||
109 | int_status &= (int_status >> LASATINT_MASK_SHIFT_200) & 0xffff; | ||
110 | return int_status; | ||
111 | } | ||
112 | |||
113 | void lasat_hw0_irqdispatch(struct pt_regs *regs) | ||
114 | { | ||
115 | unsigned long int_status; | ||
116 | int irq; | ||
117 | |||
118 | int_status = get_int_status(); | ||
119 | |||
120 | /* if int_status == 0, then the interrupt has already been cleared */ | ||
121 | if (int_status) { | ||
122 | irq = ls1bit32(int_status); | ||
123 | |||
124 | do_IRQ(irq, regs); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | void __init arch_init_irq(void) | ||
129 | { | ||
130 | int i; | ||
131 | |||
132 | switch (mips_machtype) { | ||
133 | case MACH_LASAT_100: | ||
134 | lasat_int_status = (void *)LASAT_INT_STATUS_REG_100; | ||
135 | lasat_int_mask = (void *)LASAT_INT_MASK_REG_100; | ||
136 | lasat_int_mask_shift = LASATINT_MASK_SHIFT_100; | ||
137 | get_int_status = get_int_status_100; | ||
138 | *lasat_int_mask = 0; | ||
139 | break; | ||
140 | case MACH_LASAT_200: | ||
141 | lasat_int_status = (void *)LASAT_INT_STATUS_REG_200; | ||
142 | lasat_int_mask = (void *)LASAT_INT_MASK_REG_200; | ||
143 | lasat_int_mask_shift = LASATINT_MASK_SHIFT_200; | ||
144 | get_int_status = get_int_status_200; | ||
145 | *lasat_int_mask &= 0xffff; | ||
146 | break; | ||
147 | default: | ||
148 | panic("arch_init_irq: mips_machtype incorrect"); | ||
149 | } | ||
150 | |||
151 | /* Now safe to set the exception vector. */ | ||
152 | set_except_vector(0, lasatIRQ); | ||
153 | |||
154 | for (i = 0; i <= LASATINT_END; i++) { | ||
155 | irq_desc[i].status = IRQ_DISABLED; | ||
156 | irq_desc[i].action = 0; | ||
157 | irq_desc[i].depth = 1; | ||
158 | irq_desc[i].handler = &lasat_irq_type; | ||
159 | } | ||
160 | } | ||
diff --git a/arch/mips/lasat/lasatIRQ.S b/arch/mips/lasat/lasatIRQ.S new file mode 100644 index 000000000000..2a2b0d056561 --- /dev/null +++ b/arch/mips/lasat/lasatIRQ.S | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | * Carsten Langgaard, carstenl@mips.com | ||
3 | * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can distribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License (Version 2) as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
12 | * for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
17 | * | ||
18 | * Interrupt exception dispatch code. | ||
19 | */ | ||
20 | #include <asm/asm.h> | ||
21 | #include <asm/mipsregs.h> | ||
22 | #include <asm/regdef.h> | ||
23 | #include <asm/stackframe.h> | ||
24 | |||
25 | .text | ||
26 | .set noreorder | ||
27 | .align 5 | ||
28 | NESTED(lasatIRQ, PT_SIZE, sp) | ||
29 | .set noat | ||
30 | SAVE_ALL | ||
31 | CLI | ||
32 | .set at | ||
33 | .set noreorder | ||
34 | |||
35 | mfc0 s0, CP0_CAUSE # get irq mask | ||
36 | |||
37 | /* First we check for r4k counter/timer IRQ. */ | ||
38 | andi a0, s0, CAUSEF_IP7 | ||
39 | beq a0, zero, 1f | ||
40 | andi a0, s0, CAUSEF_IP2 # delay slot, check hw0 interrupt | ||
41 | |||
42 | /* Wheee, a timer interrupt. */ | ||
43 | li a0, 7 | ||
44 | jal ll_timer_interrupt | ||
45 | move a1, sp | ||
46 | |||
47 | j ret_from_irq | ||
48 | nop | ||
49 | |||
50 | 1: | ||
51 | /* Wheee, combined hardware level zero interrupt. */ | ||
52 | jal lasat_hw0_irqdispatch | ||
53 | move a0, sp # delay slot | ||
54 | |||
55 | j ret_from_irq | ||
56 | nop # delay slot | ||
57 | |||
58 | 1: | ||
59 | /* | ||
60 | * Here by mistake? This is possible, what can happen is that by the | ||
61 | * time we take the exception the IRQ pin goes low, so just leave if | ||
62 | * this is the case. | ||
63 | */ | ||
64 | move a1,s0 | ||
65 | mfc0 a1, CP0_EPC | ||
66 | |||
67 | j ret_from_irq | ||
68 | nop | ||
69 | END(lasatIRQ) | ||
diff --git a/arch/mips/lasat/lasat_board.c b/arch/mips/lasat/lasat_board.c new file mode 100644 index 000000000000..8c784bcf1111 --- /dev/null +++ b/arch/mips/lasat/lasat_board.c | |||
@@ -0,0 +1,277 @@ | |||
1 | /* | ||
2 | * Thomas Horsten <thh@lasat.com> | ||
3 | * Copyright (C) 2000 LASAT Networks A/S. | ||
4 | * | ||
5 | * This program is free software; you can distribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License (Version 2) as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
12 | * for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
17 | * | ||
18 | * Routines specific to the LASAT boards | ||
19 | */ | ||
20 | #include <linux/config.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/crc32.h> | ||
23 | #include <asm/lasat/lasat.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/string.h> | ||
26 | #include <linux/ctype.h> | ||
27 | #include <asm/bootinfo.h> | ||
28 | #include <asm/addrspace.h> | ||
29 | #include "at93c.h" | ||
30 | /* New model description table */ | ||
31 | #include "lasat_models.h" | ||
32 | |||
33 | #define EEPROM_CRC(data, len) (~0 ^ crc32(~0, data, len)) | ||
34 | |||
35 | struct lasat_info lasat_board_info; | ||
36 | |||
37 | void update_bcastaddr(void); | ||
38 | |||
39 | int EEPROMRead(unsigned int pos, unsigned char *data, int len) | ||
40 | { | ||
41 | int i; | ||
42 | |||
43 | for (i=0; i<len; i++) | ||
44 | *data++ = at93c_read(pos++); | ||
45 | |||
46 | return 0; | ||
47 | } | ||
48 | int EEPROMWrite(unsigned int pos, unsigned char *data, int len) | ||
49 | { | ||
50 | int i; | ||
51 | |||
52 | for (i=0; i<len; i++) | ||
53 | at93c_write(pos++, *data++); | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static void init_flash_sizes(void) | ||
59 | { | ||
60 | int i; | ||
61 | unsigned long *lb = lasat_board_info.li_flashpart_base; | ||
62 | unsigned long *ls = lasat_board_info.li_flashpart_size; | ||
63 | |||
64 | ls[LASAT_MTD_BOOTLOADER] = 0x40000; | ||
65 | ls[LASAT_MTD_SERVICE] = 0xC0000; | ||
66 | ls[LASAT_MTD_NORMAL] = 0x100000; | ||
67 | |||
68 | if (mips_machtype == MACH_LASAT_100) { | ||
69 | lasat_board_info.li_flash_base = 0x1e000000; | ||
70 | |||
71 | lb[LASAT_MTD_BOOTLOADER] = 0x1e400000; | ||
72 | |||
73 | if (lasat_board_info.li_flash_size > 0x200000) { | ||
74 | ls[LASAT_MTD_CONFIG] = 0x100000; | ||
75 | ls[LASAT_MTD_FS] = 0x500000; | ||
76 | } | ||
77 | } else { | ||
78 | lasat_board_info.li_flash_base = 0x10000000; | ||
79 | |||
80 | if (lasat_board_info.li_flash_size < 0x1000000) { | ||
81 | lb[LASAT_MTD_BOOTLOADER] = 0x10000000; | ||
82 | ls[LASAT_MTD_CONFIG] = 0x100000; | ||
83 | if (lasat_board_info.li_flash_size >= 0x400000) { | ||
84 | ls[LASAT_MTD_FS] = lasat_board_info.li_flash_size - 0x300000; | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | |||
89 | for (i = 1; i < LASAT_MTD_LAST; i++) | ||
90 | lb[i] = lb[i-1] + ls[i-1]; | ||
91 | } | ||
92 | |||
93 | int lasat_init_board_info(void) | ||
94 | { | ||
95 | int c; | ||
96 | unsigned long crc; | ||
97 | unsigned long cfg0, cfg1; | ||
98 | const product_info_t *ppi; | ||
99 | int i_n_base_models = N_BASE_MODELS; | ||
100 | const char * const * i_txt_base_models = txt_base_models; | ||
101 | int i_n_prids = N_PRIDS; | ||
102 | |||
103 | memset(&lasat_board_info, 0, sizeof(lasat_board_info)); | ||
104 | |||
105 | /* First read the EEPROM info */ | ||
106 | EEPROMRead(0, (unsigned char *)&lasat_board_info.li_eeprom_info, | ||
107 | sizeof(struct lasat_eeprom_struct)); | ||
108 | |||
109 | /* Check the CRC */ | ||
110 | crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info), | ||
111 | sizeof(struct lasat_eeprom_struct) - 4); | ||
112 | |||
113 | if (crc != lasat_board_info.li_eeprom_info.crc32) { | ||
114 | prom_printf("WARNING...\nWARNING...\nEEPROM CRC does not match calculated, attempting to soldier on...\n"); | ||
115 | } | ||
116 | |||
117 | if (lasat_board_info.li_eeprom_info.version != LASAT_EEPROM_VERSION) | ||
118 | { | ||
119 | prom_printf("WARNING...\nWARNING...\nEEPROM version %d, wanted version %d, attempting to soldier on...\n", | ||
120 | (unsigned int)lasat_board_info.li_eeprom_info.version, | ||
121 | LASAT_EEPROM_VERSION); | ||
122 | } | ||
123 | |||
124 | cfg0 = lasat_board_info.li_eeprom_info.cfg[0]; | ||
125 | cfg1 = lasat_board_info.li_eeprom_info.cfg[1]; | ||
126 | |||
127 | if ( LASAT_W0_DSCTYPE(cfg0) != 1) { | ||
128 | prom_printf("WARNING...\nWARNING...\nInvalid configuration read from EEPROM, attempting to soldier on..."); | ||
129 | } | ||
130 | /* We have a valid configuration */ | ||
131 | |||
132 | switch (LASAT_W0_SDRAMBANKSZ(cfg0)) { | ||
133 | case 0: | ||
134 | lasat_board_info.li_memsize = 0x0800000; | ||
135 | break; | ||
136 | case 1: | ||
137 | lasat_board_info.li_memsize = 0x1000000; | ||
138 | break; | ||
139 | case 2: | ||
140 | lasat_board_info.li_memsize = 0x2000000; | ||
141 | break; | ||
142 | case 3: | ||
143 | lasat_board_info.li_memsize = 0x4000000; | ||
144 | break; | ||
145 | case 4: | ||
146 | lasat_board_info.li_memsize = 0x8000000; | ||
147 | break; | ||
148 | default: | ||
149 | lasat_board_info.li_memsize = 0; | ||
150 | } | ||
151 | |||
152 | switch (LASAT_W0_SDRAMBANKS(cfg0)) { | ||
153 | case 0: | ||
154 | break; | ||
155 | case 1: | ||
156 | lasat_board_info.li_memsize *= 2; | ||
157 | break; | ||
158 | default: | ||
159 | break; | ||
160 | } | ||
161 | |||
162 | switch (LASAT_W0_BUSSPEED(cfg0)) { | ||
163 | case 0x0: | ||
164 | lasat_board_info.li_bus_hz = 60000000; | ||
165 | break; | ||
166 | case 0x1: | ||
167 | lasat_board_info.li_bus_hz = 66000000; | ||
168 | break; | ||
169 | case 0x2: | ||
170 | lasat_board_info.li_bus_hz = 66666667; | ||
171 | break; | ||
172 | case 0x3: | ||
173 | lasat_board_info.li_bus_hz = 80000000; | ||
174 | break; | ||
175 | case 0x4: | ||
176 | lasat_board_info.li_bus_hz = 83333333; | ||
177 | break; | ||
178 | case 0x5: | ||
179 | lasat_board_info.li_bus_hz = 100000000; | ||
180 | break; | ||
181 | } | ||
182 | |||
183 | switch (LASAT_W0_CPUCLK(cfg0)) { | ||
184 | case 0x0: | ||
185 | lasat_board_info.li_cpu_hz = | ||
186 | lasat_board_info.li_bus_hz; | ||
187 | break; | ||
188 | case 0x1: | ||
189 | lasat_board_info.li_cpu_hz = | ||
190 | lasat_board_info.li_bus_hz + | ||
191 | (lasat_board_info.li_bus_hz >> 1); | ||
192 | break; | ||
193 | case 0x2: | ||
194 | lasat_board_info.li_cpu_hz = | ||
195 | lasat_board_info.li_bus_hz + | ||
196 | lasat_board_info.li_bus_hz; | ||
197 | break; | ||
198 | case 0x3: | ||
199 | lasat_board_info.li_cpu_hz = | ||
200 | lasat_board_info.li_bus_hz + | ||
201 | lasat_board_info.li_bus_hz + | ||
202 | (lasat_board_info.li_bus_hz >> 1); | ||
203 | break; | ||
204 | case 0x4: | ||
205 | lasat_board_info.li_cpu_hz = | ||
206 | lasat_board_info.li_bus_hz + | ||
207 | lasat_board_info.li_bus_hz + | ||
208 | lasat_board_info.li_bus_hz; | ||
209 | break; | ||
210 | } | ||
211 | |||
212 | /* Flash size */ | ||
213 | switch (LASAT_W1_FLASHSIZE(cfg1)) { | ||
214 | case 0: | ||
215 | lasat_board_info.li_flash_size = 0x200000; | ||
216 | break; | ||
217 | case 1: | ||
218 | lasat_board_info.li_flash_size = 0x400000; | ||
219 | break; | ||
220 | case 2: | ||
221 | lasat_board_info.li_flash_size = 0x800000; | ||
222 | break; | ||
223 | case 3: | ||
224 | lasat_board_info.li_flash_size = 0x1000000; | ||
225 | break; | ||
226 | case 4: | ||
227 | lasat_board_info.li_flash_size = 0x2000000; | ||
228 | break; | ||
229 | } | ||
230 | |||
231 | init_flash_sizes(); | ||
232 | |||
233 | lasat_board_info.li_bmid = LASAT_W0_BMID(cfg0); | ||
234 | lasat_board_info.li_prid = lasat_board_info.li_eeprom_info.prid; | ||
235 | if (lasat_board_info.li_prid == 0xffff || lasat_board_info.li_prid == 0) | ||
236 | lasat_board_info.li_prid = lasat_board_info.li_bmid; | ||
237 | |||
238 | /* Base model stuff */ | ||
239 | if (lasat_board_info.li_bmid > i_n_base_models) | ||
240 | lasat_board_info.li_bmid = i_n_base_models; | ||
241 | strcpy(lasat_board_info.li_bmstr, i_txt_base_models[lasat_board_info.li_bmid]); | ||
242 | |||
243 | /* Product ID dependent values */ | ||
244 | c = lasat_board_info.li_prid; | ||
245 | if (c >= i_n_prids) { | ||
246 | strcpy(lasat_board_info.li_namestr, "Unknown Model"); | ||
247 | strcpy(lasat_board_info.li_typestr, "Unknown Type"); | ||
248 | } else { | ||
249 | ppi = &vendor_info_table[0].vi_product_info[c]; | ||
250 | strcpy(lasat_board_info.li_namestr, ppi->pi_name); | ||
251 | if (ppi->pi_type) | ||
252 | strcpy(lasat_board_info.li_typestr, ppi->pi_type); | ||
253 | else | ||
254 | sprintf(lasat_board_info.li_typestr, "%d",10*c); | ||
255 | } | ||
256 | |||
257 | #if defined(CONFIG_INET) && defined(CONFIG_SYSCTL) | ||
258 | update_bcastaddr(); | ||
259 | #endif | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | void lasat_write_eeprom_info(void) | ||
265 | { | ||
266 | unsigned long crc; | ||
267 | |||
268 | /* Generate the CRC */ | ||
269 | crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info), | ||
270 | sizeof(struct lasat_eeprom_struct) - 4); | ||
271 | lasat_board_info.li_eeprom_info.crc32 = crc; | ||
272 | |||
273 | /* Write the EEPROM info */ | ||
274 | EEPROMWrite(0, (unsigned char *)&lasat_board_info.li_eeprom_info, | ||
275 | sizeof(struct lasat_eeprom_struct)); | ||
276 | } | ||
277 | |||
diff --git a/arch/mips/lasat/lasat_models.h b/arch/mips/lasat/lasat_models.h new file mode 100644 index 000000000000..ae0c5d0bd403 --- /dev/null +++ b/arch/mips/lasat/lasat_models.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * Model description tables | ||
3 | */ | ||
4 | |||
5 | typedef struct product_info_t { | ||
6 | const char *pi_name; | ||
7 | const char *pi_type; | ||
8 | } product_info_t; | ||
9 | |||
10 | typedef struct vendor_info_t { | ||
11 | const char *vi_name; | ||
12 | const product_info_t *vi_product_info; | ||
13 | } vendor_info_t; | ||
14 | |||
15 | /* | ||
16 | * Base models | ||
17 | */ | ||
18 | static const char * const txt_base_models[] = { | ||
19 | "MQ 2", "MQ Pro", "SP 25", "SP 50", "SP 100", "SP 5000", "SP 7000", "SP 1000", "Unknown" | ||
20 | }; | ||
21 | #define N_BASE_MODELS (sizeof(txt_base_models)/sizeof(char*)-1) | ||
22 | |||
23 | /* | ||
24 | * Eicon Networks | ||
25 | */ | ||
26 | static const char txt_en_mq[] = "Masquerade"; | ||
27 | static const char txt_en_sp[] = "Safepipe"; | ||
28 | |||
29 | static const product_info_t product_info_eicon[] = { | ||
30 | { txt_en_mq, "II" }, /* 0 */ | ||
31 | { txt_en_mq, "Pro" }, /* 1 */ | ||
32 | { txt_en_sp, "25" }, /* 2 */ | ||
33 | { txt_en_sp, "50" }, /* 3 */ | ||
34 | { txt_en_sp, "100" }, /* 4 */ | ||
35 | { txt_en_sp, "5000" }, /* 5 */ | ||
36 | { txt_en_sp, "7000" }, /* 6 */ | ||
37 | { txt_en_sp, "30" }, /* 7 */ | ||
38 | { txt_en_sp, "5100" }, /* 8 */ | ||
39 | { txt_en_sp, "7100" }, /* 9 */ | ||
40 | { txt_en_sp, "1110" }, /* 10 */ | ||
41 | { txt_en_sp, "3020" }, /* 11 */ | ||
42 | { txt_en_sp, "3030" }, /* 12 */ | ||
43 | { txt_en_sp, "5020" }, /* 13 */ | ||
44 | { txt_en_sp, "5030" }, /* 14 */ | ||
45 | { txt_en_sp, "1120" }, /* 15 */ | ||
46 | { txt_en_sp, "1130" }, /* 16 */ | ||
47 | { txt_en_sp, "6010" }, /* 17 */ | ||
48 | { txt_en_sp, "6110" }, /* 18 */ | ||
49 | { txt_en_sp, "6210" }, /* 19 */ | ||
50 | { txt_en_sp, "1020" }, /* 20 */ | ||
51 | { txt_en_sp, "1040" }, /* 21 */ | ||
52 | { txt_en_sp, "1050" }, /* 22 */ | ||
53 | { txt_en_sp, "1060" }, /* 23 */ | ||
54 | }; | ||
55 | #define N_PRIDS (sizeof(product_info_eicon)/sizeof(product_info_t)) | ||
56 | |||
57 | /* | ||
58 | * The vendor table | ||
59 | */ | ||
60 | static vendor_info_t const vendor_info_table[] = { | ||
61 | { "Eicon Networks", product_info_eicon }, | ||
62 | }; | ||
63 | #define N_VENDORS (sizeof(vendor_info_table)/sizeof(vendor_info_t)) | ||
diff --git a/arch/mips/lasat/picvue.c b/arch/mips/lasat/picvue.c new file mode 100644 index 000000000000..5637cd153926 --- /dev/null +++ b/arch/mips/lasat/picvue.c | |||
@@ -0,0 +1,240 @@ | |||
1 | /* | ||
2 | * Picvue PVC160206 display driver | ||
3 | * | ||
4 | * Brian Murphy <brian@murphy.dk> | ||
5 | * | ||
6 | */ | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/delay.h> | ||
9 | #include <asm/bootinfo.h> | ||
10 | #include <asm/lasat/lasat.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/errno.h> | ||
14 | #include <linux/string.h> | ||
15 | |||
16 | #include "picvue.h" | ||
17 | |||
18 | #define PVC_BUSY 0x80 | ||
19 | #define PVC_NLINES 2 | ||
20 | #define PVC_DISPMEM 80 | ||
21 | #define PVC_LINELEN PVC_DISPMEM / PVC_NLINES | ||
22 | |||
23 | struct pvc_defs *picvue = NULL; | ||
24 | |||
25 | DECLARE_MUTEX(pvc_sem); | ||
26 | |||
27 | static void pvc_reg_write(u32 val) | ||
28 | { | ||
29 | *picvue->reg = val; | ||
30 | } | ||
31 | |||
32 | static u32 pvc_reg_read(void) | ||
33 | { | ||
34 | u32 tmp = *picvue->reg; | ||
35 | return tmp; | ||
36 | } | ||
37 | |||
38 | static void pvc_write_byte(u32 data, u8 byte) | ||
39 | { | ||
40 | data |= picvue->e; | ||
41 | pvc_reg_write(data); | ||
42 | data &= ~picvue->data_mask; | ||
43 | data |= byte << picvue->data_shift; | ||
44 | pvc_reg_write(data); | ||
45 | ndelay(220); | ||
46 | pvc_reg_write(data & ~picvue->e); | ||
47 | ndelay(220); | ||
48 | } | ||
49 | |||
50 | static u8 pvc_read_byte(u32 data) | ||
51 | { | ||
52 | u8 byte; | ||
53 | |||
54 | data |= picvue->e; | ||
55 | pvc_reg_write(data); | ||
56 | ndelay(220); | ||
57 | byte = (pvc_reg_read() & picvue->data_mask) >> picvue->data_shift; | ||
58 | data &= ~picvue->e; | ||
59 | pvc_reg_write(data); | ||
60 | ndelay(220); | ||
61 | return byte; | ||
62 | } | ||
63 | |||
64 | static u8 pvc_read_data(void) | ||
65 | { | ||
66 | u32 data = pvc_reg_read(); | ||
67 | u8 byte; | ||
68 | data |= picvue->rw; | ||
69 | data &= ~picvue->rs; | ||
70 | pvc_reg_write(data); | ||
71 | ndelay(40); | ||
72 | byte = pvc_read_byte(data); | ||
73 | data |= picvue->rs; | ||
74 | pvc_reg_write(data); | ||
75 | return byte; | ||
76 | } | ||
77 | |||
78 | #define TIMEOUT 1000 | ||
79 | static int pvc_wait(void) | ||
80 | { | ||
81 | int i = TIMEOUT; | ||
82 | int err = 0; | ||
83 | |||
84 | while ((pvc_read_data() & PVC_BUSY) && i) | ||
85 | i--; | ||
86 | if (i == 0) | ||
87 | err = -ETIME; | ||
88 | |||
89 | return err; | ||
90 | } | ||
91 | |||
92 | #define MODE_INST 0 | ||
93 | #define MODE_DATA 1 | ||
94 | static void pvc_write(u8 byte, int mode) | ||
95 | { | ||
96 | u32 data = pvc_reg_read(); | ||
97 | data &= ~picvue->rw; | ||
98 | if (mode == MODE_DATA) | ||
99 | data |= picvue->rs; | ||
100 | else | ||
101 | data &= ~picvue->rs; | ||
102 | pvc_reg_write(data); | ||
103 | ndelay(40); | ||
104 | pvc_write_byte(data, byte); | ||
105 | if (mode == MODE_DATA) | ||
106 | data &= ~picvue->rs; | ||
107 | else | ||
108 | data |= picvue->rs; | ||
109 | pvc_reg_write(data); | ||
110 | pvc_wait(); | ||
111 | } | ||
112 | |||
113 | void pvc_write_string(const unsigned char *str, u8 addr, int line) | ||
114 | { | ||
115 | int i = 0; | ||
116 | |||
117 | if (line > 0 && (PVC_NLINES > 1)) | ||
118 | addr += 0x40 * line; | ||
119 | pvc_write(0x80 | addr, MODE_INST); | ||
120 | |||
121 | while (*str != 0 && i < PVC_LINELEN) { | ||
122 | pvc_write(*str++, MODE_DATA); | ||
123 | i++; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | void pvc_write_string_centered(const unsigned char *str, int line) | ||
128 | { | ||
129 | int len = strlen(str); | ||
130 | u8 addr; | ||
131 | |||
132 | if (len > PVC_VISIBLE_CHARS) | ||
133 | addr = 0; | ||
134 | else | ||
135 | addr = (PVC_VISIBLE_CHARS - strlen(str))/2; | ||
136 | |||
137 | pvc_write_string(str, addr, line); | ||
138 | } | ||
139 | |||
140 | void pvc_dump_string(const unsigned char *str) | ||
141 | { | ||
142 | int len = strlen(str); | ||
143 | |||
144 | pvc_write_string(str, 0, 0); | ||
145 | if (len > PVC_VISIBLE_CHARS) | ||
146 | pvc_write_string(&str[PVC_VISIBLE_CHARS], 0, 1); | ||
147 | } | ||
148 | |||
149 | #define BM_SIZE 8 | ||
150 | #define MAX_PROGRAMMABLE_CHARS 8 | ||
151 | int pvc_program_cg(int charnum, u8 bitmap[BM_SIZE]) | ||
152 | { | ||
153 | int i; | ||
154 | int addr; | ||
155 | |||
156 | if (charnum > MAX_PROGRAMMABLE_CHARS) | ||
157 | return -ENOENT; | ||
158 | |||
159 | addr = charnum * 8; | ||
160 | pvc_write(0x40 | addr, MODE_INST); | ||
161 | |||
162 | for (i=0; i<BM_SIZE; i++) | ||
163 | pvc_write(bitmap[i], MODE_DATA); | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | #define FUNC_SET_CMD 0x20 | ||
168 | #define EIGHT_BYTE (1 << 4) | ||
169 | #define FOUR_BYTE 0 | ||
170 | #define TWO_LINES (1 << 3) | ||
171 | #define ONE_LINE 0 | ||
172 | #define LARGE_FONT (1 << 2) | ||
173 | #define SMALL_FONT 0 | ||
174 | static void pvc_funcset(u8 cmd) | ||
175 | { | ||
176 | pvc_write(FUNC_SET_CMD | (cmd & (EIGHT_BYTE|TWO_LINES|LARGE_FONT)), MODE_INST); | ||
177 | } | ||
178 | |||
179 | #define ENTRYMODE_CMD 0x4 | ||
180 | #define AUTO_INC (1 << 1) | ||
181 | #define AUTO_DEC 0 | ||
182 | #define CURSOR_FOLLOWS_DISP (1 << 0) | ||
183 | static void pvc_entrymode(u8 cmd) | ||
184 | { | ||
185 | pvc_write(ENTRYMODE_CMD | (cmd & (AUTO_INC|CURSOR_FOLLOWS_DISP)), MODE_INST); | ||
186 | } | ||
187 | |||
188 | #define DISP_CNT_CMD 0x08 | ||
189 | #define DISP_OFF 0 | ||
190 | #define DISP_ON (1 << 2) | ||
191 | #define CUR_ON (1 << 1) | ||
192 | #define CUR_BLINK (1 << 0) | ||
193 | void pvc_dispcnt(u8 cmd) | ||
194 | { | ||
195 | pvc_write(DISP_CNT_CMD | (cmd & (DISP_ON|CUR_ON|CUR_BLINK)), MODE_INST); | ||
196 | } | ||
197 | |||
198 | #define MOVE_CMD 0x10 | ||
199 | #define DISPLAY (1 << 3) | ||
200 | #define CURSOR 0 | ||
201 | #define RIGHT (1 << 2) | ||
202 | #define LEFT 0 | ||
203 | void pvc_move(u8 cmd) | ||
204 | { | ||
205 | pvc_write(MOVE_CMD | (cmd & (DISPLAY|RIGHT)), MODE_INST); | ||
206 | } | ||
207 | |||
208 | #define CLEAR_CMD 0x1 | ||
209 | void pvc_clear(void) | ||
210 | { | ||
211 | pvc_write(CLEAR_CMD, MODE_INST); | ||
212 | } | ||
213 | |||
214 | #define HOME_CMD 0x2 | ||
215 | void pvc_home(void) | ||
216 | { | ||
217 | pvc_write(HOME_CMD, MODE_INST); | ||
218 | } | ||
219 | |||
220 | int pvc_init(void) | ||
221 | { | ||
222 | u8 cmd = EIGHT_BYTE; | ||
223 | |||
224 | if (PVC_NLINES == 2) | ||
225 | cmd |= (SMALL_FONT|TWO_LINES); | ||
226 | else | ||
227 | cmd |= (LARGE_FONT|ONE_LINE); | ||
228 | pvc_funcset(cmd); | ||
229 | pvc_dispcnt(DISP_ON); | ||
230 | pvc_entrymode(AUTO_INC); | ||
231 | |||
232 | pvc_clear(); | ||
233 | pvc_write_string_centered("Display", 0); | ||
234 | pvc_write_string_centered("Initialized", 1); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | module_init(pvc_init); | ||
240 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/mips/lasat/picvue.h b/arch/mips/lasat/picvue.h new file mode 100644 index 000000000000..74a39039135d --- /dev/null +++ b/arch/mips/lasat/picvue.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * Picvue PVC160206 display driver | ||
3 | * | ||
4 | * Brian Murphy <brian.murphy@eicon.com> | ||
5 | * | ||
6 | */ | ||
7 | #include <asm/semaphore.h> | ||
8 | |||
9 | struct pvc_defs { | ||
10 | volatile u32 *reg; | ||
11 | u32 data_shift; | ||
12 | u32 data_mask; | ||
13 | u32 e; | ||
14 | u32 rw; | ||
15 | u32 rs; | ||
16 | }; | ||
17 | |||
18 | extern struct pvc_defs *picvue; | ||
19 | |||
20 | #define PVC_NLINES 2 | ||
21 | #define PVC_DISPMEM 80 | ||
22 | #define PVC_LINELEN PVC_DISPMEM / PVC_NLINES | ||
23 | #define PVC_VISIBLE_CHARS 16 | ||
24 | |||
25 | void pvc_write_string(const unsigned char *str, u8 addr, int line); | ||
26 | void pvc_write_string_centered(const unsigned char *str, int line); | ||
27 | void pvc_dump_string(const unsigned char *str); | ||
28 | |||
29 | #define BM_SIZE 8 | ||
30 | #define MAX_PROGRAMMABLE_CHARS 8 | ||
31 | int pvc_program_cg(int charnum, u8 bitmap[BM_SIZE]); | ||
32 | |||
33 | void pvc_dispcnt(u8 cmd); | ||
34 | #define DISP_OFF 0 | ||
35 | #define DISP_ON (1 << 2) | ||
36 | #define CUR_ON (1 << 1) | ||
37 | #define CUR_BLINK (1 << 0) | ||
38 | |||
39 | void pvc_move(u8 cmd); | ||
40 | #define DISPLAY (1 << 3) | ||
41 | #define CURSOR 0 | ||
42 | #define RIGHT (1 << 2) | ||
43 | #define LEFT 0 | ||
44 | |||
45 | void pvc_clear(void); | ||
46 | void pvc_home(void); | ||
47 | |||
48 | extern struct semaphore pvc_sem; | ||
diff --git a/arch/mips/lasat/picvue_proc.c b/arch/mips/lasat/picvue_proc.c new file mode 100644 index 000000000000..eaa2b4625124 --- /dev/null +++ b/arch/mips/lasat/picvue_proc.c | |||
@@ -0,0 +1,186 @@ | |||
1 | /* | ||
2 | * Picvue PVC160206 display driver | ||
3 | * | ||
4 | * Brian Murphy <brian.murphy@eicon.com> | ||
5 | * | ||
6 | */ | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/module.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/errno.h> | ||
11 | |||
12 | #include <linux/proc_fs.h> | ||
13 | #include <linux/interrupt.h> | ||
14 | |||
15 | #include <linux/timer.h> | ||
16 | |||
17 | #include "picvue.h" | ||
18 | |||
19 | static char pvc_lines[PVC_NLINES][PVC_LINELEN+1]; | ||
20 | static int pvc_linedata[PVC_NLINES]; | ||
21 | static struct proc_dir_entry *pvc_display_dir; | ||
22 | static char *pvc_linename[PVC_NLINES] = {"line1", "line2"}; | ||
23 | #define DISPLAY_DIR_NAME "display" | ||
24 | static int scroll_dir = 0, scroll_interval = 0; | ||
25 | |||
26 | static struct timer_list timer; | ||
27 | |||
28 | static void pvc_display(unsigned long data) { | ||
29 | int i; | ||
30 | |||
31 | pvc_clear(); | ||
32 | for (i=0; i<PVC_NLINES; i++) | ||
33 | pvc_write_string(pvc_lines[i], 0, i); | ||
34 | } | ||
35 | |||
36 | static DECLARE_TASKLET(pvc_display_tasklet, &pvc_display, 0); | ||
37 | |||
38 | static int pvc_proc_read_line(char *page, char **start, | ||
39 | off_t off, int count, | ||
40 | int *eof, void *data) | ||
41 | { | ||
42 | char *origpage = page; | ||
43 | int lineno = *(int *)data; | ||
44 | |||
45 | if (lineno < 0 || lineno > PVC_NLINES) { | ||
46 | printk("proc_read_line: invalid lineno %d\n", lineno); | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | down(&pvc_sem); | ||
51 | page += sprintf(page, "%s\n", pvc_lines[lineno]); | ||
52 | up(&pvc_sem); | ||
53 | |||
54 | return page - origpage; | ||
55 | } | ||
56 | |||
57 | static int pvc_proc_write_line(struct file *file, const char *buffer, | ||
58 | unsigned long count, void *data) | ||
59 | { | ||
60 | int origcount = count; | ||
61 | int lineno = *(int *)data; | ||
62 | |||
63 | if (lineno < 0 || lineno > PVC_NLINES) { | ||
64 | printk("proc_write_line: invalid lineno %d\n", lineno); | ||
65 | return origcount; | ||
66 | } | ||
67 | |||
68 | if (count > PVC_LINELEN) | ||
69 | count = PVC_LINELEN; | ||
70 | |||
71 | if (buffer[count-1] == '\n') | ||
72 | count--; | ||
73 | |||
74 | down(&pvc_sem); | ||
75 | strncpy(pvc_lines[lineno], buffer, count); | ||
76 | pvc_lines[lineno][count] = '\0'; | ||
77 | up(&pvc_sem); | ||
78 | |||
79 | tasklet_schedule(&pvc_display_tasklet); | ||
80 | |||
81 | return origcount; | ||
82 | } | ||
83 | |||
84 | static int pvc_proc_write_scroll(struct file *file, const char *buffer, | ||
85 | unsigned long count, void *data) | ||
86 | { | ||
87 | int origcount = count; | ||
88 | int cmd = simple_strtol(buffer, NULL, 10); | ||
89 | |||
90 | down(&pvc_sem); | ||
91 | if (scroll_interval != 0) | ||
92 | del_timer(&timer); | ||
93 | |||
94 | if (cmd == 0) { | ||
95 | scroll_dir = 0; | ||
96 | scroll_interval = 0; | ||
97 | } else { | ||
98 | if (cmd < 0) { | ||
99 | scroll_dir = -1; | ||
100 | scroll_interval = -cmd; | ||
101 | } else { | ||
102 | scroll_dir = 1; | ||
103 | scroll_interval = cmd; | ||
104 | } | ||
105 | add_timer(&timer); | ||
106 | } | ||
107 | up(&pvc_sem); | ||
108 | |||
109 | return origcount; | ||
110 | } | ||
111 | |||
112 | static int pvc_proc_read_scroll(char *page, char **start, | ||
113 | off_t off, int count, | ||
114 | int *eof, void *data) | ||
115 | { | ||
116 | char *origpage = page; | ||
117 | |||
118 | down(&pvc_sem); | ||
119 | page += sprintf(page, "%d\n", scroll_dir * scroll_interval); | ||
120 | up(&pvc_sem); | ||
121 | |||
122 | return page - origpage; | ||
123 | } | ||
124 | |||
125 | |||
126 | void pvc_proc_timerfunc(unsigned long data) | ||
127 | { | ||
128 | if (scroll_dir < 0) | ||
129 | pvc_move(DISPLAY|RIGHT); | ||
130 | else if (scroll_dir > 0) | ||
131 | pvc_move(DISPLAY|LEFT); | ||
132 | |||
133 | timer.expires = jiffies + scroll_interval; | ||
134 | add_timer(&timer); | ||
135 | } | ||
136 | |||
137 | static void pvc_proc_cleanup(void) | ||
138 | { | ||
139 | int i; | ||
140 | for (i=0; i<PVC_NLINES; i++) | ||
141 | remove_proc_entry(pvc_linename[i], pvc_display_dir); | ||
142 | remove_proc_entry("scroll", pvc_display_dir); | ||
143 | remove_proc_entry(DISPLAY_DIR_NAME, NULL); | ||
144 | |||
145 | del_timer(&timer); | ||
146 | } | ||
147 | |||
148 | static int __init pvc_proc_init(void) | ||
149 | { | ||
150 | struct proc_dir_entry *proc_entry; | ||
151 | int i; | ||
152 | |||
153 | pvc_display_dir = proc_mkdir(DISPLAY_DIR_NAME, NULL); | ||
154 | if (pvc_display_dir == NULL) | ||
155 | goto error; | ||
156 | |||
157 | for (i=0; i<PVC_NLINES; i++) { | ||
158 | strcpy(pvc_lines[i], ""); | ||
159 | pvc_linedata[i] = i; | ||
160 | } | ||
161 | for (i=0; i<PVC_NLINES; i++) { | ||
162 | proc_entry = create_proc_entry(pvc_linename[i], 0644, pvc_display_dir); | ||
163 | if (proc_entry == NULL) | ||
164 | goto error; | ||
165 | proc_entry->read_proc = pvc_proc_read_line; | ||
166 | proc_entry->write_proc = pvc_proc_write_line; | ||
167 | proc_entry->data = &pvc_linedata[i]; | ||
168 | } | ||
169 | proc_entry = create_proc_entry("scroll", 0644, pvc_display_dir); | ||
170 | if (proc_entry == NULL) | ||
171 | goto error; | ||
172 | proc_entry->write_proc = pvc_proc_write_scroll; | ||
173 | proc_entry->read_proc = pvc_proc_read_scroll; | ||
174 | |||
175 | init_timer(&timer); | ||
176 | timer.function = pvc_proc_timerfunc; | ||
177 | |||
178 | return 0; | ||
179 | error: | ||
180 | pvc_proc_cleanup(); | ||
181 | return -ENOMEM; | ||
182 | } | ||
183 | |||
184 | module_init(pvc_proc_init); | ||
185 | module_exit(pvc_proc_cleanup); | ||
186 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/mips/lasat/prom.c b/arch/mips/lasat/prom.c new file mode 100644 index 000000000000..ca62881c9e52 --- /dev/null +++ b/arch/mips/lasat/prom.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * PROM interface routines. | ||
3 | */ | ||
4 | #include <linux/types.h> | ||
5 | #include <linux/init.h> | ||
6 | #include <linux/string.h> | ||
7 | #include <linux/ctype.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/mm.h> | ||
10 | #include <linux/bootmem.h> | ||
11 | #include <linux/ioport.h> | ||
12 | #include <asm/bootinfo.h> | ||
13 | #include <asm/lasat/lasat.h> | ||
14 | #include <asm/cpu.h> | ||
15 | |||
16 | #include "at93c.h" | ||
17 | #include <asm/lasat/eeprom.h> | ||
18 | #include "prom.h" | ||
19 | |||
20 | #define RESET_VECTOR 0xbfc00000 | ||
21 | #define PROM_JUMP_TABLE_ENTRY(n) (*((u32 *)(RESET_VECTOR + 0x20) + n)) | ||
22 | #define PROM_DISPLAY_ADDR PROM_JUMP_TABLE_ENTRY(0) | ||
23 | #define PROM_PUTC_ADDR PROM_JUMP_TABLE_ENTRY(1) | ||
24 | #define PROM_MONITOR_ADDR PROM_JUMP_TABLE_ENTRY(2) | ||
25 | |||
26 | static void null_prom_printf(const char * fmt, ...) | ||
27 | { | ||
28 | } | ||
29 | |||
30 | static void null_prom_display(const char *string, int pos, int clear) | ||
31 | { | ||
32 | } | ||
33 | |||
34 | static void null_prom_monitor(void) | ||
35 | { | ||
36 | } | ||
37 | |||
38 | static void null_prom_putc(char c) | ||
39 | { | ||
40 | } | ||
41 | |||
42 | /* these are functions provided by the bootloader */ | ||
43 | static void (* prom_putc)(char c) = null_prom_putc; | ||
44 | void (* prom_printf)(const char * fmt, ...) = null_prom_printf; | ||
45 | void (* prom_display)(const char *string, int pos, int clear) = | ||
46 | null_prom_display; | ||
47 | void (* prom_monitor)(void) = null_prom_monitor; | ||
48 | |||
49 | unsigned int lasat_ndelay_divider; | ||
50 | |||
51 | #define PROM_PRINTFBUF_SIZE 256 | ||
52 | static char prom_printfbuf[PROM_PRINTFBUF_SIZE]; | ||
53 | |||
54 | static void real_prom_printf(const char * fmt, ...) | ||
55 | { | ||
56 | va_list ap; | ||
57 | int len; | ||
58 | char *c = prom_printfbuf; | ||
59 | int i; | ||
60 | |||
61 | va_start(ap, fmt); | ||
62 | len = vsnprintf(prom_printfbuf, PROM_PRINTFBUF_SIZE, fmt, ap); | ||
63 | va_end(ap); | ||
64 | |||
65 | /* output overflowed the buffer */ | ||
66 | if (len < 0 || len > PROM_PRINTFBUF_SIZE) | ||
67 | len = PROM_PRINTFBUF_SIZE; | ||
68 | |||
69 | for (i=0; i < len; i++) { | ||
70 | if (*c == '\n') | ||
71 | prom_putc('\r'); | ||
72 | prom_putc(*c++); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | static void setup_prom_vectors(void) | ||
77 | { | ||
78 | u32 version = *(u32 *)(RESET_VECTOR + 0x90); | ||
79 | |||
80 | if (version >= 307) { | ||
81 | prom_display = (void *)PROM_DISPLAY_ADDR; | ||
82 | prom_putc = (void *)PROM_PUTC_ADDR; | ||
83 | prom_printf = real_prom_printf; | ||
84 | prom_monitor = (void *)PROM_MONITOR_ADDR; | ||
85 | } | ||
86 | prom_printf("prom vectors set up\n"); | ||
87 | } | ||
88 | |||
89 | static struct at93c_defs at93c_defs[N_MACHTYPES] = { | ||
90 | {(void *)AT93C_REG_100, (void *)AT93C_RDATA_REG_100, AT93C_RDATA_SHIFT_100, | ||
91 | AT93C_WDATA_SHIFT_100, AT93C_CS_M_100, AT93C_CLK_M_100}, | ||
92 | {(void *)AT93C_REG_200, (void *)AT93C_RDATA_REG_200, AT93C_RDATA_SHIFT_200, | ||
93 | AT93C_WDATA_SHIFT_200, AT93C_CS_M_200, AT93C_CLK_M_200}, | ||
94 | }; | ||
95 | |||
96 | void __init prom_init(void) | ||
97 | { | ||
98 | int argc = fw_arg0; | ||
99 | char **argv = (char **) fw_arg1; | ||
100 | |||
101 | setup_prom_vectors(); | ||
102 | |||
103 | if (current_cpu_data.cputype == CPU_R5000) { | ||
104 | prom_printf("LASAT 200 board\n"); | ||
105 | mips_machtype = MACH_LASAT_200; | ||
106 | lasat_ndelay_divider = LASAT_200_DIVIDER; | ||
107 | } else { | ||
108 | prom_printf("LASAT 100 board\n"); | ||
109 | mips_machtype = MACH_LASAT_100; | ||
110 | lasat_ndelay_divider = LASAT_100_DIVIDER; | ||
111 | } | ||
112 | |||
113 | at93c = &at93c_defs[mips_machtype]; | ||
114 | |||
115 | lasat_init_board_info(); /* Read info from EEPROM */ | ||
116 | |||
117 | mips_machgroup = MACH_GROUP_LASAT; | ||
118 | |||
119 | /* Get the command line */ | ||
120 | if (argc > 0) { | ||
121 | strncpy(arcs_cmdline, argv[0], CL_SIZE-1); | ||
122 | arcs_cmdline[CL_SIZE-1] = '\0'; | ||
123 | } | ||
124 | |||
125 | /* Set the I/O base address */ | ||
126 | set_io_port_base(KSEG1); | ||
127 | |||
128 | /* Set memory regions */ | ||
129 | ioport_resource.start = 0; | ||
130 | ioport_resource.end = 0xffffffff; /* Wrong, fixme. */ | ||
131 | |||
132 | add_memory_region(0, lasat_board_info.li_memsize, BOOT_MEM_RAM); | ||
133 | } | ||
134 | |||
135 | unsigned long __init prom_free_prom_memory(void) | ||
136 | { | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | const char *get_system_type(void) | ||
141 | { | ||
142 | return lasat_board_info.li_bmstr; | ||
143 | } | ||
diff --git a/arch/mips/lasat/prom.h b/arch/mips/lasat/prom.h new file mode 100644 index 000000000000..07be7bf1e4a3 --- /dev/null +++ b/arch/mips/lasat/prom.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef PROM_H | ||
2 | #define PROM_H | ||
3 | extern void (* prom_display)(const char *string, int pos, int clear); | ||
4 | extern void (* prom_monitor)(void); | ||
5 | extern void (* prom_printf)(const char * fmt, ...); | ||
6 | #endif | ||
diff --git a/arch/mips/lasat/reset.c b/arch/mips/lasat/reset.c new file mode 100644 index 000000000000..37e4912ee1c8 --- /dev/null +++ b/arch/mips/lasat/reset.c | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * Thomas Horsten <thh@lasat.com> | ||
3 | * Copyright (C) 2000 LASAT Networks A/S. | ||
4 | * | ||
5 | * This program is free software; you can distribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License (Version 2) as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
12 | * for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
17 | * | ||
18 | * Reset the LASAT board. | ||
19 | */ | ||
20 | #include <linux/config.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <asm/reboot.h> | ||
23 | #include <asm/system.h> | ||
24 | #include <asm/lasat/lasat.h> | ||
25 | #include "picvue.h" | ||
26 | #include "prom.h" | ||
27 | |||
28 | static void lasat_machine_restart(char *command); | ||
29 | static void lasat_machine_halt(void); | ||
30 | |||
31 | /* Used to set machine to boot in service mode via /proc interface */ | ||
32 | int lasat_boot_to_service = 0; | ||
33 | |||
34 | static void lasat_machine_restart(char *command) | ||
35 | { | ||
36 | local_irq_disable(); | ||
37 | |||
38 | if (lasat_boot_to_service) { | ||
39 | printk("machine_restart: Rebooting to service mode\n"); | ||
40 | *(volatile unsigned int *)0xa0000024 = 0xdeadbeef; | ||
41 | *(volatile unsigned int *)0xa00000fc = 0xfedeabba; | ||
42 | } | ||
43 | *lasat_misc->reset_reg = 0xbedead; | ||
44 | for (;;) ; | ||
45 | } | ||
46 | |||
47 | #define MESSAGE "System halted" | ||
48 | static void lasat_machine_halt(void) | ||
49 | { | ||
50 | local_irq_disable(); | ||
51 | |||
52 | /* Disable interrupts and loop forever */ | ||
53 | printk(KERN_NOTICE MESSAGE "\n"); | ||
54 | #ifdef CONFIG_PICVUE | ||
55 | pvc_clear(); | ||
56 | pvc_write_string(MESSAGE, 0, 0); | ||
57 | #endif | ||
58 | prom_monitor(); | ||
59 | for (;;) ; | ||
60 | } | ||
61 | |||
62 | void lasat_reboot_setup(void) | ||
63 | { | ||
64 | _machine_restart = lasat_machine_restart; | ||
65 | _machine_halt = lasat_machine_halt; | ||
66 | _machine_power_off = lasat_machine_halt; | ||
67 | } | ||
diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c new file mode 100644 index 000000000000..e371ed5cbe34 --- /dev/null +++ b/arch/mips/lasat/setup.c | |||
@@ -0,0 +1,192 @@ | |||
1 | /* | ||
2 | * Carsten Langgaard, carstenl@mips.com | ||
3 | * Copyright (C) 1999 MIPS Technologies, Inc. All rights reserved. | ||
4 | * | ||
5 | * Thomas Horsten <thh@lasat.com> | ||
6 | * Copyright (C) 2000 LASAT Networks A/S. | ||
7 | * | ||
8 | * Brian Murphy <brian@murphy.dk> | ||
9 | * | ||
10 | * This program is free software; you can distribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License (Version 2) as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
17 | * for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
22 | * | ||
23 | * Lasat specific setup. | ||
24 | */ | ||
25 | #include <linux/config.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/sched.h> | ||
28 | #include <linux/pci.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/tty.h> | ||
31 | #include <linux/serial.h> | ||
32 | #include <linux/serial_core.h> | ||
33 | |||
34 | #include <asm/time.h> | ||
35 | #include <asm/cpu.h> | ||
36 | #include <asm/bootinfo.h> | ||
37 | #include <asm/irq.h> | ||
38 | #include <asm/serial.h> | ||
39 | #include <asm/lasat/lasat.h> | ||
40 | #include <asm/lasat/serial.h> | ||
41 | |||
42 | #ifdef CONFIG_PICVUE | ||
43 | #include <linux/notifier.h> | ||
44 | #endif | ||
45 | |||
46 | #include "ds1603.h" | ||
47 | #include <asm/lasat/ds1603.h> | ||
48 | #include <asm/lasat/picvue.h> | ||
49 | #include <asm/lasat/eeprom.h> | ||
50 | |||
51 | #include "prom.h" | ||
52 | |||
53 | int lasat_command_line = 0; | ||
54 | void lasatint_init(void); | ||
55 | |||
56 | extern void lasat_reboot_setup(void); | ||
57 | extern void pcisetup(void); | ||
58 | extern void edhac_init(void *, void *, void *); | ||
59 | extern void addrflt_init(void); | ||
60 | |||
61 | struct lasat_misc lasat_misc_info[N_MACHTYPES] = { | ||
62 | {(void *)KSEG1ADDR(0x1c840000), (void *)KSEG1ADDR(0x1c800000), 2}, | ||
63 | {(void *)KSEG1ADDR(0x11080000), (void *)KSEG1ADDR(0x11000000), 6} | ||
64 | }; | ||
65 | |||
66 | struct lasat_misc *lasat_misc = NULL; | ||
67 | |||
68 | #ifdef CONFIG_DS1603 | ||
69 | static struct ds_defs ds_defs[N_MACHTYPES] = { | ||
70 | { (void *)DS1603_REG_100, (void *)DS1603_REG_100, | ||
71 | DS1603_RST_100, DS1603_CLK_100, DS1603_DATA_100, | ||
72 | DS1603_DATA_SHIFT_100, 0, 0 }, | ||
73 | { (void *)DS1603_REG_200, (void *)DS1603_DATA_REG_200, | ||
74 | DS1603_RST_200, DS1603_CLK_200, DS1603_DATA_200, | ||
75 | DS1603_DATA_READ_SHIFT_200, 1, 2000 } | ||
76 | }; | ||
77 | #endif | ||
78 | |||
79 | #ifdef CONFIG_PICVUE | ||
80 | #include "picvue.h" | ||
81 | static struct pvc_defs pvc_defs[N_MACHTYPES] = { | ||
82 | { (void *)PVC_REG_100, PVC_DATA_SHIFT_100, PVC_DATA_M_100, | ||
83 | PVC_E_100, PVC_RW_100, PVC_RS_100 }, | ||
84 | { (void *)PVC_REG_200, PVC_DATA_SHIFT_200, PVC_DATA_M_200, | ||
85 | PVC_E_200, PVC_RW_200, PVC_RS_200 } | ||
86 | }; | ||
87 | #endif | ||
88 | |||
89 | static int lasat_panic_display(struct notifier_block *this, | ||
90 | unsigned long event, void *ptr) | ||
91 | { | ||
92 | #ifdef CONFIG_PICVUE | ||
93 | unsigned char *string = ptr; | ||
94 | if (string == NULL) | ||
95 | string = "Kernel Panic"; | ||
96 | pvc_dump_string(string); | ||
97 | #endif | ||
98 | return NOTIFY_DONE; | ||
99 | } | ||
100 | |||
101 | static int lasat_panic_prom_monitor(struct notifier_block *this, | ||
102 | unsigned long event, void *ptr) | ||
103 | { | ||
104 | prom_monitor(); | ||
105 | return NOTIFY_DONE; | ||
106 | } | ||
107 | |||
108 | static struct notifier_block lasat_panic_block[] = | ||
109 | { | ||
110 | { lasat_panic_display, NULL, INT_MAX }, | ||
111 | { lasat_panic_prom_monitor, NULL, INT_MIN } | ||
112 | }; | ||
113 | |||
114 | static void lasat_time_init(void) | ||
115 | { | ||
116 | mips_hpt_frequency = lasat_board_info.li_cpu_hz / 2; | ||
117 | } | ||
118 | |||
119 | static void lasat_timer_setup(struct irqaction *irq) | ||
120 | { | ||
121 | |||
122 | write_c0_compare( | ||
123 | read_c0_count() + | ||
124 | mips_hpt_frequency / HZ); | ||
125 | change_c0_status(ST0_IM, IE_IRQ0 | IE_IRQ5); | ||
126 | } | ||
127 | |||
128 | #define DYNAMIC_SERIAL_INIT | ||
129 | #ifdef DYNAMIC_SERIAL_INIT | ||
130 | void __init serial_init(void) | ||
131 | { | ||
132 | #ifdef CONFIG_SERIAL_8250 | ||
133 | struct uart_port s; | ||
134 | |||
135 | memset(&s, 0, sizeof(s)); | ||
136 | |||
137 | s.flags = STD_COM_FLAGS; | ||
138 | s.iotype = SERIAL_IO_MEM; | ||
139 | |||
140 | if (mips_machtype == MACH_LASAT_100) { | ||
141 | s.uartclk = LASAT_BASE_BAUD_100 * 16; | ||
142 | s.irq = LASATINT_UART_100; | ||
143 | s.regshift = LASAT_UART_REGS_SHIFT_100; | ||
144 | s.membase = (char *)KSEG1ADDR(LASAT_UART_REGS_BASE_100); | ||
145 | } else { | ||
146 | s.uartclk = LASAT_BASE_BAUD_200 * 16; | ||
147 | s.irq = LASATINT_UART_200; | ||
148 | s.regshift = LASAT_UART_REGS_SHIFT_200; | ||
149 | s.membase = (char *)KSEG1ADDR(LASAT_UART_REGS_BASE_200); | ||
150 | } | ||
151 | |||
152 | if (early_serial_setup(&s) != 0) | ||
153 | printk(KERN_ERR "Serial setup failed!\n"); | ||
154 | #endif | ||
155 | } | ||
156 | #endif | ||
157 | |||
158 | static int __init lasat_setup(void) | ||
159 | { | ||
160 | int i; | ||
161 | lasat_misc = &lasat_misc_info[mips_machtype]; | ||
162 | #ifdef CONFIG_PICVUE | ||
163 | picvue = &pvc_defs[mips_machtype]; | ||
164 | #endif | ||
165 | |||
166 | /* Set up panic notifier */ | ||
167 | for (i = 0; i < sizeof(lasat_panic_block) / sizeof(struct notifier_block); i++) | ||
168 | notifier_chain_register(&panic_notifier_list, &lasat_panic_block[i]); | ||
169 | |||
170 | lasat_reboot_setup(); | ||
171 | |||
172 | board_time_init = lasat_time_init; | ||
173 | board_timer_setup = lasat_timer_setup; | ||
174 | |||
175 | #ifdef CONFIG_DS1603 | ||
176 | ds1603 = &ds_defs[mips_machtype]; | ||
177 | rtc_get_time = ds1603_read; | ||
178 | rtc_set_time = ds1603_set; | ||
179 | #endif | ||
180 | |||
181 | #ifdef DYNAMIC_SERIAL_INIT | ||
182 | serial_init(); | ||
183 | #endif | ||
184 | /* Switch from prom exception handler to normal mode */ | ||
185 | change_c0_status(ST0_BEV,0); | ||
186 | |||
187 | prom_printf("Lasat specific initialization complete\n"); | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | early_initcall(lasat_setup); | ||
diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c new file mode 100644 index 000000000000..1c0cc620a43f --- /dev/null +++ b/arch/mips/lasat/sysctl.c | |||
@@ -0,0 +1,355 @@ | |||
1 | /* | ||
2 | * Thomas Horsten <thh@lasat.com> | ||
3 | * Copyright (C) 2000 LASAT Networks A/S. | ||
4 | * | ||
5 | * This program is free software; you can distribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License (Version 2) as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
12 | * for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
17 | * | ||
18 | * Routines specific to the LASAT boards | ||
19 | */ | ||
20 | #include <linux/types.h> | ||
21 | #include <asm/lasat/lasat.h> | ||
22 | |||
23 | #include <linux/config.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/sysctl.h> | ||
26 | #include <linux/stddef.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/fs.h> | ||
29 | #include <linux/ctype.h> | ||
30 | #include <linux/string.h> | ||
31 | #include <linux/net.h> | ||
32 | #include <linux/inet.h> | ||
33 | #include <asm/uaccess.h> | ||
34 | |||
35 | #include "sysctl.h" | ||
36 | #include "ds1603.h" | ||
37 | |||
38 | static DECLARE_MUTEX(lasat_info_sem); | ||
39 | |||
40 | /* Strategy function to write EEPROM after changing string entry */ | ||
41 | int sysctl_lasatstring(ctl_table *table, int *name, int nlen, | ||
42 | void *oldval, size_t *oldlenp, | ||
43 | void *newval, size_t newlen, void **context) | ||
44 | { | ||
45 | int r; | ||
46 | down(&lasat_info_sem); | ||
47 | r = sysctl_string(table, name, | ||
48 | nlen, oldval, oldlenp, newval, newlen, context); | ||
49 | if (r < 0) { | ||
50 | up(&lasat_info_sem); | ||
51 | return r; | ||
52 | } | ||
53 | if (newval && newlen) { | ||
54 | lasat_write_eeprom_info(); | ||
55 | } | ||
56 | up(&lasat_info_sem); | ||
57 | return 1; | ||
58 | } | ||
59 | |||
60 | |||
61 | /* And the same for proc */ | ||
62 | int proc_dolasatstring(ctl_table *table, int write, struct file *filp, | ||
63 | void *buffer, size_t *lenp, loff_t *ppos) | ||
64 | { | ||
65 | int r; | ||
66 | down(&lasat_info_sem); | ||
67 | r = proc_dostring(table, write, filp, buffer, lenp, ppos); | ||
68 | if ( (!write) || r) { | ||
69 | up(&lasat_info_sem); | ||
70 | return r; | ||
71 | } | ||
72 | lasat_write_eeprom_info(); | ||
73 | up(&lasat_info_sem); | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | /* proc function to write EEPROM after changing int entry */ | ||
78 | int proc_dolasatint(ctl_table *table, int write, struct file *filp, | ||
79 | void *buffer, size_t *lenp, loff_t *ppos) | ||
80 | { | ||
81 | int r; | ||
82 | down(&lasat_info_sem); | ||
83 | r = proc_dointvec(table, write, filp, buffer, lenp, ppos); | ||
84 | if ( (!write) || r) { | ||
85 | up(&lasat_info_sem); | ||
86 | return r; | ||
87 | } | ||
88 | lasat_write_eeprom_info(); | ||
89 | up(&lasat_info_sem); | ||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | static int rtctmp; | ||
94 | |||
95 | #ifdef CONFIG_DS1603 | ||
96 | /* proc function to read/write RealTime Clock */ | ||
97 | int proc_dolasatrtc(ctl_table *table, int write, struct file *filp, | ||
98 | void *buffer, size_t *lenp, loff_t *ppos) | ||
99 | { | ||
100 | int r; | ||
101 | down(&lasat_info_sem); | ||
102 | if (!write) { | ||
103 | rtctmp = ds1603_read(); | ||
104 | /* check for time < 0 and set to 0 */ | ||
105 | if (rtctmp < 0) | ||
106 | rtctmp = 0; | ||
107 | } | ||
108 | r = proc_dointvec(table, write, filp, buffer, lenp, ppos); | ||
109 | if ( (!write) || r) { | ||
110 | up(&lasat_info_sem); | ||
111 | return r; | ||
112 | } | ||
113 | ds1603_set(rtctmp); | ||
114 | up(&lasat_info_sem); | ||
115 | return 0; | ||
116 | } | ||
117 | #endif | ||
118 | |||
119 | /* Sysctl for setting the IP addresses */ | ||
120 | int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen, | ||
121 | void *oldval, size_t *oldlenp, | ||
122 | void *newval, size_t newlen, void **context) | ||
123 | { | ||
124 | int r; | ||
125 | down(&lasat_info_sem); | ||
126 | r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context); | ||
127 | if (r < 0) { | ||
128 | up(&lasat_info_sem); | ||
129 | return r; | ||
130 | } | ||
131 | if (newval && newlen) { | ||
132 | lasat_write_eeprom_info(); | ||
133 | } | ||
134 | up(&lasat_info_sem); | ||
135 | return 1; | ||
136 | } | ||
137 | |||
138 | #ifdef CONFIG_DS1603 | ||
139 | /* Same for RTC */ | ||
140 | int sysctl_lasat_rtc(ctl_table *table, int *name, int nlen, | ||
141 | void *oldval, size_t *oldlenp, | ||
142 | void *newval, size_t newlen, void **context) | ||
143 | { | ||
144 | int r; | ||
145 | down(&lasat_info_sem); | ||
146 | rtctmp = ds1603_read(); | ||
147 | if (rtctmp < 0) | ||
148 | rtctmp = 0; | ||
149 | r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context); | ||
150 | if (r < 0) { | ||
151 | up(&lasat_info_sem); | ||
152 | return r; | ||
153 | } | ||
154 | if (newval && newlen) { | ||
155 | ds1603_set(rtctmp); | ||
156 | } | ||
157 | up(&lasat_info_sem); | ||
158 | return 1; | ||
159 | } | ||
160 | #endif | ||
161 | |||
162 | #ifdef CONFIG_INET | ||
163 | static char lasat_bcastaddr[16]; | ||
164 | |||
165 | void update_bcastaddr(void) | ||
166 | { | ||
167 | unsigned int ip; | ||
168 | |||
169 | ip = (lasat_board_info.li_eeprom_info.ipaddr & | ||
170 | lasat_board_info.li_eeprom_info.netmask) | | ||
171 | ~lasat_board_info.li_eeprom_info.netmask; | ||
172 | |||
173 | sprintf(lasat_bcastaddr, "%d.%d.%d.%d", | ||
174 | (ip ) & 0xff, | ||
175 | (ip >> 8) & 0xff, | ||
176 | (ip >> 16) & 0xff, | ||
177 | (ip >> 24) & 0xff); | ||
178 | } | ||
179 | |||
180 | static char proc_lasat_ipbuf[32]; | ||
181 | /* Parsing of IP address */ | ||
182 | int proc_lasat_ip(ctl_table *table, int write, struct file *filp, | ||
183 | void *buffer, size_t *lenp, loff_t *ppos) | ||
184 | { | ||
185 | int len; | ||
186 | unsigned int ip; | ||
187 | char *p, c; | ||
188 | |||
189 | if (!table->data || !table->maxlen || !*lenp || | ||
190 | (*ppos && !write)) { | ||
191 | *lenp = 0; | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | down(&lasat_info_sem); | ||
196 | if (write) { | ||
197 | len = 0; | ||
198 | p = buffer; | ||
199 | while (len < *lenp) { | ||
200 | if(get_user(c, p++)) { | ||
201 | up(&lasat_info_sem); | ||
202 | return -EFAULT; | ||
203 | } | ||
204 | if (c == 0 || c == '\n') | ||
205 | break; | ||
206 | len++; | ||
207 | } | ||
208 | if (len >= sizeof(proc_lasat_ipbuf)-1) | ||
209 | len = sizeof(proc_lasat_ipbuf) - 1; | ||
210 | if (copy_from_user(proc_lasat_ipbuf, buffer, len)) | ||
211 | { | ||
212 | up(&lasat_info_sem); | ||
213 | return -EFAULT; | ||
214 | } | ||
215 | proc_lasat_ipbuf[len] = 0; | ||
216 | *ppos += *lenp; | ||
217 | /* Now see if we can convert it to a valid IP */ | ||
218 | ip = in_aton(proc_lasat_ipbuf); | ||
219 | *(unsigned int *)(table->data) = ip; | ||
220 | lasat_write_eeprom_info(); | ||
221 | } else { | ||
222 | ip = *(unsigned int *)(table->data); | ||
223 | sprintf(proc_lasat_ipbuf, "%d.%d.%d.%d", | ||
224 | (ip ) & 0xff, | ||
225 | (ip >> 8) & 0xff, | ||
226 | (ip >> 16) & 0xff, | ||
227 | (ip >> 24) & 0xff); | ||
228 | len = strlen(proc_lasat_ipbuf); | ||
229 | if (len > *lenp) | ||
230 | len = *lenp; | ||
231 | if (len) | ||
232 | if(copy_to_user(buffer, proc_lasat_ipbuf, len)) { | ||
233 | up(&lasat_info_sem); | ||
234 | return -EFAULT; | ||
235 | } | ||
236 | if (len < *lenp) { | ||
237 | if(put_user('\n', ((char *) buffer) + len)) { | ||
238 | up(&lasat_info_sem); | ||
239 | return -EFAULT; | ||
240 | } | ||
241 | len++; | ||
242 | } | ||
243 | *lenp = len; | ||
244 | *ppos += len; | ||
245 | } | ||
246 | update_bcastaddr(); | ||
247 | up(&lasat_info_sem); | ||
248 | return 0; | ||
249 | } | ||
250 | #endif /* defined(CONFIG_INET) */ | ||
251 | |||
252 | static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen, | ||
253 | void *oldval, size_t *oldlenp, | ||
254 | void *newval, size_t newlen, | ||
255 | void **context) | ||
256 | { | ||
257 | int r; | ||
258 | |||
259 | down(&lasat_info_sem); | ||
260 | r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context); | ||
261 | if (r < 0) { | ||
262 | up(&lasat_info_sem); | ||
263 | return r; | ||
264 | } | ||
265 | |||
266 | if (newval && newlen) | ||
267 | { | ||
268 | if (name && *name == LASAT_PRID) | ||
269 | lasat_board_info.li_eeprom_info.prid = *(int*)newval; | ||
270 | |||
271 | lasat_write_eeprom_info(); | ||
272 | lasat_init_board_info(); | ||
273 | } | ||
274 | up(&lasat_info_sem); | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp, | ||
280 | void *buffer, size_t *lenp, loff_t *ppos) | ||
281 | { | ||
282 | int r; | ||
283 | down(&lasat_info_sem); | ||
284 | r = proc_dointvec(table, write, filp, buffer, lenp, ppos); | ||
285 | if ( (!write) || r) { | ||
286 | up(&lasat_info_sem); | ||
287 | return r; | ||
288 | } | ||
289 | if (filp && filp->f_dentry) | ||
290 | { | ||
291 | if (!strcmp(filp->f_dentry->d_name.name, "prid")) | ||
292 | lasat_board_info.li_eeprom_info.prid = lasat_board_info.li_prid; | ||
293 | if (!strcmp(filp->f_dentry->d_name.name, "debugaccess")) | ||
294 | lasat_board_info.li_eeprom_info.debugaccess = lasat_board_info.li_debugaccess; | ||
295 | } | ||
296 | lasat_write_eeprom_info(); | ||
297 | up(&lasat_info_sem); | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | extern int lasat_boot_to_service; | ||
302 | |||
303 | #ifdef CONFIG_SYSCTL | ||
304 | |||
305 | static ctl_table lasat_table[] = { | ||
306 | {LASAT_CPU_HZ, "cpu-hz", &lasat_board_info.li_cpu_hz, sizeof(int), | ||
307 | 0444, NULL, &proc_dointvec, &sysctl_intvec}, | ||
308 | {LASAT_BUS_HZ, "bus-hz", &lasat_board_info.li_bus_hz, sizeof(int), | ||
309 | 0444, NULL, &proc_dointvec, &sysctl_intvec}, | ||
310 | {LASAT_MODEL, "bmid", &lasat_board_info.li_bmid, sizeof(int), | ||
311 | 0444, NULL, &proc_dointvec, &sysctl_intvec}, | ||
312 | {LASAT_PRID, "prid", &lasat_board_info.li_prid, sizeof(int), | ||
313 | 0644, NULL, &proc_lasat_eeprom_value, &sysctl_lasat_eeprom_value}, | ||
314 | #ifdef CONFIG_INET | ||
315 | {LASAT_IPADDR, "ipaddr", &lasat_board_info.li_eeprom_info.ipaddr, sizeof(int), | ||
316 | 0644, NULL, &proc_lasat_ip, &sysctl_lasat_intvec}, | ||
317 | {LASAT_NETMASK, "netmask", &lasat_board_info.li_eeprom_info.netmask, sizeof(int), | ||
318 | 0644, NULL, &proc_lasat_ip, &sysctl_lasat_intvec}, | ||
319 | {LASAT_BCAST, "bcastaddr", &lasat_bcastaddr, | ||
320 | sizeof(lasat_bcastaddr), 0600, NULL, | ||
321 | &proc_dostring, &sysctl_string}, | ||
322 | #endif | ||
323 | {LASAT_PASSWORD, "passwd_hash", &lasat_board_info.li_eeprom_info.passwd_hash, sizeof(lasat_board_info.li_eeprom_info.passwd_hash), | ||
324 | 0600, NULL, &proc_dolasatstring, &sysctl_lasatstring}, | ||
325 | {LASAT_SBOOT, "boot-service", &lasat_boot_to_service, sizeof(int), | ||
326 | 0644, NULL, &proc_dointvec, &sysctl_intvec}, | ||
327 | #ifdef CONFIG_DS1603 | ||
328 | {LASAT_RTC, "rtc", &rtctmp, sizeof(int), | ||
329 | 0644, NULL, &proc_dolasatrtc, &sysctl_lasat_rtc}, | ||
330 | #endif | ||
331 | {LASAT_NAMESTR, "namestr", &lasat_board_info.li_namestr, sizeof(lasat_board_info.li_namestr), | ||
332 | 0444, NULL, &proc_dostring, &sysctl_string}, | ||
333 | {LASAT_TYPESTR, "typestr", &lasat_board_info.li_typestr, sizeof(lasat_board_info.li_typestr), | ||
334 | 0444, NULL, &proc_dostring, &sysctl_string}, | ||
335 | {0} | ||
336 | }; | ||
337 | |||
338 | #define CTL_LASAT 1 // CTL_ANY ??? | ||
339 | static ctl_table lasat_root_table[] = { | ||
340 | { CTL_LASAT, "lasat", NULL, 0, 0555, lasat_table }, | ||
341 | { 0 } | ||
342 | }; | ||
343 | |||
344 | static int __init lasat_register_sysctl(void) | ||
345 | { | ||
346 | struct ctl_table_header *lasat_table_header; | ||
347 | |||
348 | lasat_table_header = | ||
349 | register_sysctl_table(lasat_root_table, 0); | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | __initcall(lasat_register_sysctl); | ||
355 | #endif /* CONFIG_SYSCTL */ | ||
diff --git a/arch/mips/lasat/sysctl.h b/arch/mips/lasat/sysctl.h new file mode 100644 index 000000000000..4d139d2adbdf --- /dev/null +++ b/arch/mips/lasat/sysctl.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * LASAT sysctl values | ||
3 | */ | ||
4 | |||
5 | #ifndef _LASAT_SYSCTL_H | ||
6 | #define _LASAT_SYSCTL_H | ||
7 | |||
8 | /* /proc/sys/lasat */ | ||
9 | enum { | ||
10 | LASAT_CPU_HZ=1, | ||
11 | LASAT_BUS_HZ, | ||
12 | LASAT_MODEL, | ||
13 | LASAT_PRID, | ||
14 | LASAT_IPADDR, | ||
15 | LASAT_NETMASK, | ||
16 | LASAT_BCAST, | ||
17 | LASAT_PASSWORD, | ||
18 | LASAT_SBOOT, | ||
19 | LASAT_RTC, | ||
20 | LASAT_NAMESTR, | ||
21 | LASAT_TYPESTR, | ||
22 | }; | ||
23 | |||
24 | #endif /* _LASAT_SYSCTL_H */ | ||