• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/arch/mips/mti-sead3/
1/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
15 */
16
17#include <linux/delay.h>
18#include <linux/kernel.h>
19#include <linux/spinlock.h>
20#include <linux/init.h>
21#include <linux/io.h>
22#include <linux/errno.h>
23
24#define PIC32_NULL	0x00
25#define PIC32_RD	0x01
26#define PIC32_SYSRD	0x02
27#define PIC32_WR	0x10
28#define PIC32_SYSWR	0x20
29#define PIC32_IRQ_CLR   0x40
30#define PIC32_STATUS	0x80
31
32#define DELAY()	udelay(100)
33
34/* spinlock to ensure atomic access to PIC32 */
35static DEFINE_SPINLOCK(pic32_bus_lock);
36
37static void __iomem *bus_xfer   = (void __iomem *)0xbf000600;
38static void __iomem *bus_status = (void __iomem *)0xbf000060;
39
40static inline unsigned int ioready(void)
41{
42	return readl(bus_status) & 1;
43}
44
45static inline void wait_ioready(void)
46{
47	do { } while (!ioready());
48}
49
50static inline void wait_ioclear(void)
51{
52	do { } while (ioready());
53}
54
55static inline void check_ioclear(void)
56{
57	if (ioready()) {
58		pr_debug("ioclear: initially busy\n");
59		do {
60			(void) readl(bus_xfer);
61			DELAY();
62		} while (ioready());
63		pr_debug("ioclear: cleared busy\n");
64	}
65}
66
67u32 pic32_bus_readl(u32 reg)
68{
69	unsigned long flags;
70	u32 status, val;
71
72	spin_lock_irqsave(&pic32_bus_lock, flags);
73
74	check_ioclear();
75
76	writel((PIC32_RD << 24) | (reg & 0x00ffffff), bus_xfer);
77	DELAY();
78	wait_ioready();
79	status = readl(bus_xfer);
80	DELAY();
81	val = readl(bus_xfer);
82	wait_ioclear();
83
84	pr_debug("pic32_bus_readl: *%x -> %x (status=%x)\n", reg, val, status);
85
86	spin_unlock_irqrestore(&pic32_bus_lock, flags);
87
88	return val;
89}
90
91void pic32_bus_writel(u32 val, u32 reg)
92{
93	unsigned long flags;
94	u32 status;
95
96	spin_lock_irqsave(&pic32_bus_lock, flags);
97
98	check_ioclear();
99
100	writel((PIC32_WR << 24) | (reg & 0x00ffffff), bus_xfer);
101	DELAY();
102	writel(val, bus_xfer);
103	DELAY();
104	wait_ioready();
105	status = readl(bus_xfer);
106	wait_ioclear();
107
108	pr_debug("pic32_bus_writel: *%x <- %x (status=%x)\n", reg, val, status);
109
110	spin_unlock_irqrestore(&pic32_bus_lock, flags);
111}
112