aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sn
diff options
context:
space:
mode:
authorPatrick Gefre <pfg@sgi.com>2006-01-14 16:20:40 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-14 21:25:20 -0500
commit2d0cfb527944c2cfee2cffab14f52d483e329fcf (patch)
treeb2e3340b52d83b51674f3782a208850d53d3d24d /drivers/sn
parent7170be5f586b59bdcdab082778a5d9203ba7b667 (diff)
[PATCH] Altix: ioc3 serial support
Add driver support for a 2 port PCI IOC3-based serial card on Altix boxes: This is a re-submission. On the original submission I was asked to organize the code so that the MIPS ioc3 ethernet and serial parts could be used with this driver. Stanislaw Skowronek was kind enough to provide the shim layer for this - thanks Stanislaw. This patch includes the shim layer and the Altix PCI ioc3 serial driver. The MIPS merged ioc3 ethernet and serial support is forthcoming. Signed-off-by: Patrick Gefre <pfg@sgi.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/sn')
-rw-r--r--drivers/sn/Kconfig14
-rw-r--r--drivers/sn/Makefile1
-rw-r--r--drivers/sn/ioc3.c851
3 files changed, 866 insertions, 0 deletions
diff --git a/drivers/sn/Kconfig b/drivers/sn/Kconfig
index 13b8d249da5c..d95265b187a3 100644
--- a/drivers/sn/Kconfig
+++ b/drivers/sn/Kconfig
@@ -17,4 +17,18 @@ config SGI_IOC4
17 If you have an SGI Altix with an IOC4-based 17 If you have an SGI Altix with an IOC4-based
18 I/O controller say Y. Otherwise say N. 18 I/O controller say Y. Otherwise say N.
19 19
20config SGI_IOC3
21 tristate "SGI IOC3 Base IO support"
22 depends on (IA64_GENERIC || IA64_SGI_SN2)
23 default m
24 ---help---
25 This option enables basic support for the SGI IOC3-based Base IO
26 controller card. This option does not enable any specific
27 functions on such a card, but provides necessary infrastructure
28 for other drivers to utilize.
29
30 If you have an SGI Altix with an IOC3-based
31 I/O controller or a PCI IOC3 serial card say Y.
32 Otherwise say N.
33
20endmenu 34endmenu
diff --git a/drivers/sn/Makefile b/drivers/sn/Makefile
index c2a284185372..2cda011597c0 100644
--- a/drivers/sn/Makefile
+++ b/drivers/sn/Makefile
@@ -4,3 +4,4 @@
4# 4#
5 5
6obj-$(CONFIG_SGI_IOC4) += ioc4.o 6obj-$(CONFIG_SGI_IOC4) += ioc4.o
7obj-$(CONFIG_SGI_IOC3) += ioc3.o
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c
new file mode 100644
index 000000000000..aaa009f4a7bf
--- /dev/null
+++ b/drivers/sn/ioc3.c
@@ -0,0 +1,851 @@
1/*
2 * SGI IOC3 master driver and IRQ demuxer
3 *
4 * Copyright (c) 2005 Stanislaw Skowronek <skylark@linux-mips.org>
5 * Heavily based on similar work by:
6 * Brent Casavant <bcasavan@sgi.com> - IOC4 master driver
7 * Pat Gefre <pfg@sgi.com> - IOC3 serial port IRQ demuxer
8 */
9
10#include <linux/config.h>
11#include <linux/errno.h>
12#include <linux/module.h>
13#include <linux/pci.h>
14#include <linux/interrupt.h>
15#include <linux/spinlock.h>
16#include <linux/delay.h>
17#include <linux/ioc3.h>
18#include <linux/rwsem.h>
19
20#define IOC3_PCI_SIZE 0x100000
21
22static LIST_HEAD(ioc3_devices);
23static int ioc3_counter;
24static DECLARE_RWSEM(ioc3_devices_rwsem);
25
26static struct ioc3_submodule *ioc3_submodules[IOC3_MAX_SUBMODULES];
27static struct ioc3_submodule *ioc3_ethernet;
28static rwlock_t ioc3_submodules_lock = RW_LOCK_UNLOCKED;
29
30/* NIC probing code */
31
32#define GPCR_MLAN_EN 0x00200000 /* enable MCR to pin 8 */
33
34static inline unsigned mcr_pack(unsigned pulse, unsigned sample)
35{
36 return (pulse << 10) | (sample << 2);
37}
38
39static int nic_wait(struct ioc3_driver_data *idd)
40{
41 volatile unsigned mcr;
42
43 do {
44 mcr = (volatile unsigned)idd->vma->mcr;
45 } while (!(mcr & 2));
46
47 return mcr & 1;
48}
49
50static int nic_reset(struct ioc3_driver_data *idd)
51{
52 int presence;
53 unsigned long flags;
54
55 local_irq_save(flags);
56 idd->vma->mcr = mcr_pack(500, 65);
57 presence = nic_wait(idd);
58 local_irq_restore(flags);
59
60 udelay(500);
61
62 return presence;
63}
64
65static inline int nic_read_bit(struct ioc3_driver_data *idd)
66{
67 int result;
68 unsigned long flags;
69
70 local_irq_save(flags);
71 idd->vma->mcr = mcr_pack(6, 13);
72 result = nic_wait(idd);
73 local_irq_restore(flags);
74
75 udelay(500);
76
77 return result;
78}
79
80static inline void nic_write_bit(struct ioc3_driver_data *idd, int bit)
81{
82 if (bit)
83 idd->vma->mcr = mcr_pack(6, 110);
84 else
85 idd->vma->mcr = mcr_pack(80, 30);
86
87 nic_wait(idd);
88}
89
90static unsigned nic_read_byte(struct ioc3_driver_data *idd)
91{
92 unsigned result = 0;
93 int i;
94
95 for (i = 0; i < 8; i++)
96 result = (result >> 1) | (nic_read_bit(idd) << 7);
97
98 return result;
99}
100
101static void nic_write_byte(struct ioc3_driver_data *idd, int byte)
102{
103 int i, bit;
104
105 for (i = 8; i; i--) {
106 bit = byte & 1;
107 byte >>= 1;
108
109 nic_write_bit(idd, bit);
110 }
111}
112
113static unsigned long
114nic_find(struct ioc3_driver_data *idd, int *last, unsigned long addr)
115{
116 int a, b, index, disc;
117
118 nic_reset(idd);
119
120 /* Search ROM. */
121 nic_write_byte(idd, 0xF0);
122
123 /* Algorithm from ``Book of iButton Standards''. */
124 for (index = 0, disc = 0; index < 64; index++) {
125 a = nic_read_bit(idd);
126 b = nic_read_bit(idd);
127
128 if (a && b) {
129 printk(KERN_WARNING "IOC3 NIC search failed.\n");
130 *last = 0;
131 return 0;
132 }
133
134 if (!a && !b) {
135 if (index == *last) {
136 addr |= 1UL << index;
137 } else if (index > *last) {
138 addr &= ~(1UL << index);
139 disc = index;
140 } else if ((addr & (1UL << index)) == 0)
141 disc = index;
142 nic_write_bit(idd, (addr>>index)&1);
143 continue;
144 } else {
145 if (a)
146 addr |= 1UL << index;
147 else
148 addr &= ~(1UL << index);
149 nic_write_bit(idd, a);
150 continue;
151 }
152 }
153 *last = disc;
154 return addr;
155}
156
157static void nic_addr(struct ioc3_driver_data *idd, unsigned long addr)
158{
159 int index;
160
161 nic_reset(idd);
162 nic_write_byte(idd, 0xF0);
163 for (index = 0; index < 64; index++) {
164 nic_read_bit(idd);
165 nic_read_bit(idd);
166 nic_write_bit(idd, (addr>>index)&1);
167 }
168}
169
170static void crc16_byte(unsigned int *crc, unsigned char db)
171{
172 int i;