sh: mach-sdk7786: FPGA updates.

This does a bit of refactoring of the FPGA management code. The primary
FPGA initialization is moved out to its own file in preparation for
implementing some of the more complex capabilities, a complete set of
register definitions is provided, and all of the existing users in the
board code are moved over to use the new interface instead of setting up
overlapping mappings. This also corrects the FPGA size, which previously
was chomped off at the SDIF control register.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
diff --git a/arch/sh/boards/mach-sdk7786/Makefile b/arch/sh/boards/mach-sdk7786/Makefile
index f663768..50c8065 100644
--- a/arch/sh/boards/mach-sdk7786/Makefile
+++ b/arch/sh/boards/mach-sdk7786/Makefile
@@ -1 +1 @@
-obj-y	:= setup.o
+obj-y	:= setup.o fpga.o
diff --git a/arch/sh/boards/mach-sdk7786/fpga.c b/arch/sh/boards/mach-sdk7786/fpga.c
new file mode 100644
index 0000000..99f903c
--- /dev/null
+++ b/arch/sh/boards/mach-sdk7786/fpga.c
@@ -0,0 +1,37 @@
+/*
+ * SDK7786 FPGA Support.
+ *
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/bcd.h>
+#include <mach/fpga.h>
+
+#define FPGA_REGS_BASE	0x07fff800
+#define FPGA_REGS_SIZE	0x490
+
+void __iomem *sdk7786_fpga_base;
+
+void __init sdk7786_fpga_init(void)
+{
+	u16 version, date;
+
+	sdk7786_fpga_base = ioremap_nocache(FPGA_REGS_BASE, FPGA_REGS_SIZE);
+	if (unlikely(!sdk7786_fpga_base)) {
+		panic("FPGA remapping failed.\n");
+		return;
+	}
+
+	version = fpga_read_reg(FPGAVR);
+	date = fpga_read_reg(FPGADR);
+
+	pr_info("\tFPGA version:\t%d.%d (built on %d/%d/%d)\n",
+		bcd2bin(version >> 8) & 0xf, bcd2bin(version & 0xf),
+		((date >> 12) & 0xf) + 2000,
+		(date >> 8) & 0xf, bcd2bin(date & 0xff));
+}
diff --git a/arch/sh/boards/mach-sdk7786/setup.c b/arch/sh/boards/mach-sdk7786/setup.c
index 0e4b1c3..8dbbdea 100644
--- a/arch/sh/boards/mach-sdk7786/setup.c
+++ b/arch/sh/boards/mach-sdk7786/setup.c
@@ -18,6 +18,7 @@
 #include <asm/machvec.h>
 #include <asm/heartbeat.h>
 #include <asm/sizes.h>
+#include <mach/fpga.h>
 
 static struct resource heartbeat_resource = {
 	.start		= 0x07fff8b0,
@@ -103,27 +104,17 @@
 	&smbus_pcie_device,
 };
 
-#define SBCR_REGS_BASE	0x07fff990
-
-#define SCBR_I2CMEN	(1 << 0)	/* FPGA I2C master enable */
-#define SCBR_I2CCEN	(1 << 1)	/* CPU I2C master enable */
-
 static int sdk7786_i2c_setup(void)
 {
-	void __iomem *sbcr;
 	unsigned int tmp;
 
-	sbcr = ioremap_nocache(SBCR_REGS_BASE, SZ_16);
-
 	/*
 	 * Hand over I2C control to the FPGA.
 	 */
-	tmp = ioread16(sbcr);
+	tmp = fpga_read_reg(SBCR);
 	tmp &= ~SCBR_I2CCEN;
 	tmp |= SCBR_I2CMEN;
-	iowrite16(tmp, sbcr);
-
-	iounmap(sbcr);
+	fpga_write_reg(tmp, SBCR);
 
 	return i2c_register_board_info(0, sdk7786_i2c_devices,
 				       ARRAY_SIZE(sdk7786_i2c_devices));
@@ -141,43 +132,6 @@
 }
 __initcall(sdk7786_devices_setup);
 
