diff options
Diffstat (limited to 'arch/sh/boards/mach-sdk7786')
-rw-r--r-- | arch/sh/boards/mach-sdk7786/Makefile | 5 | ||||
-rw-r--r-- | arch/sh/boards/mach-sdk7786/gpio.c | 49 | ||||
-rw-r--r-- | arch/sh/boards/mach-sdk7786/nmi.c | 83 | ||||
-rw-r--r-- | arch/sh/boards/mach-sdk7786/setup.c | 57 | ||||
-rw-r--r-- | arch/sh/boards/mach-sdk7786/sram.c | 72 |
5 files changed, 263 insertions, 3 deletions
diff --git a/arch/sh/boards/mach-sdk7786/Makefile b/arch/sh/boards/mach-sdk7786/Makefile index a29f19e..8ae56e9 100644 --- a/arch/sh/boards/mach-sdk7786/Makefile +++ b/arch/sh/boards/mach-sdk7786/Makefile @@ -1 +1,4 @@ -obj-y := setup.o fpga.o irq.o +obj-y := fpga.o irq.o nmi.o setup.o + +obj-$(CONFIG_GENERIC_GPIO) += gpio.o +obj-$(CONFIG_HAVE_SRAM_POOL) += sram.o diff --git a/arch/sh/boards/mach-sdk7786/gpio.c b/arch/sh/boards/mach-sdk7786/gpio.c new file mode 100644 index 0000000..f71ce09 --- /dev/null +++ b/arch/sh/boards/mach-sdk7786/gpio.c @@ -0,0 +1,49 @@ +/* + * SDK7786 FPGA USRGPIR 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/interrupt.h> +#include <linux/gpio.h> +#include <linux/irq.h> +#include <linux/kernel.h> +#include <linux/spinlock.h> +#include <linux/io.h> +#include <mach/fpga.h> + +#define NR_FPGA_GPIOS 8 + +static const char *usrgpir_gpio_names[NR_FPGA_GPIOS] = { + "in0", "in1", "in2", "in3", "in4", "in5", "in6", "in7", +}; + +static int usrgpir_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) +{ + /* always in */ + return 0; +} + +static int usrgpir_gpio_get(struct gpio_chip *chip, unsigned gpio) +{ + return !!(fpga_read_reg(USRGPIR) & (1 << gpio)); +} + +static struct gpio_chip usrgpir_gpio_chip = { + .label = "sdk7786-fpga", + .names = usrgpir_gpio_names, + .direction_input = usrgpir_gpio_direction_input, + .get = usrgpir_gpio_get, + .base = -1, /* don't care */ + .ngpio = NR_FPGA_GPIOS, +}; + +static int __init usrgpir_gpio_setup(void) +{ + return gpiochip_add(&usrgpir_gpio_chip); +} +device_initcall(usrgpir_gpio_setup); diff --git a/arch/sh/boards/mach-sdk7786/nmi.c b/arch/sh/boards/mach-sdk7786/nmi.c new file mode 100644 index 0000000..edcfa1f --- /dev/null +++ b/arch/sh/boards/mach-sdk7786/nmi.c @@ -0,0 +1,83 @@ +/* + * SDK7786 FPGA NMI 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/kernel.h> +#include <linux/string.h> +#include <mach/fpga.h> + +enum { + NMI_MODE_MANUAL, + NMI_MODE_AUX, + NMI_MODE_MASKED, + NMI_MODE_ANY, + NMI_MODE_UNKNOWN, +}; + +/* + * Default to the manual NMI switch. + */ +static unsigned int __initdata nmi_mode = NMI_MODE_ANY; + +static int __init nmi_mode_setup(char *str) +{ + if (!str) + return 0; + + if (strcmp(str, "manual") == 0) + nmi_mode = NMI_MODE_MANUAL; + else if (strcmp(str, "aux") == 0) + nmi_mode = NMI_MODE_AUX; + else if (strcmp(str, "masked") == 0) + nmi_mode = NMI_MODE_MASKED; + else if (strcmp(str, "any") == 0) + nmi_mode = NMI_MODE_ANY; + else { + nmi_mode = NMI_MODE_UNKNOWN; + pr_warning("Unknown NMI mode %s\n", str); + } + + printk("Set NMI mode to %d\n", nmi_mode); + return 0; +} +early_param("nmi_mode", nmi_mode_setup); + +void __init sdk7786_nmi_init(void) +{ + unsigned int source, mask, tmp; + + switch (nmi_mode) { + case NMI_MODE_MANUAL: + source = NMISR_MAN_NMI; + mask = NMIMR_MAN_NMIM; + break; + case NMI_MODE_AUX: + source = NMISR_AUX_NMI; + mask = NMIMR_AUX_NMIM; + break; + case NMI_MODE_ANY: + source = NMISR_MAN_NMI | NMISR_AUX_NMI; + mask = NMIMR_MAN_NMIM | NMIMR_AUX_NMIM; + break; + case NMI_MODE_MASKED: + case NMI_MODE_UNKNOWN: + default: + source = mask = 0; + break; + } + + /* Set the NMI source */ + tmp = fpga_read_reg(NMISR); + tmp &= ~NMISR_MASK; + tmp |= source; + fpga_write_reg(tmp, NMISR); + + /* And the IRQ masking */ + fpga_write_reg(NMIMR_MASK ^ mask, NMIMR); +} diff --git a/arch/sh/boards/mach-sdk7786/setup.c b/arch/sh/boards/mach-sdk7786/setup.c index 2ec1ea5..1521aa7 100644 --- a/arch/sh/boards/mach-sdk7786/setup.c +++ b/arch/sh/boards/mach-sdk7786/setup.c @@ -15,11 +15,13 @@ #include <linux/i2c.h> #include <linux/irq.h> #include <linux/clk.h> +#include <linux/clkdev.h> #include <mach/fpga.h> #include <mach/irq.h> #include <asm/machvec.h> #include <asm/heartbeat.h> #include <asm/sizes.h> +#include <asm/clock.h> #include <asm/reboot.h> #include <asm/smp-ops.h> @@ -133,13 +135,52 @@ static int __init sdk7786_devices_setup(void) return sdk7786_i2c_setup(); } -__initcall(sdk7786_devices_setup); +device_initcall(sdk7786_devices_setup); static int sdk7786_mode_pins(void) { return fpga_read_reg(MODSWR); } +/* + * FPGA-driven PCIe clocks + * + * Historically these include the oscillator, clock B (slots 2/3/4) and + * clock A (slot 1 and the CPU clock). Newer revs of the PCB shove + * everything under a single PCIe clocks enable bit that happens to map + * to the same bit position as the oscillator bit for earlier FPGA + * versions. + * + * Given that the legacy clocks have the side-effect of shutting the CPU + * off through the FPGA along with the PCI slots, we simply leave them in + * their initial state and don't bother registering them with the clock + * framework. + */ +static int sdk7786_pcie_clk_enable(struct clk *clk) +{ + fpga_write_reg(fpga_read_reg(PCIECR) | PCIECR_CLKEN, PCIECR); + return 0; +} + +static void sdk7786_pcie_clk_disable(struct clk *clk) +{ + fpga_write_reg(fpga_read_reg(PCIECR) & ~PCIECR_CLKEN, PCIECR); +} + +static struct clk_ops sdk7786_pcie_clk_ops = { + .enable = sdk7786_pcie_clk_enable, + .disable = sdk7786_pcie_clk_disable, +}; + +static struct clk sdk7786_pcie_clk = { + .ops = &sdk7786_pcie_clk_ops, +}; + +static struct clk_lookup sdk7786_pcie_cl = { + .con_id = "pcie_plat_clk", + .clk = &sdk7786_pcie_clk, +}; + static int sdk7786_clk_init(void) { struct clk *clk; @@ -158,7 +199,18 @@ static int sdk7786_clk_init(void) ret = clk_set_rate(clk, 33333333); clk_put(clk); - return ret; + /* + * Setup the FPGA clocks. + */ + ret = clk_register(&sdk7786_pcie_clk); + if (unlikely(ret)) { + pr_err("FPGA clock registration failed\n"); + return ret; + } + + clkdev_add(&sdk7786_pcie_cl); + + return 0; } static void sdk7786_restart(char *cmd) @@ -185,6 +237,7 @@ static void __init sdk7786_setup(char **cmdline_p) pr_info("Renesas Technology Europe SDK7786 support:\n"); sdk7786_fpga_init(); + sdk7786_nmi_init(); pr_info("\tPCB revision:\t%d\n", fpga_read_reg(PCBRR) & 0xf); diff --git a/arch/sh/boards/mach-sdk7786/sram.c b/arch/sh/boards/mach-sdk7786/sram.c new file mode 100644 index 0000000..c81c3ab --- /dev/null +++ b/arch/sh/boards/mach-sdk7786/sram.c @@ -0,0 +1,72 @@ +/* + * SDK7786 FPGA SRAM 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. + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/io.h> +#include <linux/string.h> +#include <mach/fpga.h> +#include <asm/sram.h> +#include <asm/sizes.h> + +static int __init fpga_sram_init(void) +{ + unsigned long phys; + unsigned int area; + void __iomem *vaddr; + int ret; + u16 data; + + /* Enable FPGA SRAM */ + data = fpga_read_reg(LCLASR); + data |= LCLASR_FRAMEN; + fpga_write_reg(data, LCLASR); + + /* + * FPGA_SEL determines the area mapping + */ + area = (data & LCLASR_FPGA_SEL_MASK) >> LCLASR_FPGA_SEL_SHIFT; + if (unlikely(area == LCLASR_AREA_MASK)) { + pr_err("FPGA memory unmapped.\n"); + return -ENXIO; + } + + /* + * The memory itself occupies a 2KiB range at the top of the area + * immediately below the system registers. + */ + phys = (area << 26) + SZ_64M - SZ_4K; + + /* + * The FPGA SRAM resides in translatable physical space, so set + * up a mapping prior to inserting it in to the pool. + */ + vaddr = ioremap(phys, SZ_2K); + if (unlikely(!vaddr)) { + pr_err("Failed remapping FPGA memory.\n"); + return -ENXIO; + } + + pr_info("Adding %dKiB of FPGA memory at 0x%08lx-0x%08lx " + "(area %d) to pool.\n", + SZ_2K >> 10, phys, phys + SZ_2K - 1, area); + + ret = gen_pool_add(sram_pool, (unsigned long)vaddr, SZ_2K, -1); + if (unlikely(ret < 0)) { + pr_err("Failed adding memory\n"); + iounmap(vaddr); + return ret; + } + + return 0; +} +postcore_initcall(fpga_sram_init); |