Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
[linux-drm-fsl-dcu.git] / arch / mips / mti-sead3 / sead3-pic32-bus.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 2012 MIPS Technologies, Inc.  All rights reserved.
7  */
8 #include <linux/delay.h>
9 #include <linux/kernel.h>
10 #include <linux/spinlock.h>
11 #include <linux/io.h>
12 #include <linux/errno.h>
13
14 #define PIC32_NULL      0x00
15 #define PIC32_RD        0x01
16 #define PIC32_SYSRD     0x02
17 #define PIC32_WR        0x10
18 #define PIC32_SYSWR     0x20
19 #define PIC32_IRQ_CLR   0x40
20 #define PIC32_STATUS    0x80
21
22 #define DELAY() udelay(100)     /* FIXME: needed? */
23
24 /* spinlock to ensure atomic access to PIC32 */
25 static DEFINE_SPINLOCK(pic32_bus_lock);
26
27 /* FIXME: io_remap these */
28 static void __iomem *bus_xfer   = (void __iomem *)0xbf000600;
29 static void __iomem *bus_status = (void __iomem *)0xbf000060;
30
31 static inline unsigned int ioready(void)
32 {
33         return readl(bus_status) & 1;
34 }
35
36 static inline void wait_ioready(void)
37 {
38         do { } while (!ioready());
39 }
40
41 static inline void wait_ioclear(void)
42 {
43         do { } while (ioready());
44 }
45
46 static inline void check_ioclear(void)
47 {
48         if (ioready()) {
49                 pr_debug("ioclear: initially busy\n");
50                 do {
51                         (void) readl(bus_xfer);
52                         DELAY();
53                 } while (ioready());
54                 pr_debug("ioclear: cleared busy\n");
55         }
56 }
57
58 u32 pic32_bus_readl(u32 reg)
59 {
60         unsigned long flags;
61         u32 status, val;
62
63         spin_lock_irqsave(&pic32_bus_lock, flags);
64
65         check_ioclear();
66
67         writel((PIC32_RD << 24) | (reg & 0x00ffffff), bus_xfer);
68         DELAY();
69         wait_ioready();
70         status = readl(bus_xfer);
71         DELAY();
72         val = readl(bus_xfer);
73         wait_ioclear();
74
75         pr_debug("pic32_bus_readl: *%x -> %x (status=%x)\n", reg, val, status);
76
77         spin_unlock_irqrestore(&pic32_bus_lock, flags);
78
79         return val;
80 }
81
82 void pic32_bus_writel(u32 val, u32 reg)
83 {
84         unsigned long flags;
85         u32 status;
86
87         spin_lock_irqsave(&pic32_bus_lock, flags);
88
89         check_ioclear();
90
91         writel((PIC32_WR << 24) | (reg & 0x00ffffff), bus_xfer);
92         DELAY();
93         writel(val, bus_xfer);
94         DELAY();
95         wait_ioready();
96         status = readl(bus_xfer);
97         wait_ioclear();
98
99         pr_debug("pic32_bus_writel: *%x <- %x (status=%x)\n", reg, val, status);
100
101         spin_unlock_irqrestore(&pic32_bus_lock, flags);
102 }