-#define FPGA_REGS_BASE	0x07fff800
-#define FPGA_REGS_SIZE	1152
-
-#define INTASR		0x010
-#define INTAMR		0x020
-#define INTBSR		0x090
-#define INTBMR		0x0a0
-#define INTMSR		0x130
-
-#define IASELR1		0x210
-#define IASELR2		0x220
-#define IASELR3		0x230
-#define IASELR4		0x240
-#define IASELR5		0x250
-#define IASELR6		0x260
-#define IASELR7		0x270
-#define IASELR8		0x280
-#define IASELR9		0x290
-#define IASELR10	0x2a0
-#define IASELR11	0x2b0
-#define IASELR12	0x2c0
-#define IASELR13	0x2d0
-#define IASELR14	0x2e0
-#define IASELR15	0x2f0
-
-static void __iomem *fpga_regs;
-
-static u16 fpga_read_reg(unsigned int reg)
-{
-	return __raw_readw(fpga_regs + reg);
-}
-
-static void fpga_write_reg(u16 val, unsigned int reg)
-{
-	__raw_writew(val, fpga_regs + reg);
-}
-
 enum {
 	ATA_IRQ_BIT		= 1,
 	SPI_BUSY_BIT		= 2,
@@ -197,12 +151,6 @@
 {
 	unsigned int tmp;
 
-	fpga_regs = ioremap_nocache(FPGA_REGS_BASE, FPGA_REGS_SIZE);
-	if (!fpga_regs) {
-		printk(KERN_ERR "Couldn't map FPGA registers\n");
-		return;
-	}
-
 	/* Enable priority encoding for all IRLs */
 	fpga_write_reg(fpga_read_reg(INTMSR) | 0x0303, INTMSR);
 
@@ -219,21 +167,9 @@
 	plat_irq_setup_pins(IRQ_MODE_IRL3210_MASK);
 }
 
-#define MODSWR_REGS	0x07fff830
-
 static int sdk7786_mode_pins(void)
 {
-	void __iomem *modswr;
-	int pin_states;
-
-	modswr = ioremap_nocache(MODSWR_REGS, SZ_16);
-	if (!modswr)
-		return -ENXIO;
-
-	pin_states = ioread16(modswr);
-	iounmap(modswr);
-
-	return pin_states;
+	return fpga_read_reg(MODSWR);
 }
 
 static int sdk7786_clk_init(void)
@@ -260,7 +196,11 @@
 /* Initialize the board */
 static void __init sdk7786_setup(char **cmdline_p)
 {
-	printk(KERN_INFO "Renesas Technology Corp. SDK7786 support.\n");
+	pr_info("Renesas Technology Europe SDK7786 support:\n");
+
+	sdk7786_fpga_init();
+
+	pr_info("\tPCB revision:\t%d\n", fpga_read_reg(PCBRR) & 0xf);
 }
 
 /*
diff --git a/arch/sh/include/mach-sdk7786/mach/fpga.h b/arch/sh/include/mach-sdk7786/mach/fpga.h
new file mode 100644
index 0000000..a85d985
--- /dev/null
+++ b/arch/sh/include/mach-sdk7786/mach/fpga.h
@@ -0,0 +1,112 @@
+#ifndef __MACH_SDK7786_FPGA_H
+#define __MACH_SDK7786_FPGA_H
+
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+
+#define SRSTR		0x000
+#define INTASR		0x010
+#define INTAMR		0x020
+#define MODSWR		0x030
+#define INTTESTR	0x040
+#define SYSSR		0x050
+#define NRGPR		0x060
+#define NMISR		0x070
+
+#define NMIMR		0x080
+#define  NMIMR_MAN_NMIM	BIT(0)	/* Manual NMI mask */
+#define  NMIMR_AUX_NMIM	BIT(1)	/* Auxiliary NMI mask */
+
+#define INTBSR		0x090
+#define INTBMR		0x0a0
+#define USRLEDR		0x0b0
+#define MAPSWR		0x0c0
+#define FPGAVR		0x0d0
+#define FPGADR		0x0e0
+#define PCBRR		0x0f0
+#define RSR		0x100
+#define EXTASR		0x110
+#define SPCAR		0x120
+#define INTMSR		0x130
+#define PCIECR		0x140
+#define FAER		0x150
+#define USRGPIR		0x160
+/* 0x170 reserved */
+#define LCLASR		0x180
+
+#define SBCR		0x190
+#define  SCBR_I2CMEN	BIT(0)	/* FPGA I2C master enable */
+#define  SCBR_I2CCEN	BIT(1)	/* CPU I2C master enable */
+
+#define PWRCR		0x1a0
+#define SPCBR		0x1b0
+#define SPICR		0x1c0
+#define SPIDR		0x1d0
+#define I2CCR		0x1e0
+#define I2CDR		0x1f0
+#define FPGACR		0x200
+#define IASELR1		0x210
+#define IASELR2		0x220
+#define IASELR3		0x230
+#define IASELR4		0x240
+#define IASELR5		0x250
+#define IASELR6		0x260
+#define IASELR7		0x270
+#define IASELR8		0x280
+#define IASELR9		0x290
+#define IASELR10	0x2a0
+#define IASELR11	0x2b0
+#define IASELR12	0x2c0
+#define IASELR13	0x2d0
+#define IASELR14	0x2e0
+#define IASELR15	0x2f0
+/* 0x300 reserved */
+#define IBSELR1		0x310
+#define IBSELR2		0x320
+#define IBSELR3		0x330
+#define IBSELR4		0x340
+#define IBSELR5		0x350
+#define IBSELR6		0x360
+#define IBSELR7		0x370
+#define IBSELR8		0x380
+#define IBSELR9		0x390
+#define IBSELR10	0x3a0
+#define IBSELR11	0x3b0
+#define IBSELR12	0x3c0
+#define IBSELR13	0x3d0
+#define IBSELR14	0x3e0
+#define IBSELR15	0x3f0
+#define USRACR		0x400
+#define BEEPR		0x410
+#define USRLCDR		0x420
+#define SMBCR		0x430
+#define SMBDR		0x440
+#define USBCR		0x450
+#define AMSR		0x460
+#define ACCR		0x470
+#define SDIFCR		0x480
+
+/* arch/sh/boards/mach-sdk7786/fpga.c */
+extern void __iomem *sdk7786_fpga_base;
+extern void sdk7786_fpga_init(void);
+
+#define SDK7786_FPGA_REGADDR(reg)	(sdk7786_fpga_base + (reg))
+
+/*
+ * A convenience wrapper from register offset to internal I2C address,
+ * when the FPGA is in I2C slave mode.
+ */
+#define SDK7786_FPGA_I2CADDR(reg)	((reg) >> 3)
+
+static inline u16 fpga_read_reg(unsigned int reg)
+{
+	return ioread16(sdk7786_fpga_base + reg);
+}
+
+static inline void fpga_write_reg(u16 val, unsigned int reg)
+{
+	iowrite16(val, sdk7786_fpga_base + reg);
+}
+
+#endif /* __MACH_SDK7786_FPGA_H */