aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS2
-rw-r--r--arch/arm/Kconfig2
-rw-r--r--arch/arm/lib/Makefile1
-rw-r--r--arch/arm/mach-rpc/Makefile3
-rw-r--r--arch/arm/mach-rpc/dma.c97
-rw-r--r--arch/arm/mach-rpc/ecard-loader.S (renamed from arch/arm/lib/ecard.S)0
-rw-r--r--arch/arm/mach-rpc/ecard.c32
-rw-r--r--arch/arm/mach-rpc/floppydma.S (renamed from arch/arm/lib/floppydma.S)0
-rw-r--r--arch/arm/mach-rpc/include/mach/uncompress.h23
-rw-r--r--arch/arm/mach-rpc/io-acorn.S (renamed from arch/arm/lib/io-acorn.S)0
-rw-r--r--arch/arm/mach-rpc/irq.c136
-rw-r--r--arch/arm/mach-rpc/time.c38
12 files changed, 161 insertions, 173 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 429c6c624861..bff3200f0e82 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1229,7 +1229,7 @@ F: include/uapi/drm/panfrost_drm.h
1229ARM MFM AND FLOPPY DRIVERS 1229ARM MFM AND FLOPPY DRIVERS
1230M: Ian Molton <spyro@f2s.com> 1230M: Ian Molton <spyro@f2s.com>
1231S: Maintained 1231S: Maintained
1232F: arch/arm/lib/floppydma.S 1232F: arch/arm/mach-rpc/floppydma.S
1233F: arch/arm/include/asm/floppy.h 1233F: arch/arm/include/asm/floppy.h
1234 1234
1235ARM PMU PROFILING AND DEBUGGING 1235ARM PMU PROFILING AND DEBUGGING
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 70aebb6d2905..fe31c97c74ea 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -528,7 +528,7 @@ config ARCH_RPC
528 select ARCH_ACORN 528 select ARCH_ACORN
529 select ARCH_MAY_HAVE_PC_FDC 529 select ARCH_MAY_HAVE_PC_FDC
530 select ARCH_SPARSEMEM_ENABLE 530 select ARCH_SPARSEMEM_ENABLE
531 select ARCH_USES_GETTIMEOFFSET 531 select ARM_HAS_SG_CHAIN
532 select CPU_SA110 532 select CPU_SA110
533 select FIQ 533 select FIQ
534 select HAVE_IDE 534 select HAVE_IDE
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 0bff0176db2c..b25c54585048 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -31,7 +31,6 @@ else
31endif 31endif
32 32
33ifeq ($(CONFIG_ARCH_RPC),y) 33ifeq ($(CONFIG_ARCH_RPC),y)
34 lib-y += ecard.o io-acorn.o floppydma.o
35 AFLAGS_delay-loop.o += -march=armv4 34 AFLAGS_delay-loop.o += -march=armv4
36endif 35endif
37 36
diff --git a/arch/arm/mach-rpc/Makefile b/arch/arm/mach-rpc/Makefile
index 056ef5460290..90a645a18444 100644
--- a/arch/arm/mach-rpc/Makefile
+++ b/arch/arm/mach-rpc/Makefile
@@ -5,4 +5,5 @@
5 5
6# Object file lists. 6# Object file lists.
7 7
8obj-y := dma.o ecard.o fiq.o irq.o riscpc.o time.o 8obj-y :=dma.o ecard.o ecard-loader.o fiq.o floppydma.o io-acorn.o irq.o \
9 riscpc.o time.o
diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c
index f2703ca17954..e221f6bb935f 100644
--- a/arch/arm/mach-rpc/dma.c
+++ b/arch/arm/mach-rpc/dma.c
@@ -27,10 +27,11 @@
27 27
28struct iomd_dma { 28struct iomd_dma {
29 struct dma_struct dma; 29 struct dma_struct dma;
30 unsigned int state; 30 void __iomem *base; /* Controller base address */
31 unsigned long base; /* Controller base address */
32 int irq; /* Controller IRQ */ 31 int irq; /* Controller IRQ */
33 struct scatterlist cur_sg; /* Current controller buffer */ 32 unsigned int state;
33 dma_addr_t cur_addr;
34 unsigned int cur_len;
34 dma_addr_t dma_addr; 35 dma_addr_t dma_addr;
35 unsigned int dma_len; 36 unsigned int dma_len;
36}; 37};
@@ -53,13 +54,13 @@ typedef enum {
53#define CR (IOMD_IO0CR - IOMD_IO0CURA) 54#define CR (IOMD_IO0CR - IOMD_IO0CURA)
54#define ST (IOMD_IO0ST - IOMD_IO0CURA) 55#define ST (IOMD_IO0ST - IOMD_IO0CURA)
55 56
56static void iomd_get_next_sg(struct scatterlist *sg, struct iomd_dma *idma) 57static void iomd_get_next_sg(struct iomd_dma *idma)
57{ 58{
58 unsigned long end, offset, flags = 0; 59 unsigned long end, offset, flags = 0;
59 60
60 if (idma->dma.sg) { 61 if (idma->dma.sg) {
61 sg->dma_address = idma->dma_addr; 62 idma->cur_addr = idma->dma_addr;
62 offset = sg->dma_address & ~PAGE_MASK; 63 offset = idma->cur_addr & ~PAGE_MASK;
63 64
64 end = offset + idma->dma_len; 65 end = offset + idma->dma_len;
65 66
@@ -69,7 +70,7 @@ static void iomd_get_next_sg(struct scatterlist *sg, struct iomd_dma *idma)
69 if (offset + TRANSFER_SIZE >= end) 70 if (offset + TRANSFER_SIZE >= end)
70 flags |= DMA_END_L; 71 flags |= DMA_END_L;
71 72
72 sg->length = end - TRANSFER_SIZE; 73 idma->cur_len = end - TRANSFER_SIZE;
73 74
74 idma->dma_len -= end - offset; 75 idma->dma_len -= end - offset;
75 idma->dma_addr += end - offset; 76 idma->dma_addr += end - offset;
@@ -87,52 +88,49 @@ static void iomd_get_next_sg(struct scatterlist *sg, struct iomd_dma *idma)
87 } 88 }
88 } else { 89 } else {
89 flags = DMA_END_S | DMA_END_L; 90 flags = DMA_END_S | DMA_END_L;
90 sg->dma_address = 0; 91 idma->cur_addr = 0;
91 sg->length = 0; 92 idma->cur_len = 0;
92 } 93 }
93 94
94 sg->length |= flags; 95 idma->cur_len |= flags;
95} 96}
96 97
97static irqreturn_t iomd_dma_handle(int irq, void *dev_id) 98static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
98{ 99{
99 struct iomd_dma *idma = dev_id; 100 struct iomd_dma *idma = dev_id;
100 unsigned long base = idma->base; 101 void __iomem *base = idma->base;
102 unsigned int state = idma->state;
103 unsigned int status, cur, end;
101 104
102 do { 105 do {
103 unsigned int status; 106 status = readb(base + ST);
104
105 status = iomd_readb(base + ST);
106 if (!(status & DMA_ST_INT)) 107 if (!(status & DMA_ST_INT))
107 return IRQ_HANDLED; 108 goto out;
108 109
109 if ((idma->state ^ status) & DMA_ST_AB) 110 if ((state ^ status) & DMA_ST_AB)
110 iomd_get_next_sg(&idma->cur_sg, idma); 111 iomd_get_next_sg(idma);
111 112
112 switch (status & (DMA_ST_OFL | DMA_ST_AB)) { 113 // This efficiently implements state = OFL != AB ? AB : 0
113 case DMA_ST_OFL: /* OIA */ 114 state = ((status >> 2) ^ status) & DMA_ST_AB;
114 case DMA_ST_AB: /* .IB */ 115 if (state) {
115 iomd_writel(idma->cur_sg.dma_address, base + CURA); 116 cur = CURA;
116 iomd_writel(idma->cur_sg.length, base + ENDA); 117 end = ENDA;
117 idma->state = DMA_ST_AB; 118 } else {
118 break; 119 cur = CURB;
119 120 end = ENDB;
120 case DMA_ST_OFL | DMA_ST_AB: /* OIB */
121 case 0: /* .IA */
122 iomd_writel(idma->cur_sg.dma_address, base + CURB);
123 iomd_writel(idma->cur_sg.length, base + ENDB);
124 idma->state = 0;
125 break;
126 } 121 }
122 writel(idma->cur_addr, base + cur);
123 writel(idma->cur_len, base + end);
127 124
128 if (status & DMA_ST_OFL && 125 if (status & DMA_ST_OFL &&
129 idma->cur_sg.length == (DMA_END_S|DMA_END_L)) 126 idma->cur_len == (DMA_END_S|DMA_END_L))
130 break; 127 break;
131 } while (1); 128 } while (1);
132 129
133 idma->state = ~DMA_ST_AB; 130 state = ~DMA_ST_AB;
134 disable_irq(irq); 131 disable_irq_nosync(irq);
135 132out:
133 idma->state = state;
136 return IRQ_HANDLED; 134 return IRQ_HANDLED;
137} 135}
138 136
@@ -160,7 +158,7 @@ static struct device isa_dma_dev = {
160static void iomd_enable_dma(unsigned int chan, dma_t *dma) 158static void iomd_enable_dma(unsigned int chan, dma_t *dma)
161{ 159{
162 struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma); 160 struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
163 unsigned long dma_base = idma->base; 161 void __iomem *base = idma->base;
164 unsigned int ctrl = TRANSFER_SIZE | DMA_CR_E; 162 unsigned int ctrl = TRANSFER_SIZE | DMA_CR_E;
165 163
166 if (idma->dma.invalid) { 164 if (idma->dma.invalid) {
@@ -180,27 +178,30 @@ static void iomd_enable_dma(unsigned int chan, dma_t *dma)
180 DMA_FROM_DEVICE : DMA_TO_DEVICE); 178 DMA_FROM_DEVICE : DMA_TO_DEVICE);
181 } 179 }
182 180
183 iomd_writeb(DMA_CR_C, dma_base + CR); 181 idma->dma_addr = idma->dma.sg->dma_address;
182 idma->dma_len = idma->dma.sg->length;
183
184 writeb(DMA_CR_C, base + CR);
184 idma->state = DMA_ST_AB; 185 idma->state = DMA_ST_AB;
185 } 186 }
186 187
187 if (idma->dma.dma_mode == DMA_MODE_READ) 188 if (idma->dma.dma_mode == DMA_MODE_READ)
188 ctrl |= DMA_CR_D; 189 ctrl |= DMA_CR_D;
189 190
190 iomd_writeb(ctrl, dma_base + CR); 191 writeb(ctrl, base + CR);
191 enable_irq(idma->irq); 192 enable_irq(idma->irq);
192} 193}
193 194
194static void iomd_disable_dma(unsigned int chan, dma_t *dma) 195static void iomd_disable_dma(unsigned int chan, dma_t *dma)
195{ 196{
196 struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma); 197 struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
197 unsigned long dma_base = idma->base; 198 void __iomem *base = idma->base;
198 unsigned long flags; 199 unsigned long flags;
199 200
200 local_irq_save(flags); 201 local_irq_save(flags);
201 if (idma->state != ~DMA_ST_AB) 202 if (idma->state != ~DMA_ST_AB)
202 disable_irq(idma->irq); 203 disable_irq(idma->irq);
203 iomd_writeb(0, dma_base + CR); 204 writeb(0, base + CR);
204 local_irq_restore(flags); 205 local_irq_restore(flags);
205} 206}
206 207
@@ -363,17 +364,17 @@ static int __init rpc_dma_init(void)
363 */ 364 */
364 iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT); 365 iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);
365 366
366 iomd_dma[DMA_0].base = IOMD_IO0CURA; 367 iomd_dma[DMA_0].base = IOMD_BASE + IOMD_IO0CURA;
367 iomd_dma[DMA_0].irq = IRQ_DMA0; 368 iomd_dma[DMA_0].irq = IRQ_DMA0;
368 iomd_dma[DMA_1].base = IOMD_IO1CURA; 369 iomd_dma[DMA_1].base = IOMD_BASE + IOMD_IO1CURA;
369 iomd_dma[DMA_1].irq = IRQ_DMA1; 370 iomd_dma[DMA_1].irq = IRQ_DMA1;
370 iomd_dma[DMA_2].base = IOMD_IO2CURA; 371 iomd_dma[DMA_2].base = IOMD_BASE + IOMD_IO2CURA;
371 iomd_dma[DMA_2].irq = IRQ_DMA2; 372 iomd_dma[DMA_2].irq = IRQ_DMA2;
372 iomd_dma[DMA_3].base = IOMD_IO3CURA; 373 iomd_dma[DMA_3].base = IOMD_BASE + IOMD_IO3CURA;
373 iomd_dma[DMA_3].irq = IRQ_DMA3; 374 iomd_dma[DMA_3].irq = IRQ_DMA3;
374 iomd_dma[DMA_S0].base = IOMD_SD0CURA; 375 iomd_dma[DMA_S0].base = IOMD_BASE + IOMD_SD0CURA;
375 iomd_dma[DMA_S0].irq = IRQ_DMAS0; 376 iomd_dma[DMA_S0].irq = IRQ_DMAS0;
376 iomd_dma[DMA_S1].base = IOMD_SD1CURA; 377 iomd_dma[DMA_S1].base = IOMD_BASE + IOMD_SD1CURA;
377 iomd_dma[DMA_S1].irq = IRQ_DMAS1; 378 iomd_dma[DMA_S1].irq = IRQ_DMAS1;
378 379
379 for (i = DMA_0; i <= DMA_S1; i++) { 380 for (i = DMA_0; i <= DMA_S1; i++) {
diff --git a/arch/arm/lib/ecard.S b/arch/arm/mach-rpc/ecard-loader.S
index e6057fa851bb..e6057fa851bb 100644
--- a/arch/arm/lib/ecard.S
+++ b/arch/arm/mach-rpc/ecard-loader.S
diff --git a/arch/arm/mach-rpc/ecard.c b/arch/arm/mach-rpc/ecard.c
index 04b2f22c2739..eec5ecd6e948 100644
--- a/arch/arm/mach-rpc/ecard.c
+++ b/arch/arm/mach-rpc/ecard.c
@@ -70,17 +70,21 @@ struct expcard_blacklist {
70 unsigned short manufacturer; 70 unsigned short manufacturer;
71 unsigned short product; 71 unsigned short product;
72 const char *type; 72 const char *type;
73 void (*init)(ecard_t *ec);
73}; 74};
74 75
75static ecard_t *cards; 76static ecard_t *cards;
76static ecard_t *slot_to_expcard[MAX_ECARDS]; 77static ecard_t *slot_to_expcard[MAX_ECARDS];
77static unsigned int ectcr; 78static unsigned int ectcr;
78 79
80static void atomwide_3p_quirk(ecard_t *ec);
81
79/* List of descriptions of cards which don't have an extended 82/* List of descriptions of cards which don't have an extended
80 * identification, or chunk directories containing a description. 83 * identification, or chunk directories containing a description.
81 */ 84 */
82static struct expcard_blacklist __initdata blacklist[] = { 85static struct expcard_blacklist __initdata blacklist[] = {
83 { MANU_ACORN, PROD_ACORN_ETHER1, "Acorn Ether1" } 86 { MANU_ACORN, PROD_ACORN_ETHER1, "Acorn Ether1" },
87 { MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL, NULL, atomwide_3p_quirk },
84}; 88};
85 89
86asmlinkage extern int 90asmlinkage extern int
@@ -496,18 +500,21 @@ static void ecard_dump_irq_state(void)
496 printk("Expansion card IRQ state:\n"); 500 printk("Expansion card IRQ state:\n");
497 501
498 for (ec = cards; ec; ec = ec->next) { 502 for (ec = cards; ec; ec = ec->next) {
503 const char *claimed;
504
499 if (ec->slot_no == 8) 505 if (ec->slot_no == 8)
500 continue; 506 continue;
501 507
502 printk(" %d: %sclaimed, ", 508 claimed = ec->claimed ? "" : "not ";
503 ec->slot_no, ec->claimed ? "" : "not ");
504 509
505 if (ec->ops && ec->ops->irqpending && 510 if (ec->ops && ec->ops->irqpending &&
506 ec->ops != &ecard_default_ops) 511 ec->ops != &ecard_default_ops)
507 printk("irq %spending\n", 512 printk(" %d: %sclaimed irq %spending\n",
513 ec->slot_no, claimed,
508 ec->ops->irqpending(ec) ? "" : "not "); 514 ec->ops->irqpending(ec) ? "" : "not ");
509 else 515 else
510 printk("irqaddr %p, mask = %02X, status = %02X\n", 516 printk(" %d: %sclaimed irqaddr %p, mask = %02X, status = %02X\n",
517 ec->slot_no, claimed,
511 ec->irqaddr, ec->irqmask, readb(ec->irqaddr)); 518 ec->irqaddr, ec->irqmask, readb(ec->irqaddr));
512 } 519 }
513} 520}
@@ -868,6 +875,16 @@ void __iomem *ecardm_iomap(struct expansion_card *ec, unsigned int res,
868} 875}
869EXPORT_SYMBOL(ecardm_iomap); 876EXPORT_SYMBOL(ecardm_iomap);
870 877
878static void atomwide_3p_quirk(ecard_t *ec)
879{
880 void __iomem *addr = __ecard_address(ec, ECARD_IOC, ECARD_SYNC);
881 unsigned int i;
882
883 /* Disable interrupts on each port */
884 for (i = 0x2000; i <= 0x2800; i += 0x0400)
885 writeb(0, addr + i + 4);
886}
887
871/* 888/*
872 * Probe for an expansion card. 889 * Probe for an expansion card.
873 * 890 *
@@ -924,7 +941,10 @@ static int __init ecard_probe(int slot, unsigned irq, card_type_t type)
924 for (i = 0; i < ARRAY_SIZE(blacklist); i++) 941 for (i = 0; i < ARRAY_SIZE(blacklist); i++)
925 if (blacklist[i].manufacturer == ec->cid.manufacturer && 942 if (blacklist[i].manufacturer == ec->cid.manufacturer &&
926 blacklist[i].product == ec->cid.product) { 943 blacklist[i].product == ec->cid.product) {
927 ec->card_desc = blacklist[i].type; 944 if (blacklist[i].type)
945 ec->card_desc = blacklist[i].type;
946 if (blacklist[i].init)
947 blacklist[i].init(ec);
928 break; 948 break;
929 } 949 }
930 950
diff --git a/arch/arm/lib/floppydma.S b/arch/arm/mach-rpc/floppydma.S
index de68d3b343e3..de68d3b343e3 100644
--- a/arch/arm/lib/floppydma.S
+++ b/arch/arm/mach-rpc/floppydma.S
diff --git a/arch/arm/mach-rpc/include/mach/uncompress.h b/arch/arm/mach-rpc/include/mach/uncompress.h
index 654a6f3f2547..edc1961e8d1e 100644
--- a/arch/arm/mach-rpc/include/mach/uncompress.h
+++ b/arch/arm/mach-rpc/include/mach/uncompress.h
@@ -118,29 +118,22 @@ static void arch_decomp_setup(void)
118 struct tag *t = (struct tag *)params; 118 struct tag *t = (struct tag *)params;
119 unsigned int nr_pages = 0, page_size = PAGE_SIZE; 119 unsigned int nr_pages = 0, page_size = PAGE_SIZE;
120 120
121 if (t->hdr.tag == ATAG_CORE) 121 if (t->hdr.tag == ATAG_CORE) {
122 { 122 for (; t->hdr.size; t = tag_next(t)) {
123 for (; t->hdr.size; t = tag_next(t)) 123 if (t->hdr.tag == ATAG_VIDEOTEXT) {
124 {
125 if (t->hdr.tag == ATAG_VIDEOTEXT)
126 {
127 video_num_rows = t->u.videotext.video_lines; 124 video_num_rows = t->u.videotext.video_lines;
128 video_num_cols = t->u.videotext.video_cols; 125 video_num_cols = t->u.videotext.video_cols;
129 bytes_per_char_h = t->u.videotext.video_points;
130 bytes_per_char_v = t->u.videotext.video_points;
131 video_x = t->u.videotext.x; 126 video_x = t->u.videotext.x;
132 video_y = t->u.videotext.y; 127 video_y = t->u.videotext.y;
133 } 128 } else if (t->hdr.tag == ATAG_VIDEOLFB) {
134 129 bytes_per_char_h = t->u.videolfb.lfb_depth;
135 if (t->hdr.tag == ATAG_MEM) 130 bytes_per_char_v = 8;
136 { 131 } else if (t->hdr.tag == ATAG_MEM) {
137 page_size = PAGE_SIZE; 132 page_size = PAGE_SIZE;
138 nr_pages += (t->u.mem.size / PAGE_SIZE); 133 nr_pages += (t->u.mem.size / PAGE_SIZE);
139 } 134 }
140 } 135 }
141 } 136 } else {
142 else
143 {
144 nr_pages = params->nr_pages; 137 nr_pages = params->nr_pages;
145 page_size = params->page_size; 138 page_size = params->page_size;
146 video_num_rows = params->video_num_rows; 139 video_num_rows = params->video_num_rows;
diff --git a/arch/arm/lib/io-acorn.S b/arch/arm/mach-rpc/io-acorn.S
index 69719bad674d..69719bad674d 100644
--- a/arch/arm/lib/io-acorn.S
+++ b/arch/arm/mach-rpc/io-acorn.S
diff --git a/arch/arm/mach-rpc/irq.c b/arch/arm/mach-rpc/irq.c
index b8a61cb11207..803aeb126f0e 100644
--- a/arch/arm/mach-rpc/irq.c
+++ b/arch/arm/mach-rpc/irq.c
@@ -8,117 +8,71 @@
8#include <asm/irq.h> 8#include <asm/irq.h>
9#include <asm/fiq.h> 9#include <asm/fiq.h>
10 10
11static void iomd_ack_irq_a(struct irq_data *d) 11// These are offsets from the stat register for each IRQ bank
12{ 12#define STAT 0x00
13 unsigned int val, mask; 13#define REQ 0x04
14 14#define CLR 0x04
15 mask = 1 << d->irq; 15#define MASK 0x08
16 val = iomd_readb(IOMD_IRQMASKA);
17 iomd_writeb(val & ~mask, IOMD_IRQMASKA);
18 iomd_writeb(mask, IOMD_IRQCLRA);
19}
20
21static void iomd_mask_irq_a(struct irq_data *d)
22{
23 unsigned int val, mask;
24 16
25 mask = 1 << d->irq; 17static void __iomem *iomd_get_base(struct irq_data *d)
26 val = iomd_readb(IOMD_IRQMASKA);
27 iomd_writeb(val & ~mask, IOMD_IRQMASKA);
28}
29
30static void iomd_unmask_irq_a(struct irq_data *d)
31{ 18{
32 unsigned int val, mask; 19 void *cd = irq_data_get_irq_chip_data(d);
33 20
34 mask = 1 << d->irq; 21 return (void __iomem *)(unsigned long)cd;
35 val = iomd_readb(IOMD_IRQMASKA);
36 iomd_writeb(val | mask, IOMD_IRQMASKA);
37} 22}
38 23
39static struct irq_chip iomd_a_chip = { 24static void iomd_set_base_mask(unsigned int irq, void __iomem *base, u32 mask)
40 .irq_ack = iomd_ack_irq_a,
41 .irq_mask = iomd_mask_irq_a,
42 .irq_unmask = iomd_unmask_irq_a,
43};
44
45static void iomd_mask_irq_b(struct irq_data *d)
46{ 25{
47 unsigned int val, mask; 26 struct irq_data *d = irq_get_irq_data(irq);
48 27
49 mask = 1 << (d->irq & 7); 28 d->mask = mask;
50 val = iomd_readb(IOMD_IRQMASKB); 29 irq_set_chip_data(irq, (void *)(unsigned long)base);
51 iomd_writeb(val & ~mask, IOMD_IRQMASKB);
52} 30}
53 31
54static void iomd_unmask_irq_b(struct irq_data *d) 32static void iomd_irq_mask_ack(struct irq_data *d)
55{ 33{
56 unsigned int val, mask; 34 void __iomem *base = iomd_get_base(d);
35 unsigned int val, mask = d->mask;
57 36
58 mask = 1 << (d->irq & 7); 37 val = readb(base + MASK);
59 val = iomd_readb(IOMD_IRQMASKB); 38 writeb(val & ~mask, base + MASK);
60 iomd_writeb(val | mask, IOMD_IRQMASKB); 39 writeb(mask, base + CLR);
61} 40}
62 41
63static struct irq_chip iomd_b_chip = { 42static void iomd_irq_mask(struct irq_data *d)
64 .irq_ack = iomd_mask_irq_b,
65 .irq_mask = iomd_mask_irq_b,
66 .irq_unmask = iomd_unmask_irq_b,
67};
68
69static void iomd_mask_irq_dma(struct irq_data *d)
70{ 43{
71 unsigned int val, mask; 44 void __iomem *base = iomd_get_base(d);
45 unsigned int val, mask = d->mask;
72 46
73 mask = 1 << (d->irq & 7); 47 val = readb(base + MASK);
74 val = iomd_readb(IOMD_DMAMASK); 48 writeb(val & ~mask, base + MASK);
75 iomd_writeb(val & ~mask, IOMD_DMAMASK);
76} 49}
77 50
78static void iomd_unmask_irq_dma(struct irq_data *d) 51static void iomd_irq_unmask(struct irq_data *d)
79{ 52{
80 unsigned int val, mask; 53 void __iomem *base = iomd_get_base(d);
54 unsigned int val, mask = d->mask;
81 55
82 mask = 1 << (d->irq & 7); 56 val = readb(base + MASK);
83 val = iomd_readb(IOMD_DMAMASK); 57 writeb(val | mask, base + MASK);
84 iomd_writeb(val | mask, IOMD_DMAMASK);
85} 58}
86 59
87static struct irq_chip iomd_dma_chip = { 60static struct irq_chip iomd_chip_clr = {
88 .irq_ack = iomd_mask_irq_dma, 61 .irq_mask_ack = iomd_irq_mask_ack,
89 .irq_mask = iomd_mask_irq_dma, 62 .irq_mask = iomd_irq_mask,
90 .irq_unmask = iomd_unmask_irq_dma, 63 .irq_unmask = iomd_irq_unmask,
91}; 64};
92 65
93static void iomd_mask_irq_fiq(struct irq_data *d) 66static struct irq_chip iomd_chip_noclr = {
94{ 67 .irq_mask = iomd_irq_mask,
95 unsigned int val, mask; 68 .irq_unmask = iomd_irq_unmask,
96
97 mask = 1 << (d->irq & 7);
98 val = iomd_readb(IOMD_FIQMASK);
99 iomd_writeb(val & ~mask, IOMD_FIQMASK);
100}
101
102static void iomd_unmask_irq_fiq(struct irq_data *d)
103{
104 unsigned int val, mask;
105
106 mask = 1 << (d->irq & 7);
107 val = iomd_readb(IOMD_FIQMASK);
108 iomd_writeb(val | mask, IOMD_FIQMASK);
109}
110
111static struct irq_chip iomd_fiq_chip = {
112 .irq_ack = iomd_mask_irq_fiq,
113 .irq_mask = iomd_mask_irq_fiq,
114 .irq_unmask = iomd_unmask_irq_fiq,
115}; 69};
116 70
117extern unsigned char rpc_default_fiq_start, rpc_default_fiq_end; 71extern unsigned char rpc_default_fiq_start, rpc_default_fiq_end;
118 72
119void __init rpc_init_irq(void) 73void __init rpc_init_irq(void)
120{ 74{
121 unsigned int irq, clr, set = 0; 75 unsigned int irq, clr, set;
122 76
123 iomd_writeb(0, IOMD_IRQMASKA); 77 iomd_writeb(0, IOMD_IRQMASKA);
124 iomd_writeb(0, IOMD_IRQMASKB); 78 iomd_writeb(0, IOMD_IRQMASKB);
@@ -130,6 +84,7 @@ void __init rpc_init_irq(void)
130 84
131 for (irq = 0; irq < NR_IRQS; irq++) { 85 for (irq = 0; irq < NR_IRQS; irq++) {
132 clr = IRQ_NOREQUEST; 86 clr = IRQ_NOREQUEST;
87 set = 0;
133 88
134 if (irq <= 6 || (irq >= 9 && irq <= 15)) 89 if (irq <= 6 || (irq >= 9 && irq <= 15))
135 clr |= IRQ_NOPROBE; 90 clr |= IRQ_NOPROBE;
@@ -140,30 +95,37 @@ void __init rpc_init_irq(void)
140 95
141 switch (irq) { 96 switch (irq) {
142 case 0 ... 7: 97 case 0 ... 7:
143 irq_set_chip_and_handler(irq, &iomd_a_chip, 98 irq_set_chip_and_handler(irq, &iomd_chip_clr,
144 handle_level_irq); 99 handle_level_irq);
145 irq_modify_status(irq, clr, set); 100 irq_modify_status(irq, clr, set);
101 iomd_set_base_mask(irq, IOMD_BASE + IOMD_IRQSTATA,
102 BIT(irq));
146 break; 103 break;
147 104
148 case 8 ... 15: 105 case 8 ... 15:
149 irq_set_chip_and_handler(irq, &iomd_b_chip, 106 irq_set_chip_and_handler(irq, &iomd_chip_noclr,
150 handle_level_irq); 107 handle_level_irq);
151 irq_modify_status(irq, clr, set); 108 irq_modify_status(irq, clr, set);
109 iomd_set_base_mask(irq, IOMD_BASE + IOMD_IRQSTATB,
110 BIT(irq - 8));
152 break; 111 break;
153 112
154 case 16 ... 21: 113 case 16 ... 21:
155 irq_set_chip_and_handler(irq, &iomd_dma_chip, 114 irq_set_chip_and_handler(irq, &iomd_chip_noclr,
156 handle_level_irq); 115 handle_level_irq);
157 irq_modify_status(irq, clr, set); 116 irq_modify_status(irq, clr, set);
117 iomd_set_base_mask(irq, IOMD_BASE + IOMD_DMASTAT,
118 BIT(irq - 16));
158 break; 119 break;
159 120
160 case 64 ... 71: 121 case 64 ... 71:
161 irq_set_chip(irq, &iomd_fiq_chip); 122 irq_set_chip(irq, &iomd_chip_noclr);
162 irq_modify_status(irq, clr, set); 123 irq_modify_status(irq, clr, set);
124 iomd_set_base_mask(irq, IOMD_BASE + IOMD_FIQSTAT,
125 BIT(irq - 64));
163 break; 126 break;
164 } 127 }
165 } 128 }
166 129
167 init_FIQ(FIQ_START); 130 init_FIQ(FIQ_START);
168} 131}
169
diff --git a/arch/arm/mach-rpc/time.c b/arch/arm/mach-rpc/time.c
index 2689771c1d38..1c84efc9db1f 100644
--- a/arch/arm/mach-rpc/time.c
+++ b/arch/arm/mach-rpc/time.c
@@ -13,7 +13,7 @@
13 * 04-Dec-1997 RMK Updated for new arch/arm/time.c 13 * 04-Dec-1997 RMK Updated for new arch/arm/time.c
14 * 13=Jun-2004 DS Moved to arch/arm/common b/c shared w/CLPS7500 14 * 13=Jun-2004 DS Moved to arch/arm/common b/c shared w/CLPS7500
15 */ 15 */
16#include <linux/timex.h> 16#include <linux/clocksource.h>
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/interrupt.h> 18#include <linux/interrupt.h>
19#include <linux/irq.h> 19#include <linux/irq.h>
@@ -27,11 +27,15 @@
27#define RPC_CLOCK_FREQ 2000000 27#define RPC_CLOCK_FREQ 2000000
28#define RPC_LATCH DIV_ROUND_CLOSEST(RPC_CLOCK_FREQ, HZ) 28#define RPC_LATCH DIV_ROUND_CLOSEST(RPC_CLOCK_FREQ, HZ)
29 29
30static u32 ioc_timer_gettimeoffset(void) 30static u32 ioc_time;
31
32static u64 ioc_timer_read(struct clocksource *cs)
31{ 33{
32 unsigned int count1, count2, status; 34 unsigned int count1, count2, status;
33 long offset; 35 unsigned long flags;
36 u32 ticks;
34 37
38 local_irq_save(flags);
35 ioc_writeb (0, IOC_T0LATCH); 39 ioc_writeb (0, IOC_T0LATCH);
36 barrier (); 40 barrier ();
37 count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8); 41 count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
@@ -41,27 +45,34 @@ static u32 ioc_timer_gettimeoffset(void)
41 ioc_writeb (0, IOC_T0LATCH); 45 ioc_writeb (0, IOC_T0LATCH);
42 barrier (); 46 barrier ();
43 count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8); 47 count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
48 ticks = ioc_time + RPC_LATCH - count2;
49 local_irq_restore(flags);
44 50
45 offset = count2;
46 if (count2 < count1) { 51 if (count2 < count1) {
47 /* 52 /*
48 * We have not had an interrupt between reading count1 53 * The timer has not reloaded between reading count1 and
49 * and count2. 54 * count2, check whether an interrupt was actually pending.
50 */ 55 */
51 if (status & (1 << 5)) 56 if (status & (1 << 5))
52 offset -= RPC_LATCH; 57 ticks += RPC_LATCH;
53 } else if (count2 > count1) { 58 } else if (count2 > count1) {
54 /* 59 /*
55 * We have just had another interrupt between reading 60 * The timer has reloaded, so count2 indicates the new
56 * count1 and count2. 61 * count since the wrap. The interrupt would not have
62 * been processed, so add the missed ticks.
57 */ 63 */
58 offset -= RPC_LATCH; 64 ticks += RPC_LATCH;
59 } 65 }
60 66
61 offset = (RPC_LATCH - offset) * (tick_nsec / 1000); 67 return ticks;
62 return DIV_ROUND_CLOSEST(offset, RPC_LATCH) * 1000;
63} 68}
64 69
70static struct clocksource ioctime_clocksource = {
71 .read = ioc_timer_read,
72 .mask = CLOCKSOURCE_MASK(32),
73 .rating = 100,
74};
75
65void __init ioctime_init(void) 76void __init ioctime_init(void)
66{ 77{
67 ioc_writeb(RPC_LATCH & 255, IOC_T0LTCHL); 78 ioc_writeb(RPC_LATCH & 255, IOC_T0LTCHL);
@@ -72,6 +83,7 @@ void __init ioctime_init(void)
72static irqreturn_t 83static irqreturn_t
73ioc_timer_interrupt(int irq, void *dev_id) 84ioc_timer_interrupt(int irq, void *dev_id)
74{ 85{
86 ioc_time += RPC_LATCH;
75 timer_tick(); 87 timer_tick();
76 return IRQ_HANDLED; 88 return IRQ_HANDLED;
77} 89}
@@ -86,7 +98,7 @@ static struct irqaction ioc_timer_irq = {
86 */ 98 */
87void __init ioc_timer_init(void) 99void __init ioc_timer_init(void)
88{ 100{
89 arch_gettimeoffset = ioc_timer_gettimeoffset; 101 WARN_ON(clocksource_register_hz(&ioctime_clocksource, RPC_CLOCK_FREQ));
90 ioctime_init(); 102 ioctime_init();
91 setup_irq(IRQ_TIMER0, &ioc_timer_irq); 103 setup_irq(IRQ_TIMER0, &ioc_timer_irq);
92} 104}