Merge branch 'for-arm-soc' of git://git.armlinux.org.uk/~rmk/linux-arm into arm/soc
authorOlof Johansson <olof@lixom.net>
Tue, 16 Jul 2019 00:29:45 +0000 (17:29 -0700)
committerOlof Johansson <olof@lixom.net>
Tue, 16 Jul 2019 00:29:45 +0000 (17:29 -0700)
* 'for-arm-soc' of git://git.armlinux.org.uk/~rmk/linux-arm: (21 commits)
  ARM: sa1100: convert to common clock framework
  ARM: riscpc: enable chained scatterlist support
  ARM: riscpc: reduce IRQ handling code
  ARM: riscpc: move RiscPC assembly files from arch/arm/lib to mach-rpc
  ARM: riscpc: parse video information from tagged list
  ARM: riscpc: add ecard quirk for Atomwide 3port serial card
  ARM: sa1100/neponset: convert serial to use gpiod APIs
  ARM: sa1100/hackkit: remove empty serial mctrl functions
  ARM: sa1100/badge4: remove commented out modem control initialisers
  ARM: sa1100/h3xxx: convert serial to gpiod APIs
  ARM: sa1100/assabet: convert serial to gpiod APIs
  serial: sa1100: add note about modem control signals
  serial: sa1100: add support for mctrl gpios
  ARM: riscpc: dma: use __iomem pointers for writing DMA
  ARM: riscpc: dma: improve address/length writing
  ARM: riscpc: dma: make state a local variable
  ARM: riscpc: dma: eliminate "cur_sg" scatterlist usage
  ARM: riscpc: fix DMA
  ARM: riscpc: fix ecard printing
  ARM: riscpc: fix lack of keyboard interrupts after irq conversion
  ...
Signed-off-by: Olof Johansson <olof@lixom.net>
23 files changed:
MAINTAINERS
arch/arm/Kconfig
arch/arm/lib/Makefile
arch/arm/lib/ecard.S [deleted file]
arch/arm/lib/floppydma.S [deleted file]
arch/arm/lib/io-acorn.S [deleted file]
arch/arm/mach-rpc/Makefile
arch/arm/mach-rpc/dma.c
arch/arm/mach-rpc/ecard-loader.S [new file with mode: 0644]
arch/arm/mach-rpc/ecard.c
arch/arm/mach-rpc/floppydma.S [new file with mode: 0644]
arch/arm/mach-rpc/include/mach/uncompress.h
arch/arm/mach-rpc/io-acorn.S [new file with mode: 0644]
arch/arm/mach-rpc/irq.c
arch/arm/mach-rpc/time.c
arch/arm/mach-sa1100/assabet.c
arch/arm/mach-sa1100/badge4.c
arch/arm/mach-sa1100/clock.c
arch/arm/mach-sa1100/h3xxx.c
arch/arm/mach-sa1100/hackkit.c
arch/arm/mach-sa1100/neponset.c
drivers/tty/serial/Kconfig
drivers/tty/serial/sa1100.c

index ba64522..1f1164b 100644 (file)
@@ -1231,7 +1231,7 @@ F:        include/uapi/drm/panfrost_drm.h
 ARM MFM AND FLOPPY DRIVERS
 M:     Ian Molton <spyro@f2s.com>
 S:     Maintained
-F:     arch/arm/lib/floppydma.S
+F:     arch/arm/mach-rpc/floppydma.S
 F:     arch/arm/include/asm/floppy.h
 
 ARM PMU PROFILING AND DEBUGGING
index 02c62ba..1d50861 100644 (file)
@@ -519,7 +519,7 @@ config ARCH_RPC
        select ARCH_ACORN
        select ARCH_MAY_HAVE_PC_FDC
        select ARCH_SPARSEMEM_ENABLE
-       select ARCH_USES_GETTIMEOFFSET
+       select ARM_HAS_SG_CHAIN
        select CPU_SA110
        select FIQ
        select HAVE_IDE
@@ -540,6 +540,7 @@ config ARCH_SA1100
        select CLKSRC_MMIO
        select CLKSRC_PXA
        select TIMER_OF if OF
+       select COMMON_CLK
        select CPU_FREQ
        select CPU_SA1100
        select GENERIC_CLOCKEVENTS
index 0bff017..b25c545 100644 (file)
@@ -31,7 +31,6 @@ else
 endif
 
 ifeq ($(CONFIG_ARCH_RPC),y)
-  lib-y                                += ecard.o io-acorn.o floppydma.o
   AFLAGS_delay-loop.o          += -march=armv4
 endif
 
