aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/lasat
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/lasat')
-rw-r--r--arch/mips/lasat/Makefile14
-rw-r--r--arch/mips/lasat/at93c.c148
-rw-r--r--arch/mips/lasat/at93c.h18
-rw-r--r--arch/mips/lasat/ds1603.c174
-rw-r--r--arch/mips/lasat/ds1603.h33
-rw-r--r--arch/mips/lasat/image/Makefile53
-rw-r--r--arch/mips/lasat/image/head.S31
-rw-r--r--arch/mips/lasat/image/romscript.normal22
-rw-r--r--arch/mips/lasat/interrupt.c160
-rw-r--r--arch/mips/lasat/lasatIRQ.S69
-rw-r--r--arch/mips/lasat/lasat_board.c277
-rw-r--r--arch/mips/lasat/lasat_models.h63
-rw-r--r--arch/mips/lasat/picvue.c240
-rw-r--r--arch/mips/lasat/picvue.h48
-rw-r--r--arch/mips/lasat/picvue_proc.c186
-rw-r--r--arch/mips/lasat/prom.c143
-rw-r--r--arch/mips/lasat/prom.h6
-rw-r--r--arch/mips/lasat/reset.c67
-rw-r--r--arch/mips/lasat/setup.c192
-rw-r--r--arch/mips/lasat/sysctl.c355
-rw-r--r--arch/mips/lasat/sysctl.h24
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
5obj-y += reset.o setup.o prom.o lasat_board.o \
6 at93c.o interrupt.o lasatIRQ.o
7
8obj-$(CONFIG_LASAT_SYSCTL) += sysctl.o
9obj-$(CONFIG_DS1603) += ds1603.o
10obj-$(CONFIG_PICVUE) += picvue.o
11obj-$(CONFIG_PICVUE_PROC) += picvue_proc.o
12
13clean:
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
22struct at93c_defs *at93c;
23
24static void at93c_reg_write(u32 val)
25{
26 *at93c->reg = val;
27}
28
29static u32 at93c_reg_read(void)
30{
31 u32 tmp = *at93c->reg;
32 return tmp;
33}
34
35static u32 at93c_datareg_read(void)
36{
37 u32 tmp = *at93c->rdata_reg;
38 return tmp;
39}
40
41static 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
49static 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
62static 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
71static 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
83static 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
95static 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
101static void at93c_end_op(void)
102{
103 at93c_reg_write(at93c_reg_read() & ~at93c->cs);
104 lasat_ndelay(250);
105}
106
107static void at93c_wait(void)
108{
109 at93c_init_op();
110 while (!at93c_read_databit())
111 ;
112 at93c_end_op();
113};
114
115static void at93c_disable_wp(void)
116{
117 at93c_init_op();
118 at93c_write_bits(AT93C_WENCMD, 10);
119 at93c_end_op();
120}
121
122static void at93c_enable_wp(void)
123{
124 at93c_init_op();
125 at93c_write_bits(AT93C_WDSCMD, 10);
126 at93c_end_op();
127}
128
129u8 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
139void 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
8extern 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
17u8 at93c_read(u8 addr);
18void 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
20struct ds_defs *ds1603 = NULL;
21
22/* HW specific register functions */
23static void rtc_reg_write(unsigned long val)
24{
25 *ds1603->reg = val;
26}
27
28static unsigned long rtc_reg_read(void)
29{
30 unsigned long tmp = *ds1603->reg;
31 return tmp;
32}
33
34static unsigned long rtc_datareg_read(void)
35{
36 unsigned long tmp = *ds1603->data_reg;
37 return tmp;
38}
39
40static void rtc_nrst_high(void)
41{
42 rtc_reg_write(rtc_reg_read() | ds1603->rst);
43}
44
45static void rtc_nrst_low(void)
46{
47 rtc_reg_write(rtc_reg_read() & ~ds1603->rst);
48}
49
50static 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
64static 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
79static 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
89static 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
99static 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
109static 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
122static 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
131static void rtc_end_op(void)
132{
133 rtc_nrst_low();
134 lasat_ndelay(1000);
135}
136
137/* interface */
138unsigned 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
148int 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
158void 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
166void ds1603_disable(void)
167{
168 ds1603_set_trimmer(TRIMMER_DISABLE_RTC);
169}
170
171void 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
10struct 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
21extern struct ds_defs *ds1603;
22
23unsigned long ds1603_read(void);
24int ds1603_set(unsigned long);
25void ds1603_set_trimmer(unsigned int);
26void ds1603_enable(void);
27void ds1603_disable(void);
28void 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
9ifndef Version
10 Version = "$(USER)-test"
11endif
12
13MKLASATIMG = mklasatimg
14MKLASATIMG_ARCH = mq2,mqpro,sp100,sp200
15KERNEL_IMAGE = $(TOPDIR)/vmlinux
16KERNEL_START = $(shell $(NM) $(KERNEL_IMAGE) | grep " _text" | cut -f1 -d\ )
17KERNEL_ENTRY = $(shell $(NM) $(KERNEL_IMAGE) | grep kernel_entry | cut -f1 -d\ )
18
19LDSCRIPT= -L$(obj) -Tromscript.normal
20
21HEAD_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
29OBJECTS = head.o kImage.o
30
31rom.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
52clean:
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
26reldate:
27 .word TIMESTAMP
28
29 .org 0x50
30release:
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 @@
1OUTPUT_ARCH(mips)
2
3SECTIONS
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
32static volatile int *lasat_int_status = NULL;
33static volatile int *lasat_int_mask = NULL;
34static volatile int lasat_int_mask_shift;
35
36extern asmlinkage void lasatIRQ(void);
37
38void 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
47void 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
56static 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
67static 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
73static 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
84static 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
97static unsigned long (* get_int_status)(void);
98
99static unsigned long get_int_status_100(void)
100{
101 return *lasat_int_status & *lasat_int_mask;
102}
103
104static 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
113void 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
128void __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
501:
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
581:
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
35struct lasat_info lasat_board_info;
36
37void update_bcastaddr(void);
38
39int 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}
48int 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
58static 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
93int 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
264void 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
5typedef struct product_info_t {
6 const char *pi_name;
7 const char *pi_type;
8} product_info_t;
9
10typedef 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 */
18static 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 */
26static const char txt_en_mq[] = "Masquerade";
27static const char txt_en_sp[] = "Safepipe";
28
29static 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 */
60static 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
23struct pvc_defs *picvue = NULL;
24
25DECLARE_MUTEX(pvc_sem);
26
27static void pvc_reg_write(u32 val)
28{
29 *picvue->reg = val;
30}
31
32static u32 pvc_reg_read(void)
33{
34 u32 tmp = *picvue->reg;
35 return tmp;
36}
37
38static 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
50static 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
64static 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
79static 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
94static 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
113void 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
127void 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
140void 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
151int 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
174static 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)
183static 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)
193void 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
203void pvc_move(u8 cmd)
204{
205 pvc_write(MOVE_CMD | (cmd & (DISPLAY|RIGHT)), MODE_INST);
206}
207
208#define CLEAR_CMD 0x1
209void pvc_clear(void)
210{
211 pvc_write(CLEAR_CMD, MODE_INST);
212}
213
214#define HOME_CMD 0x2
215void pvc_home(void)
216{
217 pvc_write(HOME_CMD, MODE_INST);
218}
219
220int 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
239module_init(pvc_init);
240MODULE_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
9struct 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
18extern 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
25void pvc_write_string(const unsigned char *str, u8 addr, int line);
26void pvc_write_string_centered(const unsigned char *str, int line);
27void pvc_dump_string(const unsigned char *str);
28
29#define BM_SIZE 8
30#define MAX_PROGRAMMABLE_CHARS 8
31int pvc_program_cg(int charnum, u8 bitmap[BM_SIZE]);
32
33void 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
39void pvc_move(u8 cmd);
40#define DISPLAY (1 << 3)
41#define CURSOR 0
42#define RIGHT (1 << 2)
43#define LEFT 0
44
45void pvc_clear(void);
46void pvc_home(void);
47
48extern 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
19static char pvc_lines[PVC_NLINES][PVC_LINELEN+1];
20static int pvc_linedata[PVC_NLINES];
21static struct proc_dir_entry *pvc_display_dir;
22static char *pvc_linename[PVC_NLINES] = {"line1", "line2"};
23#define DISPLAY_DIR_NAME "display"
24static int scroll_dir = 0, scroll_interval = 0;
25
26static struct timer_list timer;
27
28static 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
36static DECLARE_TASKLET(pvc_display_tasklet, &pvc_display, 0);
37
38static 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
57static 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
84static 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
112static 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
126void 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
137static 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
148static 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;
179error:
180 pvc_proc_cleanup();
181 return -ENOMEM;
182}
183
184module_init(pvc_proc_init);
185module_exit(pvc_proc_cleanup);
186MODULE_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
26static void null_prom_printf(const char * fmt, ...)
27{
28}
29
30static void null_prom_display(const char *string, int pos, int clear)
31{
32}
33
34static void null_prom_monitor(void)
35{
36}
37
38static void null_prom_putc(char c)
39{
40}
41
42/* these are functions provided by the bootloader */
43static void (* prom_putc)(char c) = null_prom_putc;
44void (* prom_printf)(const char * fmt, ...) = null_prom_printf;
45void (* prom_display)(const char *string, int pos, int clear) =
46 null_prom_display;
47void (* prom_monitor)(void) = null_prom_monitor;
48
49unsigned int lasat_ndelay_divider;
50
51#define PROM_PRINTFBUF_SIZE 256
52static char prom_printfbuf[PROM_PRINTFBUF_SIZE];
53
54static 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
76static 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
89static 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
96void __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
135unsigned long __init prom_free_prom_memory(void)
136{
137 return 0;
138}
139
140const 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
3extern void (* prom_display)(const char *string, int pos, int clear);
4extern void (* prom_monitor)(void);
5extern 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
28static void lasat_machine_restart(char *command);
29static void lasat_machine_halt(void);
30
31/* Used to set machine to boot in service mode via /proc interface */
32int lasat_boot_to_service = 0;
33
34static 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"
48static 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
62void 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
53int lasat_command_line = 0;
54void lasatint_init(void);
55
56extern void lasat_reboot_setup(void);
57extern void pcisetup(void);
58extern void edhac_init(void *, void *, void *);
59extern void addrflt_init(void);
60
61struct 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
66struct lasat_misc *lasat_misc = NULL;
67
68#ifdef CONFIG_DS1603
69static 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"
81static 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
89static 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
101static 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
108static struct notifier_block lasat_panic_block[] =
109{
110 { lasat_panic_display, NULL, INT_MAX },
111 { lasat_panic_prom_monitor, NULL, INT_MIN }
112};
113
114static void lasat_time_init(void)
115{
116 mips_hpt_frequency = lasat_board_info.li_cpu_hz / 2;
117}
118
119static 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
130void __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
158static 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
192early_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
38static DECLARE_MUTEX(lasat_info_sem);
39
40/* Strategy function to write EEPROM after changing string entry */
41int 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 */
62int 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 */
78int 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
93static int rtctmp;
94
95#ifdef CONFIG_DS1603
96/* proc function to read/write RealTime Clock */
97int 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 */
120int 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 */
140int 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
163static char lasat_bcastaddr[16];
164
165void 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
180static char proc_lasat_ipbuf[32];
181/* Parsing of IP address */
182int 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
252static 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
279int 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
301extern int lasat_boot_to_service;
302
303#ifdef CONFIG_SYSCTL
304
305static 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 ???
339static ctl_table lasat_root_table[] = {
340 { CTL_LASAT, "lasat", NULL, 0, 0555, lasat_table },
341 { 0 }
342};
343
344static 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 */
9enum {
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 */