diff --git a/arch/arm/lib/ecard.S b/arch/arm/lib/ecard.S
deleted file mode 100644 (file)
index e6057fa..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *  linux/arch/arm/lib/ecard.S
- *
- *  Copyright (C) 1995, 1996 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 27/03/03 Ian Molton Clean up CONFIG_CPU
- *
- */
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-
-#define CPSR2SPSR(rt) \
-               mrs     rt, cpsr; \
-               msr     spsr_cxsf, rt
-
-@ Purpose: call an expansion card loader to read bytes.
-@ Proto  : char read_loader(int offset, char *card_base, char *loader);
-@ Returns: byte read
-
-ENTRY(ecard_loader_read)
-               stmfd   sp!, {r4 - r12, lr}
-               mov     r11, r1
-               mov     r1, r0
-               CPSR2SPSR(r0)
-               mov     lr, pc
-               mov     pc, r2
-               ldmfd   sp!, {r4 - r12, pc}
-
-@ Purpose: call an expansion card loader to reset the card
-@ Proto  : void read_loader(int card_base, char *loader);
-@ Returns: byte read
-
-ENTRY(ecard_loader_reset)
-               stmfd   sp!, {r4 - r12, lr}
-               mov     r11, r0
-               CPSR2SPSR(r0)
-               mov     lr, pc
-               add     pc, r1, #8
-               ldmfd   sp!, {r4 - r12, pc}
-
diff --git a/arch/arm/lib/floppydma.S b/arch/arm/lib/floppydma.S
deleted file mode 100644 (file)
index de68d3b..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  linux/arch/arm/lib/floppydma.S
- *
- *  Copyright (C) 1995, 1996 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-               .text
-
-               .global floppy_fiqin_end
-ENTRY(floppy_fiqin_start)
-               subs    r9, r9, #1
-               ldrbgt  r12, [r11, #-4]
-               ldrble  r12, [r11], #0
-               strb    r12, [r10], #1
-               subs    pc, lr, #4
-floppy_fiqin_end:
-
-               .global floppy_fiqout_end
-ENTRY(floppy_fiqout_start)
-               subs    r9, r9, #1
-               ldrbge  r12, [r10], #1
-               movlt   r12, #0
-               strble  r12, [r11], #0
-               subsle  pc, lr, #4
-               strb    r12, [r11, #-4]
-               subs    pc, lr, #4
-floppy_fiqout_end:
diff --git a/arch/arm/lib/io-acorn.S b/arch/arm/lib/io-acorn.S
deleted file mode 100644 (file)
index 69719ba..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  linux/arch/arm/lib/io-acorn.S
- *
- *  Copyright (C) 1995, 1996 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 27/03/03 Ian Molton Clean up CONFIG_CPU
- *
- */
-#include <linux/linkage.h>
-#include <linux/kern_levels.h>
-#include <asm/assembler.h>
-
-               .text
-               .align
-
-.Liosl_warning:
-               .ascii  KERN_WARNING "insl/outsl not implemented, called from %08lX\0"
-               .align
-
-/*
- * These make no sense on Acorn machines.
- * Print a warning message.
- */
-ENTRY(insl)
-ENTRY(outsl)
-               adr     r0, .Liosl_warning
-               mov     r1, lr
-               b       printk
index 056ef54..90a645a 100644 (file)
@@ -5,4 +5,5 @@
 
 # Object file lists.
 
-obj-y                  := dma.o ecard.o fiq.o irq.o riscpc.o time.o
+obj-y  :=dma.o ecard.o ecard-loader.o fiq.o floppydma.o io-acorn.o irq.o \
+         riscpc.o time.o
index f2703ca..e221f6b 100644 (file)
 
 struct iomd_dma {
        struct dma_struct       dma;
-       unsigned int            state;
-       unsigned long           base;           /* Controller base address */
+       void __iomem            *base;          /* Controller base address */
        int                     irq;            /* Controller IRQ */
-       struct scatterlist      cur_sg;         /* Current controller buffer */
+       unsigned int            state;
+       dma_addr_t              cur_addr;
+       unsigned int            cur_len;
        dma_addr_t              dma_addr;
        unsigned int            dma_len;
 };
@@ -53,13 +54,13 @@ typedef enum {
 #define CR     (IOMD_IO0CR - IOMD_IO0CURA)
 #define ST     (IOMD_IO0ST - IOMD_IO0CURA)
 
-static void iomd_get_next_sg(struct scatterlist *sg, struct iomd_dma *idma)
+static void iomd_get_next_sg(struct iomd_dma *idma)
 {
        unsigned long end, offset, flags = 0;
 
        if (idma->dma.sg) {
-               sg->dma_address = idma->dma_addr;
-               offset = sg->dma_address & ~PAGE_MASK;
+               idma->cur_addr = idma->dma_addr;
+               offset = idma->cur_addr & ~PAGE_MASK;
 
                end = offset + idma->dma_len;
 
@@ -69,7 +70,7 @@ static void iomd_get_next_sg(struct scatterlist *sg, struct iomd_dma *idma)
                if (offset + TRANSFER_SIZE >= end)
                        flags |= DMA_END_L;
 
-               sg->length = end - TRANSFER_SIZE;
+               idma->cur_len = end - TRANSFER_SIZE;
 
                idma->dma_len -= end - offset;
                idma->dma_addr += end - offset;
@@ -87,52 +88,49 @@ static void iomd_get_next_sg(struct scatterlist *sg, struct iomd_dma *idma)
                }
        } else {
                flags = DMA_END_S | DMA_END_L;
-               sg->dma_address = 0;
-               sg->length = 0;
+               idma->cur_addr = 0;
+               idma->cur_len = 0;
        }
 
-       sg->length |= flags;
+       idma->cur_len |= flags;
 }
 
 static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
 {
        struct iomd_dma *idma = dev_id;
-       unsigned long base = idma->base;
+       void __iomem *base = idma->base;
+       unsigned int state = idma->state;
+       unsigned int status, cur, end;
 
        do {
-               unsigned int status;
-
-               status = iomd_readb(base + ST);
+               status = readb(base + ST);
                if (!(status & DMA_ST_INT))
-                       return IRQ_HANDLED;
-
-               if ((idma->state ^ status) & DMA_ST_AB)
-                       iomd_get_next_sg(&idma->cur_sg, idma);
-
-               switch (status & (DMA_ST_OFL | DMA_ST_AB)) {
-               case DMA_ST_OFL:                        /* OIA */
-               case DMA_ST_AB:                         /* .IB */
-                       iomd_writel(idma->cur_sg.dma_address, base + CURA);
-                       iomd_writel(idma->cur_sg.length, base + ENDA);
-                       idma->state = DMA_ST_AB;
-                       break;
-
-               case DMA_ST_OFL | DMA_ST_AB:            /* OIB */
-               case 0:                                 /* .IA */
-                       iomd_writel(idma->cur_sg.dma_address, base + CURB);
-                       iomd_writel(idma->cur_sg.length, base + ENDB);
-                       idma->state = 0;
-                       break;
+                       goto out;
+
+               if ((state ^ status) & DMA_ST_AB)
+                       iomd_get_next_sg(idma);
+
+               // This efficiently implements state = OFL != AB ? AB : 0
+               state = ((status >> 2) ^ status) & DMA_ST_AB;
+               if (state) {
+                       cur = CURA;
+                       end = ENDA;
+               } else {
+                       cur = CURB;
+                       end = ENDB;
                }
+               writel(idma->cur_addr, base + cur);
+               writel(idma->cur_len, base + end);
 
                if (status & DMA_ST_OFL &&
-                   idma->cur_sg.length == (DMA_END_S|DMA_END_L))
+                   idma->cur_len == (DMA_END_S|DMA_END_L))
                        break;
        } while (1);
 
-       idma->state = ~DMA_ST_AB;
-       disable_irq(irq);
-
+       state = ~DMA_ST_AB;
+       disable_irq_nosync(irq);
+out:
+       idma->state = state;
        return IRQ_HANDLED;
 }
 
@@ -160,7 +158,7 @@ static struct device isa_dma_dev = {
 static void iomd_enable_dma(unsigned int chan, dma_t *dma)
 {
        struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
-       unsigned long dma_base = idma->base;
+       void __iomem *base = idma->base;
        unsigned int ctrl = TRANSFER_SIZE | DMA_CR_E;
 
        if (idma->dma.invalid) {
@@ -180,27 +178,30 @@ static void iomd_enable_dma(unsigned int chan, dma_t *dma)
                                DMA_FROM_DEVICE : DMA_TO_DEVICE);
                }
 
-               iomd_writeb(DMA_CR_C, dma_base + CR);
+               idma->dma_addr = idma->dma.sg->dma_address;
+               idma->dma_len = idma->dma.sg->length;
+
+               writeb(DMA_CR_C, base + CR);
                idma->state = DMA_ST_AB;
        }
 
        if (idma->dma.dma_mode == DMA_MODE_READ)
                ctrl |= DMA_CR_D;
 
-       iomd_writeb(ctrl, dma_base + CR);
+       writeb(ctrl, base + CR);
        enable_irq(idma->irq);
 }
 
 static void iomd_disable_dma(unsigned int chan, dma_t *dma)
 {
        struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
-       unsigned long dma_base = idma->base;
+       void __iomem *base = idma->base;
        unsigned long flags;
 
        local_irq_save(flags);
        if (idma->state != ~DMA_ST_AB)
                disable_irq(idma->irq);
-       iomd_writeb(0, dma_base + CR);
+       writeb(0, base + CR);
        local_irq_restore(flags);
 }
 
@@ -363,17 +364,17 @@ static int __init rpc_dma_init(void)
         */
        iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);
 
-       iomd_dma[DMA_0].base    = IOMD_IO0CURA;
+       iomd_dma[DMA_0].base    = IOMD_BASE + IOMD_IO0CURA;
        iomd_dma[DMA_0].irq     = IRQ_DMA0;
-       iomd_dma[DMA_1].base    = IOMD_IO1CURA;
+       iomd_dma[DMA_1].base    = IOMD_BASE + IOMD_IO1CURA;
        iomd_dma[DMA_1].irq     = IRQ_DMA1;
-       iomd_dma[DMA_2].base    = IOMD_IO2CURA;
+       iomd_dma[DMA_2].base    = IOMD_BASE + IOMD_IO2CURA;
        iomd_dma[DMA_2].irq     = IRQ_DMA2;
-       iomd_dma[DMA_3].base    = IOMD_IO3CURA;
+       iomd_dma[DMA_3].base    = IOMD_BASE + IOMD_IO3CURA;
        iomd_dma[DMA_3].irq     = IRQ_DMA3;
-       iomd_dma[DMA_S0].base   = IOMD_SD0CURA;
+       iomd_dma[DMA_S0].base   = IOMD_BASE + IOMD_SD0CURA;
        iomd_dma[DMA_S0].irq    = IRQ_DMAS0;
-       iomd_dma[DMA_S1].base   = IOMD_SD1CURA;
+       iomd_dma[DMA_S1].base   = IOMD_BASE + IOMD_SD1CURA;
        iomd_dma[DMA_S1].irq    = IRQ_DMAS1;
 
        for (i = DMA_0; i <= DMA_S1; i++) {
diff --git a/arch/arm/mach-rpc/ecard-loader.S b/arch/arm/mach-rpc/ecard-loader.S
new file mode 100644 (file)
index 0000000..e6057fa
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ *  linux/arch/arm/lib/ecard.S
+ *
+ *  Copyright (C) 1995, 1996 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 27/03/03 Ian Molton Clean up CONFIG_CPU
+ *
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+#define CPSR2SPSR(rt) \
+               mrs     rt, cpsr; \
+               msr     spsr_cxsf, rt
+
+@ Purpose: call an expansion card loader to read bytes.
+@ Proto  : char read_loader(int offset, char *card_base, char *loader);
+@ Returns: byte read
+
+ENTRY(ecard_loader_read)
+               stmfd   sp!, {r4 - r12, lr}
+               mov     r11, r1
+               mov     r1, r0
+               CPSR2SPSR(r0)
+               mov     lr, pc
+               mov     pc, r2
+               ldmfd   sp!, {r4 - r12, pc}
+
+@ Purpose: call an expansion card loader to reset the card
+@ Proto  : void read_loader(int card_base, char *loader);
+@ Returns: byte read
+
+ENTRY(ecard_loader_reset)
+               stmfd   sp!, {r4 - r12, lr}
+               mov     r11, r0
+               CPSR2SPSR(r0)
+               mov     lr, pc
+               add     pc, r1, #8
+               ldmfd   sp!, {r4 - r12, pc}
+
index 04b2f22..eec5ecd 100644 (file)
@@ -70,17 +70,21 @@ struct expcard_blacklist {
        unsigned short   manufacturer;
        unsigned short   product;
        const char      *type;
+       void (*init)(ecard_t *ec);
 };
 
 static ecard_t *cards;
 static ecard_t *slot_to_expcard[MAX_ECARDS];
 static unsigned int ectcr;
 
+static void atomwide_3p_quirk(ecard_t *ec);
+
 /* List of descriptions of cards which don't have an extended
  * identification, or chunk directories containing a description.
  */
 static struct expcard_blacklist __initdata blacklist[] = {
-       { MANU_ACORN, PROD_ACORN_ETHER1, "Acorn Ether1" }
+       { MANU_ACORN, PROD_ACORN_ETHER1, "Acorn Ether1" },
+       { MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL, NULL, atomwide_3p_quirk },
 };
 
 asmlinkage extern int
@@ -496,18 +500,21 @@ static void ecard_dump_irq_state(void)
        printk("Expansion card IRQ state:\n");
 
        for (ec = cards; ec; ec = ec->next) {
+               const char *claimed;
+
                if (ec->slot_no == 8)
                        continue;
 
-               printk("  %d: %sclaimed, ",
-                      ec->slot_no, ec->claimed ? "" : "not ");
+               claimed = ec->claimed ? "" : "not ";
 
                if (ec->ops && ec->ops->irqpending &&
                    ec->ops != &ecard_default_ops)
-                       printk("irq %spending\n",
+                       printk("  %d: %sclaimed irq %spending\n",
+                              ec->slot_no, claimed,
                               ec->ops->irqpending(ec) ? "" : "not ");
                else
-                       printk("irqaddr %p, mask = %02X, status = %02X\n",
+                       printk("  %d: %sclaimed irqaddr %p, mask = %02X, status = %02X\n",
+                              ec->slot_no, claimed,
                               ec->irqaddr, ec->irqmask, readb(ec->irqaddr));
        }
 }
@@ -868,6 +875,16 @@ void __iomem *ecardm_iomap(struct expansion_card *ec, unsigned int res,
 }
 EXPORT_SYMBOL(ecardm_iomap);
 
+static void atomwide_3p_quirk(ecard_t *ec)
+{
+       void __iomem *addr = __ecard_address(ec, ECARD_IOC, ECARD_SYNC);
+       unsigned int i;
+
+       /* Disable interrupts on each port */
+       for (i = 0x2000; i <= 0x2800; i += 0x0400)
+               writeb(0, addr + i + 4);        
+}
+
 /*
  * Probe for an expansion card.
  *
@@ -924,7 +941,10 @@ static int __init ecard_probe(int slot, unsigned irq, card_type_t type)
        for (i = 0; i < ARRAY_SIZE(blacklist); i++)
                if (blacklist[i].manufacturer == ec->cid.manufacturer &&
                    blacklist[i].product == ec->cid.product) {
-                       ec->card_desc = blacklist[i].type;
+                       if (blacklist[i].type)
+                               ec->card_desc = blacklist[i].type;
+                       if (blacklist[i].init)
+                               blacklist[i].init(ec);
                        break;
                }
 
diff --git a/arch/arm/mach-rpc/floppydma.S b/arch/arm/mach-rpc/floppydma.S
new file mode 100644 (file)
index 0000000..de68d3b
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  linux/arch/arm/lib/floppydma.S
+ *
+ *  Copyright (C) 1995, 1996 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+               .text
+
+               .global floppy_fiqin_end
+ENTRY(floppy_fiqin_start)
+               subs    r9, r9, #1
+               ldrbgt  r12, [r11, #-4]
+               ldrble  r12, [r11], #0
+               strb    r12, [r10], #1
+               subs    pc, lr, #4
+floppy_fiqin_end:
+
+               .global floppy_fiqout_end
+ENTRY(floppy_fiqout_start)
+               subs    r9, r9, #1
+               ldrbge  r12, [r10], #1
+               movlt   r12, #0
+               strble  r12, [r11], #0
+               subsle  pc, lr, #4
+               strb    r12, [r11, #-4]
+               subs    pc, lr, #4
+floppy_fiqout_end:
index 654a6f3..edc1961 100644 (file)
@@ -118,29 +118,22 @@ static void arch_decomp_setup(void)
        struct tag *t = (struct tag *)params;
        unsigned int nr_pages = 0, page_size = PAGE_SIZE;
 
-       if (t->hdr.tag == ATAG_CORE)
-       {
-               for (; t->hdr.size; t = tag_next(t))
-               {
-                       if (t->hdr.tag == ATAG_VIDEOTEXT)
-                       {
+       if (t->hdr.tag == ATAG_CORE) {
+               for (; t->hdr.size; t = tag_next(t)) {
+                       if (t->hdr.tag == ATAG_VIDEOTEXT) {
                                video_num_rows = t->u.videotext.video_lines;
                                video_num_cols = t->u.videotext.video_cols;
-                               bytes_per_char_h = t->u.videotext.video_points;
-                               bytes_per_char_v = t->u.videotext.video_points;
                                video_x = t->u.videotext.x;
                                video_y = t->u.videotext.y;
-                       }
-
-                       if (t->hdr.tag == ATAG_MEM)
-                       {
+                       } else if (t->hdr.tag == ATAG_VIDEOLFB) {
+                               bytes_per_char_h = t->u.videolfb.lfb_depth;
+                               bytes_per_char_v = 8;
+                       } else if (t->hdr.tag == ATAG_MEM) {
                                page_size = PAGE_SIZE;
                                nr_pages += (t->u.mem.size / PAGE_SIZE);
                        }
                }
-       }
-       else
-       {
+       } else {
                nr_pages = params->nr_pages;
                page_size = params->page_size;
                video_num_rows = params->video_num_rows;
diff --git a/arch/arm/mach-rpc/io-acorn.S b/arch/arm/mach-rpc/io-acorn.S
new file mode 100644 (file)
index 0000000..69719ba
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  linux/arch/arm/lib/io-acorn.S
+ *
+ *  Copyright (C) 1995, 1996 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 27/03/03 Ian Molton Clean up CONFIG_CPU
+ *
+ */
+#include <linux/linkage.h>
+#include <linux/kern_levels.h>
+#include <asm/assembler.h>
+
+               .text
+               .align
+
+.Liosl_warning:
+               .ascii  KERN_WARNING "insl/outsl not implemented, called from %08lX\0"
+               .align
+
+/*
+ * These make no sense on Acorn machines.
+ * Print a warning message.
+ */
+ENTRY(insl)
+ENTRY(outsl)
+               adr     r0, .Liosl_warning
+               mov     r1, lr
+               b       printk
index b8a61cb..803aeb1 100644 (file)
 #include <asm/irq.h>
 #include <asm/fiq.h>
 
-static void iomd_ack_irq_a(struct irq_data *d)
-{
-       unsigned int val, mask;
-
-       mask = 1 << d->irq;
-       val = iomd_readb(IOMD_IRQMASKA);
-       iomd_writeb(val & ~mask, IOMD_IRQMASKA);
-       iomd_writeb(mask, IOMD_IRQCLRA);
-}
-
-static void iomd_mask_irq_a(struct irq_data *d)
-{
-       unsigned int val, mask;
+// These are offsets from the stat register for each IRQ bank
+#define STAT   0x00
+#define REQ    0x04
+#define CLR    0x04
+#define MASK   0x08
 
-       mask = 1 << d->irq;
-       val = iomd_readb(IOMD_IRQMASKA);
-       iomd_writeb(val & ~mask, IOMD_IRQMASKA);
-}
-
-static void iomd_unmask_irq_a(struct irq_data *d)
+static void __iomem *iomd_get_base(struct irq_data *d)
 {
-       unsigned int val, mask;
+       void *cd = irq_data_get_irq_chip_data(d);
 
-       mask = 1 << d->irq;
-       val = iomd_readb(IOMD_IRQMASKA);
-       iomd_writeb(val | mask, IOMD_IRQMASKA);
+       return (void __iomem *)(unsigned long)cd;
 }
 
-static struct irq_chip iomd_a_chip = {
-       .irq_ack        = iomd_ack_irq_a,
-       .irq_mask       = iomd_mask_irq_a,
-       .irq_unmask     = iomd_unmask_irq_a,
-};
-
-static void iomd_mask_irq_b(struct irq_data *d)
+static void iomd_set_base_mask(unsigned int irq, void __iomem *base, u32 mask)
 {
-       unsigned int val, mask;
+       struct irq_data *d = irq_get_irq_data(irq);
 
-       mask = 1 << (d->irq & 7);
-       val = iomd_readb(IOMD_IRQMASKB);
-       iomd_writeb(val & ~mask, IOMD_IRQMASKB);
+       d->mask = mask;
+       irq_set_chip_data(irq, (void *)(unsigned long)base);
 }
 
-static void iomd_unmask_irq_b(struct irq_data *d)
+static void iomd_irq_mask_ack(struct irq_data *d)
 {
-       unsigned int val, mask;
+       void __iomem *base = iomd_get_base(d);
+       unsigned int val, mask = d->mask;
 
-       mask = 1 << (d->irq & 7);
-       val = iomd_readb(IOMD_IRQMASKB);
-       iomd_writeb(val | mask, IOMD_IRQMASKB);
+       val = readb(base + MASK);
+       writeb(val & ~mask, base + MASK);
+       writeb(mask, base + CLR);
 }
 
-static struct irq_chip iomd_b_chip = {
-       .irq_ack        = iomd_mask_irq_b,
-       .irq_mask       = iomd_mask_irq_b,
-       .irq_unmask     = iomd_unmask_irq_b,
-};
-
-static void iomd_mask_irq_dma(struct irq_data *d)
+static void iomd_irq_mask(struct irq_data *d)
 {
-       unsigned int val, mask;
+       void __iomem *base = iomd_get_base(d);
+       unsigned int val, mask = d->mask;
 
-       mask = 1 << (d->irq & 7);
-       val = iomd_readb(IOMD_DMAMASK);
-       iomd_writeb(val & ~mask, IOMD_DMAMASK);
+       val = readb(base + MASK);
+       writeb(val & ~mask, base + MASK);
 }
 
-static void iomd_unmask_irq_dma(struct irq_data *d)
+static void iomd_irq_unmask(struct irq_data *d)
 {
-       unsigned int val, mask;
+       void __iomem *base = iomd_get_base(d);
+       unsigned int val, mask = d->mask;
 
-       mask = 1 << (d->irq & 7);
-       val = iomd_readb(IOMD_DMAMASK);
-       iomd_writeb(val | mask, IOMD_DMAMASK);
+       val = readb(base + MASK);
+       writeb(val | mask, base + MASK);
 }
 
-static struct irq_chip iomd_dma_chip = {
-       .irq_ack        = iomd_mask_irq_dma,
-       .irq_mask       = iomd_mask_irq_dma,
-       .irq_unmask     = iomd_unmask_irq_dma,
+static struct irq_chip iomd_chip_clr = {
+       .irq_mask_ack   = iomd_irq_mask_ack,
+       .irq_mask       = iomd_irq_mask,
+       .irq_unmask     = iomd_irq_unmask,
 };
 
-static void iomd_mask_irq_fiq(struct irq_data *d)
-{
-       unsigned int val, mask;
-
-       mask = 1 << (d->irq & 7);
-       val = iomd_readb(IOMD_FIQMASK);
-       iomd_writeb(val & ~mask, IOMD_FIQMASK);
-}
-
-static void iomd_unmask_irq_fiq(struct irq_data *d)
-{
-       unsigned int val, mask;
-
-       mask = 1 << (d->irq & 7);
-       val = iomd_readb(IOMD_FIQMASK);
-       iomd_writeb(val | mask, IOMD_FIQMASK);
-}
-
-static struct irq_chip iomd_fiq_chip = {
-       .irq_ack        = iomd_mask_irq_fiq,
-       .irq_mask       = iomd_mask_irq_fiq,
-       .irq_unmask     = iomd_unmask_irq_fiq,
+static struct irq_chip iomd_chip_noclr = {
+       .irq_mask       = iomd_irq_mask,
+       .irq_unmask     = iomd_irq_unmask,
 };
 
 extern unsigned char rpc_default_fiq_start, rpc_default_fiq_end;
 
 void __init rpc_init_irq(void)
 {
-       unsigned int irq, clr, set = 0;
+       unsigned int irq, clr, set;
 
        iomd_writeb(0, IOMD_IRQMASKA);
        iomd_writeb(0, IOMD_IRQMASKB);
@@ -130,6 +84,7 @@ void __init rpc_init_irq(void)
 
        for (irq = 0; irq < NR_IRQS; irq++) {
                clr = IRQ_NOREQUEST;
+               set = 0;
 
                if (irq <= 6 || (irq >= 9 && irq <= 15))
                        clr |= IRQ_NOPROBE;
@@ -140,30 +95,37 @@ void __init rpc_init_irq(void)
 
                switch (irq) {
                case 0 ... 7:
-                       irq_set_chip_and_handler(irq, &iomd_a_chip,
+                       irq_set_chip_and_handler(irq, &iomd_chip_clr,
                                                 handle_level_irq);
                        irq_modify_status(irq, clr, set);
+                       iomd_set_base_mask(irq, IOMD_BASE + IOMD_IRQSTATA,
+                                          BIT(irq));
                        break;
 
                case 8 ... 15:
-                       irq_set_chip_and_handler(irq, &iomd_b_chip,
+                       irq_set_chip_and_handler(irq, &iomd_chip_noclr,
                                                 handle_level_irq);
                        irq_modify_status(irq, clr, set);
+                       iomd_set_base_mask(irq, IOMD_BASE + IOMD_IRQSTATB,
+                                          BIT(irq - 8));
                        break;
 
                case 16 ... 21:
-                       irq_set_chip_and_handler(irq, &iomd_dma_chip,
+                       irq_set_chip_and_handler(irq, &iomd_chip_noclr,
                                                 handle_level_irq);
                        irq_modify_status(irq, clr, set);
+                       iomd_set_base_mask(irq, IOMD_BASE + IOMD_DMASTAT,
+                                          BIT(irq - 16));
                        break;
 
                case 64 ... 71:
-                       irq_set_chip(irq, &iomd_fiq_chip);
+                       irq_set_chip(irq, &iomd_chip_noclr);
                        irq_modify_status(irq, clr, set);
+                       iomd_set_base_mask(irq, IOMD_BASE + IOMD_FIQSTAT,
+                                          BIT(irq - 64));
                        break;
                }
        }
 
        init_FIQ(FIQ_START);
 }
-
index 2689771..1c84efc 100644 (file)
@@ -13,7 +13,7 @@
  *   04-Dec-1997       RMK     Updated for new arch/arm/time.c
  *   13=Jun-2004       DS      Moved to arch/arm/common b/c shared w/CLPS7500
  */
-#include <linux/timex.h>
+#include <linux/clocksource.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #define RPC_CLOCK_FREQ 2000000
 #define RPC_LATCH DIV_ROUND_CLOSEST(RPC_CLOCK_FREQ, HZ)
 
-static u32 ioc_timer_gettimeoffset(void)
+static u32 ioc_time;
+
+static u64 ioc_timer_read(struct clocksource *cs)
 {
        unsigned int count1, count2, status;
-       long offset;
+       unsigned long flags;
+       u32 ticks;
 
+       local_irq_save(flags);
        ioc_writeb (0, IOC_T0LATCH);
        barrier ();
        count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
@@ -41,27 +45,34 @@ static u32 ioc_timer_gettimeoffset(void)
        ioc_writeb (0, IOC_T0LATCH);
        barrier ();
        count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
+       ticks = ioc_time + RPC_LATCH - count2;
+       local_irq_restore(flags);
 
-       offset = count2;
        if (count2 < count1) {
                /*
-                * We have not had an interrupt between reading count1
-                * and count2.
+                * The timer has not reloaded between reading count1 and
+                * count2, check whether an interrupt was actually pending.
                 */
                if (status & (1 << 5))
-                       offset -= RPC_LATCH;
+                       ticks += RPC_LATCH;
        } else if (count2 > count1) {
                /*
-                * We have just had another interrupt between reading
-                * count1 and count2.
+                * The timer has reloaded, so count2 indicates the new
+                * count since the wrap.  The interrupt would not have
+                * been processed, so add the missed ticks.
                 */
-               offset -= RPC_LATCH;
+               ticks += RPC_LATCH;
        }
 
-       offset = (RPC_LATCH - offset) * (tick_nsec / 1000);
-       return DIV_ROUND_CLOSEST(offset, RPC_LATCH) * 1000;
+       return ticks;
 }
 
+static struct clocksource ioctime_clocksource = {
+       .read = ioc_timer_read,
+       .mask = CLOCKSOURCE_MASK(32),
+       .rating = 100,
+};
+
 void __init ioctime_init(void)
 {
        ioc_writeb(RPC_LATCH & 255, IOC_T0LTCHL);
@@ -72,6 +83,7 @@ void __init ioctime_init(void)
 static irqreturn_t
 ioc_timer_interrupt(int irq, void *dev_id)
 {
+       ioc_time += RPC_LATCH;
        timer_tick();
        return IRQ_HANDLED;
 }
@@ -86,7 +98,7 @@ static struct irqaction ioc_timer_irq = {
  */
 void __init ioc_timer_init(void)
 {
-       arch_gettimeoffset = ioc_timer_gettimeoffset;
+       WARN_ON(clocksource_register_hz(&ioctime_clocksource, RPC_CLOCK_FREQ));
        ioctime_init();
        setup_irq(IRQ_TIMER0, &ioc_timer_irq);
 }
index d09c3f2..bc03582 100644 (file)
@@ -522,6 +522,29 @@ static const struct gpio_keys_platform_data assabet_keys_pdata = {
        .rep = 0,
 };
 
+static struct gpiod_lookup_table assabet_uart1_gpio_table = {
+       .dev_id = "sa11x0-uart.1",
+       .table = {
+               GPIO_LOOKUP("assabet", 16, "dtr", GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP("assabet", 17, "rts", GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP("assabet", 25, "dcd", GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP("assabet", 26, "cts", GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP("assabet", 27, "dsr", GPIO_ACTIVE_LOW),
+               { },
+       },
+};
+
+static struct gpiod_lookup_table assabet_uart3_gpio_table = {
+       .dev_id = "sa11x0-uart.3",
+       .table = {
+               GPIO_LOOKUP("assabet", 28, "cts", GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP("assabet", 29, "dsr", GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP("assabet", 30, "dcd", GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP("assabet", 31, "rng", GPIO_ACTIVE_LOW),
+               { },
+       },
+};
+
 static void __init assabet_init(void)
 {
        /*
@@ -568,7 +591,10 @@ static void __init assabet_init(void)
                        neponset_resources, ARRAY_SIZE(neponset_resources));
 #endif
        } else {
+               gpiod_add_lookup_table(&assabet_uart1_gpio_table);
+               gpiod_add_lookup_table(&assabet_uart3_gpio_table);
                gpiod_add_lookup_table(&assabet_cf_vcc_gpio_table);
+
                sa11x0_register_fixed_regulator(0, &assabet_cf_vcc_pdata,
                                        assabet_cf_vcc_consumers,
                                        ARRAY_SIZE(assabet_cf_vcc_consumers),
@@ -658,74 +684,13 @@ static void assabet_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
 {
        if (port->mapbase == _Ser1UTCR0) {
                if (state)
-                       ASSABET_BCR_clear(ASSABET_BCR_RS232EN |
-                                         ASSABET_BCR_COM_RTS |
-                                         ASSABET_BCR_COM_DTR);
-               else
-                       ASSABET_BCR_set(ASSABET_BCR_RS232EN |
-                                       ASSABET_BCR_COM_RTS |
-                                       ASSABET_BCR_COM_DTR);
-       }
-}
-
-/*
- * Assabet uses COM_RTS and COM_DTR for both UART1 (com port)
- * and UART3 (radio module).  We only handle them for UART1 here.
- */
-static void assabet_set_mctrl(struct uart_port *port, u_int mctrl)
-{
-       if (port->mapbase == _Ser1UTCR0) {
-               u_int set = 0, clear = 0;
-
-               if (mctrl & TIOCM_RTS)
-                       clear |= ASSABET_BCR_COM_RTS;
+                       ASSABET_BCR_clear(ASSABET_BCR_RS232EN);
                else
-                       set |= ASSABET_BCR_COM_RTS;
-
-               if (mctrl & TIOCM_DTR)
-                       clear |= ASSABET_BCR_COM_DTR;
-               else
-                       set |= ASSABET_BCR_COM_DTR;
-
-               ASSABET_BCR_clear(clear);
-               ASSABET_BCR_set(set);
-       }
-}
-
-static u_int assabet_get_mctrl(struct uart_port *port)
-{
-       u_int ret = 0;
-       u_int bsr = ASSABET_BSR;
-
-       /* need 2 reads to read current value */
-       bsr = ASSABET_BSR;
-
-       if (port->mapbase == _Ser1UTCR0) {
-               if (bsr & ASSABET_BSR_COM_DCD)
-                       ret |= TIOCM_CD;
-               if (bsr & ASSABET_BSR_COM_CTS)
-                       ret |= TIOCM_CTS;
-               if (bsr & ASSABET_BSR_COM_DSR)
-                       ret |= TIOCM_DSR;
-       } else if (port->mapbase == _Ser3UTCR0) {
-               if (bsr & ASSABET_BSR_RAD_DCD)
-                       ret |= TIOCM_CD;
-               if (bsr & ASSABET_BSR_RAD_CTS)
-                       ret |= TIOCM_CTS;
-               if (bsr & ASSABET_BSR_RAD_DSR)
-                       ret |= TIOCM_DSR;
-               if (bsr & ASSABET_BSR_RAD_RI)
-                       ret |= TIOCM_RI;
-       } else {
-               ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
+                       ASSABET_BCR_set(ASSABET_BCR_RS232EN);
        }
-
-       return ret;
 }
 
 static struct sa1100_port_fns assabet_port_fns __initdata = {
-       .set_mctrl      = assabet_set_mctrl,
-       .get_mctrl      = assabet_get_mctrl,
        .pm             = assabet_uart_pm,
 };
 
index 63361b6..17d28b4 100644 (file)
@@ -315,8 +315,6 @@ badge4_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
 }
 
 static struct sa1100_port_fns badge4_port_fns __initdata = {
-       //.get_mctrl    = badge4_get_mctrl,
-       //.set_mctrl    = badge4_set_mctrl,
        .pm             = badge4_uart_pm,
 };
 
index 6199e87..e869192 100644 (file)
 /*
  *  linux/arch/arm/mach-sa1100/clock.c
  */
-#include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/err.h>
-#include <linux/string.h>
 #include <linux/clk.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
 #include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
 
 #include <mach/hardware.h>
 #include <mach/generic.h>
 
-struct clkops {
-       void                    (*enable)(struct clk *);
-       void                    (*disable)(struct clk *);
-       unsigned long           (*get_rate)(struct clk *);
+static const char * const clk_tucr_parents[] = {
+       "clk32768", "clk3686400",
 };
 
-struct clk {
-       const struct clkops     *ops;
-       unsigned int            enabled;
-};
-
-#define DEFINE_CLK(_name, _ops)                                \
-struct clk clk_##_name = {                             \
-               .ops    = _ops,                         \
-       }
-
-static DEFINE_SPINLOCK(clocks_lock);
-
-/* Dummy clk routine to build generic kernel parts that may be using them */
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-       return clk_get_rate(clk);
-}
-EXPORT_SYMBOL(clk_round_rate);
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-       return 0;
-}
-EXPORT_SYMBOL(clk_set_rate);
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-       return 0;
-}
-EXPORT_SYMBOL(clk_set_parent);
+static DEFINE_SPINLOCK(tucr_lock);
 
-struct clk *clk_get_parent(struct clk *clk)
+static int clk_gpio27_enable(struct clk_hw *hw)
 {
-       return NULL;
-}
-EXPORT_SYMBOL(clk_get_parent);
+       unsigned long flags;
 
-static void clk_gpio27_enable(struct clk *clk)
-{
        /*
         * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
         * (SA-1110 Developer's Manual, section 9.1.2.1)
         */
+       local_irq_save(flags);
        GAFR |= GPIO_32_768kHz;
        GPDR |= GPIO_32_768kHz;
-       TUCR = TUCR_3_6864MHz;
+       local_irq_restore(flags);
+
+       return 0;
 }
 
-static void clk_gpio27_disable(struct clk *clk)
+static void clk_gpio27_disable(struct clk_hw *hw)
 {
-       TUCR = 0;
+       unsigned long flags;
+
+       local_irq_save(flags);
        GPDR &= ~GPIO_32_768kHz;
        GAFR &= ~GPIO_32_768kHz;
+       local_irq_restore(flags);
 }
 
-static void clk_cpu_enable(struct clk *clk)
-{
-}
+static const struct clk_ops clk_gpio27_ops = {
+       .enable = clk_gpio27_enable,
+       .disable = clk_gpio27_disable,
+};
 
-static void clk_cpu_disable(struct clk *clk)
-{
-}
+static const char * const clk_gpio27_parents[] = {
+       "tucr-mux",
+};
 
-static unsigned long clk_cpu_get_rate(struct clk *clk)
+static const struct clk_init_data clk_gpio27_init_data __initconst = {
+       .name = "gpio27",
+       .ops = &clk_gpio27_ops,
+       .parent_names = clk_gpio27_parents,
+       .num_parents = ARRAY_SIZE(clk_gpio27_parents),
+};
+
+/*
+ * Derived from the table 8-1 in the SA1110 manual, the MPLL appears to
+ * multiply its input rate by 4 x (4 + PPCR).  This calculation gives
+ * the exact rate.  The figures given in the table are the rates rounded
+ * to 100kHz.  Stick with sa11x0_getspeed() for the time being.
+ */
+static unsigned long clk_mpll_recalc_rate(struct clk_hw *hw,
+       unsigned long prate)
 {
        return sa11x0_getspeed(0) * 1000;
 }
 
-int clk_enable(struct clk *clk)
-{
-       unsigned long flags;
-
-       if (clk) {
-               spin_lock_irqsave(&clocks_lock, flags);
-               if (clk->enabled++ == 0)
-                       clk->ops->enable(clk);
-               spin_unlock_irqrestore(&clocks_lock, flags);
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(clk_enable);
+static const struct clk_ops clk_mpll_ops = {
+       .recalc_rate = clk_mpll_recalc_rate,
+};
 
-void clk_disable(struct clk *clk)
-{
-       unsigned long flags;
+static const char * const clk_mpll_parents[] = {
+       "clk3686400",
+};
 
-       if (clk) {
-               WARN_ON(clk->enabled == 0);
-               spin_lock_irqsave(&clocks_lock, flags);
-               if (--clk->enabled == 0)
-                       clk->ops->disable(clk);
-               spin_unlock_irqrestore(&clocks_lock, flags);
-       }
-}
-EXPORT_SYMBOL(clk_disable);
+static const struct clk_init_data clk_mpll_init_data __initconst = {
+       .name = "mpll",
+       .ops = &clk_mpll_ops,
+       .parent_names = clk_mpll_parents,
+       .num_parents = ARRAY_SIZE(clk_mpll_parents),
+       .flags = CLK_GET_RATE_NOCACHE | CLK_IS_CRITICAL,
+};
 
-unsigned long clk_get_rate(struct clk *clk)
+int __init sa11xx_clk_init(void)
 {
-       if (clk && clk->ops && clk->ops->get_rate)
-               return clk->ops->get_rate(clk);
-
-       return 0;
-}
-EXPORT_SYMBOL(clk_get_rate);
+       struct clk_hw *hw;
+       int ret;
 
-const struct clkops clk_gpio27_ops = {
-       .enable         = clk_gpio27_enable,
-       .disable        = clk_gpio27_disable,
-};
+       hw = clk_hw_register_fixed_rate(NULL, "clk32768", NULL, 0, 32768);
+       if (IS_ERR(hw))
+               return PTR_ERR(hw);
 
-const struct clkops clk_cpu_ops = {
-       .enable         = clk_cpu_enable,
-       .disable        = clk_cpu_disable,
-       .get_rate       = clk_cpu_get_rate,
-};
+       clk_hw_register_clkdev(hw, NULL, "sa1100-rtc");
 
-static DEFINE_CLK(gpio27, &clk_gpio27_ops);
+       hw = clk_hw_register_fixed_rate(NULL, "clk3686400", NULL, 0, 3686400);
+       if (IS_ERR(hw))
+               return PTR_ERR(hw);
 
-static DEFINE_CLK(cpu, &clk_cpu_ops);
+       clk_hw_register_clkdev(hw, "OSTIMER0", NULL);
 
-static unsigned long clk_36864_get_rate(struct clk *clk)
-{
-       return 3686400;
-}
+       hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+       if (!hw)
+               return -ENOMEM;
+       hw->init = &clk_mpll_init_data;
+       ret = clk_hw_register(NULL, hw);
+       if (ret) {
+               kfree(hw);
+               return ret;
+       }
 
-static struct clkops clk_36864_ops = {
-       .enable         = clk_cpu_enable,
-       .disable        = clk_cpu_disable,
-       .get_rate       = clk_36864_get_rate,
-};
+       clk_hw_register_clkdev(hw, NULL, "sa11x0-fb");
+       clk_hw_register_clkdev(hw, NULL, "sa11x0-pcmcia");
+       clk_hw_register_clkdev(hw, NULL, "sa11x0-pcmcia.0");
+       clk_hw_register_clkdev(hw, NULL, "sa11x0-pcmcia.1");
+       clk_hw_register_clkdev(hw, NULL, "1800");
+
+       hw = clk_hw_register_mux(NULL, "tucr-mux", clk_tucr_parents,
+                                ARRAY_SIZE(clk_tucr_parents), 0,
+                                (void __iomem *)&TUCR, FShft(TUCR_TSEL),
+                                FAlnMsk(TUCR_TSEL), 0, &tucr_lock);
+       clk_set_rate(hw->clk, 3686400);
+
+       hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+       if (!hw)
+               return -ENOMEM;
+       hw->init = &clk_gpio27_init_data;
+       ret = clk_hw_register(NULL, hw);
+       if (ret) {
+               kfree(hw);
+               return ret;
+       }
 
-static DEFINE_CLK(36864, &clk_36864_ops);
-
-static struct clk_lookup sa11xx_clkregs[] = {
-       CLKDEV_INIT("sa1111.0", NULL, &clk_gpio27),
-       CLKDEV_INIT("sa1100-rtc", NULL, NULL),
-       CLKDEV_INIT("sa11x0-fb", NULL, &clk_cpu),
-       CLKDEV_INIT("sa11x0-pcmcia", NULL, &clk_cpu),
-       CLKDEV_INIT("sa11x0-pcmcia.0", NULL, &clk_cpu),
-       CLKDEV_INIT("sa11x0-pcmcia.1", NULL, &clk_cpu),
-       /* sa1111 names devices using internal offsets, PCMCIA is at 0x1800 */
-       CLKDEV_INIT("1800", NULL, &clk_cpu),
-       CLKDEV_INIT(NULL, "OSTIMER0", &clk_36864),
-};
+       clk_hw_register_clkdev(hw, NULL, "sa1111.0");
 
-int __init sa11xx_clk_init(void)
-{
-       clkdev_add_table(sa11xx_clkregs, ARRAY_SIZE(sa11xx_clkregs));
        return 0;
 }
index 36a78b0..e736229 100644 (file)
@@ -87,57 +87,6 @@ static struct resource h3xxx_flash_resource =
 /*
  * H3xxx uart support
  */
-static struct gpio h3xxx_uart_gpio[] = {
-       { H3XXX_GPIO_COM_DCD,   GPIOF_IN,               "COM DCD" },
-       { H3XXX_GPIO_COM_CTS,   GPIOF_IN,               "COM CTS" },
-       { H3XXX_GPIO_COM_RTS,   GPIOF_OUT_INIT_LOW,     "COM RTS" },
-};
-
-static bool h3xxx_uart_request_gpios(void)
-{
-       static bool h3xxx_uart_gpio_ok;
-       int rc;
-
-       if (h3xxx_uart_gpio_ok)
-               return true;
-
-       rc = gpio_request_array(h3xxx_uart_gpio, ARRAY_SIZE(h3xxx_uart_gpio));
-       if (rc)
-               pr_err("h3xxx_uart_request_gpios: error %d\n", rc);
-       else
-               h3xxx_uart_gpio_ok = true;
-
-       return h3xxx_uart_gpio_ok;
-}
-
-static void h3xxx_uart_set_mctrl(struct uart_port *port, u_int mctrl)
-{
-       if (port->mapbase == _Ser3UTCR0) {
-               if (!h3xxx_uart_request_gpios())
-                       return;
-               gpio_set_value(H3XXX_GPIO_COM_RTS, !(mctrl & TIOCM_RTS));
-       }
-}
-
-static u_int h3xxx_uart_get_mctrl(struct uart_port *port)
-{
-       u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
-
-       if (port->mapbase == _Ser3UTCR0) {
-               if (!h3xxx_uart_request_gpios())
-                       return ret;
-               /*
-                * DCD and CTS bits are inverted in GPLR by RS232 transceiver
-                */
-               if (gpio_get_value(H3XXX_GPIO_COM_DCD))
-                       ret &= ~TIOCM_CD;
-               if (gpio_get_value(H3XXX_GPIO_COM_CTS))
-                       ret &= ~TIOCM_CTS;
-       }
-
-       return ret;
-}
-
 static void h3xxx_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
 {
        if (port->mapbase == _Ser3UTCR0) {
@@ -170,12 +119,20 @@ static int h3xxx_uart_set_wake(struct uart_port *port, u_int enable)
 }
 
 static struct sa1100_port_fns h3xxx_port_fns __initdata = {
-       .set_mctrl      = h3xxx_uart_set_mctrl,
-       .get_mctrl      = h3xxx_uart_get_mctrl,
        .pm             = h3xxx_uart_pm,
        .set_wake       = h3xxx_uart_set_wake,
 };
 
+static struct gpiod_lookup_table h3xxx_uart3_gpio_table = {
+       .dev_id = "sa11x0-uart.3",
+       .table = {
+               GPIO_LOOKUP("gpio", H3XXX_GPIO_COM_DCD, "dcd", GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP("gpio", H3XXX_GPIO_COM_CTS, "cts", GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP("gpio", H3XXX_GPIO_COM_RTS, "rts", GPIO_ACTIVE_LOW),
+               { },
+       },
+};
+
 /*
  * EGPIO
  */
@@ -283,6 +240,7 @@ static struct gpiod_lookup_table h3xxx_pcmcia_gpio_table = {
 void __init h3xxx_mach_init(void)
 {
        gpiod_add_lookup_table(&h3xxx_pcmcia_gpio_table);
+       gpiod_add_lookup_table(&h3xxx_uart3_gpio_table);
        sa1100_register_uart_fns(&h3xxx_port_fns);
        sa11x0_register_mtd(&h3xxx_flash_data, &h3xxx_flash_resource, 1);
        platform_add_devices(h3xxx_devices, ARRAY_SIZE(h3xxx_devices));
index 643d5f2..9faf602 100644 (file)
@@ -49,8 +49,6 @@
 /* init funcs */
 static void __init hackkit_map_io(void);
 
-static u_int hackkit_get_mctrl(struct uart_port *port);
-static void hackkit_set_mctrl(struct uart_port *port, u_int mctrl);
 static void hackkit_uart_pm(struct uart_port *port, u_int state, u_int oldstate);
 
 /**********************************************************************
@@ -71,8 +69,6 @@ static struct map_desc hackkit_io_desc[] __initdata = {
 };
 
 static struct sa1100_port_fns hackkit_port_fns __initdata = {
-       .set_mctrl      = hackkit_set_mctrl,
-       .get_mctrl      = hackkit_get_mctrl,
        .pm             = hackkit_uart_pm,
 };
 
@@ -105,50 +101,6 @@ static void hackkit_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
        /* TODO: switch on/off uart in powersave mode */
 }
 
-/*
- * Note! this can be called from IRQ context.
- * FIXME: No modem ctrl lines yet.
- */
-static void hackkit_set_mctrl(struct uart_port *port, u_int mctrl)
-{
-#if 0
-       if (port->mapbase == _Ser1UTCR0) {
-               u_int set = 0, clear = 0;
-
-               if (mctrl & TIOCM_RTS)
-                       set |= PT_CTRL2_RS1_RTS;
-               else
-                       clear |= PT_CTRL2_RS1_RTS;
-
-               if (mctrl & TIOCM_DTR)
-                       set |= PT_CTRL2_RS1_DTR;
-               else
-                       clear |= PT_CTRL2_RS1_DTR;
-
-               PTCTRL2_clear(clear);
-               PTCTRL2_set(set);
-       }
-#endif
-}
-
-static u_int hackkit_get_mctrl(struct uart_port *port)
-{
-       u_int ret = 0;
-#if 0
-       u_int irqsr = PT_IRQSR;
-
-       /* need 2 reads to read current value */
-       irqsr = PT_IRQSR;
-
-       /* TODO: check IRQ source register for modem/com
-        status lines and set them correctly. */
-#endif
-
-       ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
-
-       return ret;
-}
-
 static struct mtd_partition hackkit_partitions[] = {
        {
                .name           = "BLOB",
index a671e4c..6876bc1 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/platform_data/sa11x0-serial.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/serial_core.h>
 #define IRR_SA1111     (1 << 2)
 
 #define NCR_NGPIO      7
-
-#define MDM_CTL0_RTS1  (1 << 0)
-#define MDM_CTL0_DTR1  (1 << 1)
-#define MDM_CTL0_RTS2  (1 << 2)
-#define MDM_CTL0_DTR2  (1 << 3)
 #define MDM_CTL0_NGPIO 4
-
-#define MDM_CTL1_CTS1  (1 << 0)
-#define MDM_CTL1_DSR1  (1 << 1)
-#define MDM_CTL1_DCD1  (1 << 2)
-#define MDM_CTL1_CTS2  (1 << 3)
-#define MDM_CTL1_DSR2  (1 << 4)
-#define MDM_CTL1_DCD2  (1 << 5)
 #define MDM_CTL1_NGPIO 6
-
-#define AUD_SEL_1341   (1 << 0)
-#define AUD_MUTE_1341  (1 << 1)
 #define AUD_NGPIO      2
 
 extern void sa1110_mb_disable(void);
@@ -97,6 +81,30 @@ struct neponset_drvdata {
        struct gpio_chip *gpio[4];
 };
 
+static struct gpiod_lookup_table neponset_uart1_gpio_table = {
+       .dev_id = "sa11x0-uart.1",
+       .table = {
+               GPIO_LOOKUP("neponset-mdm-ctl0", 2, "rts", GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP("neponset-mdm-ctl0", 3, "dtr", GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP("neponset-mdm-ctl1", 3, "cts", GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP("neponset-mdm-ctl1", 4, "dsr", GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP("neponset-mdm-ctl1", 5, "dcd", GPIO_ACTIVE_LOW),
+               { },
+       },
+};
+
+static struct gpiod_lookup_table neponset_uart3_gpio_table = {
+       .dev_id = "sa11x0-uart.3",
+       .table = {
+               GPIO_LOOKUP("neponset-mdm-ctl0", 0, "rts", GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP("neponset-mdm-ctl0", 1, "dtr", GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP("neponset-mdm-ctl1", 0, "cts", GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP("neponset-mdm-ctl1", 1, "dsr", GPIO_ACTIVE_LOW),
+               GPIO_LOOKUP("neponset-mdm-ctl1", 2, "dcd", GPIO_ACTIVE_LOW),
+               { },
+       },
+};
+
 static struct gpiod_lookup_table neponset_pcmcia_table = {
        .dev_id = "1800",
        .table = {
@@ -124,69 +132,6 @@ void neponset_ncr_frob(unsigned int mask, unsigned int val)
 }
 EXPORT_SYMBOL(neponset_ncr_frob);
 
-static void neponset_set_mctrl(struct uart_port *port, u_int mctrl)
-{
-       struct neponset_drvdata *n = nep;
-       unsigned long mask, val = 0;
-
-       if (!n)
-               return;
-
-       if (port->mapbase == _Ser1UTCR0) {
-               mask = MDM_CTL0_RTS2 | MDM_CTL0_DTR2;
-
-               if (!(mctrl & TIOCM_RTS))
-                       val |= MDM_CTL0_RTS2;
-
-               if (!(mctrl & TIOCM_DTR))
-                       val |= MDM_CTL0_DTR2;
-       } else if (port->mapbase == _Ser3UTCR0) {
-               mask = MDM_CTL0_RTS1 | MDM_CTL0_DTR1;
-
-               if (!(mctrl & TIOCM_RTS))
-                       val |= MDM_CTL0_RTS1;
-
-               if (!(mctrl & TIOCM_DTR))
-                       val |= MDM_CTL0_DTR1;
-       }
-
-       n->gpio[1]->set_multiple(n->gpio[1], &mask, &val);
-}
-
-static u_int neponset_get_mctrl(struct uart_port *port)
-{
-       void __iomem *base = nep->base;
-       u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
-       u_int mdm_ctl1;
-
-       if (!base)
-               return ret;
-
-       mdm_ctl1 = readb_relaxed(base + MDM_CTL_1);
-       if (port->mapbase == _Ser1UTCR0) {
-               if (mdm_ctl1 & MDM_CTL1_DCD2)
-                       ret &= ~TIOCM_CD;
-               if (mdm_ctl1 & MDM_CTL1_CTS2)
-                       ret &= ~TIOCM_CTS;
-               if (mdm_ctl1 & MDM_CTL1_DSR2)
-                       ret &= ~TIOCM_DSR;
-       } else if (port->mapbase == _Ser3UTCR0) {
-               if (mdm_ctl1 & MDM_CTL1_DCD1)
-                       ret &= ~TIOCM_CD;
-               if (mdm_ctl1 & MDM_CTL1_CTS1)
-                       ret &= ~TIOCM_CTS;
-               if (mdm_ctl1 & MDM_CTL1_DSR1)
-                       ret &= ~TIOCM_DSR;
-       }
-
-       return ret;
-}
-
-static struct sa1100_port_fns neponset_port_fns = {
-       .set_mctrl      = neponset_set_mctrl,
-       .get_mctrl      = neponset_get_mctrl,
-};
-
 /*
  * Install handler for Neponset IRQ.  Note that we have to loop here
  * since the ETHERNET and USAR IRQs are level based, and we need to
@@ -388,6 +333,8 @@ static int neponset_probe(struct platform_device *dev)
                           d->base + AUD_CTL, AUD_NGPIO, false,
                           neponset_aud_names);
 
+       gpiod_add_lookup_table(&neponset_uart1_gpio_table);
+       gpiod_add_lookup_table(&neponset_uart3_gpio_table);
        gpiod_add_lookup_table(&neponset_pcmcia_table);
 
        /*
@@ -402,8 +349,6 @@ static int neponset_probe(struct platform_device *dev)
                 d->irq_base, d->irq_base + NEP_IRQ_NR - 1);
        nep = d;
 
-       sa1100_register_uart_fns(&neponset_port_fns);
-
        /* Ensure that the memory bus request/grant signals are setup */
        sa1110_mb_disable();
 
@@ -442,6 +387,8 @@ static int neponset_remove(struct platform_device *dev)
                platform_device_unregister(d->smc91x);
 
        gpiod_remove_lookup_table(&neponset_pcmcia_table);
+       gpiod_remove_lookup_table(&neponset_uart3_gpio_table);
+       gpiod_remove_lookup_table(&neponset_uart1_gpio_table);
 
        irq_set_chained_handler(irq, NULL);
        irq_free_descs(d->irq_base, NEP_IRQ_NR);
index 0d31251..2c86d19 100644 (file)
@@ -511,6 +511,7 @@ config SERIAL_SA1100
        bool "SA1100 serial port support"
        depends on ARCH_SA1100
        select SERIAL_CORE
+       select SERIAL_MCTRL_GPIO if GPIOLIB
        help
          If you have a machine based on a SA1100/SA1110 StrongARM(R) CPU you
          can enable its onboard serial port by enabling this option.
index a399772..8e61812 100644 (file)
@@ -28,6 +28,8 @@
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 
+#include "serial_mctrl_gpio.h"
+
 /* We've been assigned a range on the "Low-density serial ports" major */
 #define SERIAL_SA1100_MAJOR    204
 #define MINOR_START            5
@@ -77,6 +79,7 @@ struct sa1100_port {
        struct uart_port        port;
        struct timer_list       timer;
        unsigned int            old_status;
+       struct mctrl_gpios      *gpios;
 };
 
 /*
@@ -174,6 +177,8 @@ static void sa1100_enable_ms(struct uart_port *port)
                container_of(port, struct sa1100_port, port);
 
        mod_timer(&sport->timer, jiffies);
+
+       mctrl_gpio_enable_ms(sport->gpios);
 }
 
 static void
@@ -322,11 +327,21 @@ static unsigned int sa1100_tx_empty(struct uart_port *port)
 
 static unsigned int sa1100_get_mctrl(struct uart_port *port)
 {
-       return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+       struct sa1100_port *sport =
+               container_of(port, struct sa1100_port, port);
+       int ret = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+
+       mctrl_gpio_get(sport->gpios, &ret);
+
+       return ret;
 }
 
 static void sa1100_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
+       struct sa1100_port *sport =
+               container_of(port, struct sa1100_port, port);
+
+       mctrl_gpio_set(sport->gpios, mctrl);
 }
 
 /*
@@ -842,6 +857,31 @@ static int sa1100_serial_resume(struct platform_device *dev)
        return 0;
 }
 
+static int sa1100_serial_add_one_port(struct sa1100_port *sport, struct platform_device *dev)
+{
+       sport->port.dev = &dev->dev;
+
+       // mctrl_gpio_init() requires that the GPIO driver supports interrupts,
+       // but we need to support GPIO drivers for hardware that has no such
+       // interrupts.  Use mctrl_gpio_init_noauto() instead.
+       sport->gpios = mctrl_gpio_init_noauto(sport->port.dev, 0);
+       if (IS_ERR(sport->gpios)) {
+               int err = PTR_ERR(sport->gpios);
+
+               dev_err(sport->port.dev, "failed to get mctrl gpios: %d\n",
+                       err);
+
+               if (err == -EPROBE_DEFER)
+                       return err;
+
+               sport->gpios = NULL;
+       }
+
+       platform_set_drvdata(dev, sport);
+
+       return uart_add_one_port(&sa1100_reg, &sport->port);
+}
+
 static int sa1100_serial_probe(struct platform_device *dev)
 {
        struct resource *res = dev->resource;
@@ -856,9 +896,7 @@ static int sa1100_serial_probe(struct platform_device *dev)
                        if (sa1100_ports[i].port.mapbase != res->start)
                                continue;
 
-                       sa1100_ports[i].port.dev = &dev->dev;
-                       uart_add_one_port(&sa1100_reg, &sa1100_ports[i].port);
-                       platform_set_drvdata(dev, &sa1100_ports[i]);
+                       sa1100_serial_add_one_port(&sa1100_ports[i], dev);
                        break;
                }
        }