Initial commit; kernel source import

This commit is contained in:
Nathan
2025-04-06 23:50:55 -05:00
commit 25c6d769f4
45093 changed files with 18199410 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
obj-y := fpga.o irq.o nmi.o setup.o
obj-$(CONFIG_GPIOLIB) += gpio.o
obj-$(CONFIG_HAVE_SRAM_POOL) += sram.o

View File

@@ -0,0 +1,72 @@
/*
* 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>
#include <asm/sizes.h>
#define FPGA_REGS_OFFSET 0x03fff800
#define FPGA_REGS_SIZE 0x490
/*
* The FPGA can be mapped in any of the generally available areas,
* so we attempt to scan for it using the fixed SRSTR read magic.
*
* Once the FPGA is located, the rest of the mapping data for the other
* components can be determined dynamically from its section mapping
* registers.
*/
static void __iomem *sdk7786_fpga_probe(void)
{
unsigned long area;
void __iomem *base;
/*
* Iterate over all of the areas where the FPGA could be mapped.
* The possible range is anywhere from area 0 through 6, area 7
* is reserved.
*/
for (area = PA_AREA0; area < PA_AREA7; area += SZ_64M) {
base = ioremap_nocache(area + FPGA_REGS_OFFSET, FPGA_REGS_SIZE);
if (!base) {
/* Failed to remap this area, move along. */
continue;
}
if (ioread16(base + SRSTR) == SRSTR_MAGIC)
return base; /* Found it! */
iounmap(base);
}
return NULL;
}
void __iomem *sdk7786_fpga_base;
void __init sdk7786_fpga_init(void)
{
u16 version, date;
sdk7786_fpga_base = sdk7786_fpga_probe();
if (unlikely(!sdk7786_fpga_base)) {
panic("FPGA detection 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));
}

View File

@@ -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);

View File

@@ -0,0 +1,48 @@
/*
* SDK7786 FPGA IRQ Controller Support.
*
* Copyright (C) 2010 Matt Fleming
* 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/irq.h>
#include <mach/fpga.h>
#include <mach/irq.h>
enum {
ATA_IRQ_BIT = 1,
SPI_BUSY_BIT = 2,
LIRQ5_BIT = 3,
LIRQ6_BIT = 4,
LIRQ7_BIT = 5,
LIRQ8_BIT = 6,
KEY_IRQ_BIT = 7,
PEN_IRQ_BIT = 8,
ETH_IRQ_BIT = 9,
RTC_ALARM_BIT = 10,
CRYSTAL_FAIL_BIT = 12,
ETH_PME_BIT = 14,
};
void __init sdk7786_init_irq(void)
{
unsigned int tmp;
/* Enable priority encoding for all IRLs */
fpga_write_reg(fpga_read_reg(INTMSR) | 0x0303, INTMSR);
/* Clear FPGA interrupt status registers */
fpga_write_reg(0x0000, INTASR);
fpga_write_reg(0x0000, INTBSR);
/* Unmask FPGA interrupts */
tmp = fpga_read_reg(INTAMR);
tmp &= ~(1 << ETH_IRQ_BIT);
fpga_write_reg(tmp, INTAMR);
plat_irq_setup_pins(IRQ_MODE_IRL7654_MASK);
plat_irq_setup_pins(IRQ_MODE_IRL3210_MASK);
}

View File

@@ -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);
}

View File

@@ -0,0 +1,269 @@
/*
* Renesas Technology Europe SDK7786 Support.
*
* Copyright (C) 2010 Matt Fleming
* 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/platform_device.h>
#include <linux/io.h>
#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
#include <linux/smsc911x.h>
#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>
static struct resource heartbeat_resource = {
.start = 0x07fff8b0,
.end = 0x07fff8b0 + sizeof(u16) - 1,
.flags = IORESOURCE_MEM | IORESOURCE_MEM_16BIT,
};
static struct platform_device heartbeat_device = {
.name = "heartbeat",
.id = -1,
.num_resources = 1,
.resource = &heartbeat_resource,
};
/* Dummy supplies, where voltage doesn't matter */
static struct regulator_consumer_supply dummy_supplies[] = {
REGULATOR_SUPPLY("vddvario", "smsc911x"),
REGULATOR_SUPPLY("vdd33a", "smsc911x"),
};
static struct resource smsc911x_resources[] = {
[0] = {
.name = "smsc911x-memory",
.start = 0x07ffff00,
.end = 0x07ffff00 + SZ_256 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.name = "smsc911x-irq",
.start = evt2irq(0x2c0),
.end = evt2irq(0x2c0),
.flags = IORESOURCE_IRQ,
},
};
static struct smsc911x_platform_config smsc911x_config = {
.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
.irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
.flags = SMSC911X_USE_32BIT,
.phy_interface = PHY_INTERFACE_MODE_MII,
};
static struct platform_device smsc911x_device = {
.name = "smsc911x",
.id = -1,
.num_resources = ARRAY_SIZE(smsc911x_resources),
.resource = smsc911x_resources,
.dev = {
.platform_data = &smsc911x_config,
},
};
static struct resource smbus_fpga_resource = {
.start = 0x07fff9e0,
.end = 0x07fff9e0 + SZ_32 - 1,
.flags = IORESOURCE_MEM,
};
static struct platform_device smbus_fpga_device = {
.name = "i2c-sdk7786",
.id = 0,
.num_resources = 1,
.resource = &smbus_fpga_resource,
};
static struct resource smbus_pcie_resource = {
.start = 0x07fffc30,
.end = 0x07fffc30 + SZ_32 - 1,
.flags = IORESOURCE_MEM,
};
static struct platform_device smbus_pcie_device = {
.name = "i2c-sdk7786",
.id = 1,
.num_resources = 1,
.resource = &smbus_pcie_resource,
};
static struct i2c_board_info __initdata sdk7786_i2c_devices[] = {
{
I2C_BOARD_INFO("max6900", 0x68),
},
};
static struct platform_device *sh7786_devices[] __initdata = {
&heartbeat_device,
&smsc911x_device,
&smbus_fpga_device,
&smbus_pcie_device,
};
static int sdk7786_i2c_setup(void)
{
unsigned int tmp;
/*
* Hand over I2C control to the FPGA.
*/
tmp = fpga_read_reg(SBCR);
tmp &= ~SCBR_I2CCEN;
tmp |= SCBR_I2CMEN;
fpga_write_reg(tmp, SBCR);
return i2c_register_board_info(0, sdk7786_i2c_devices,
ARRAY_SIZE(sdk7786_i2c_devices));
}
static int __init sdk7786_devices_setup(void)
{
int ret;
ret = platform_add_devices(sh7786_devices, ARRAY_SIZE(sh7786_devices));
if (unlikely(ret != 0))
return ret;
return sdk7786_i2c_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 sh_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;
int ret;
/*
* Only handle the EXTAL case, anyone interfacing a crystal
* resonator will need to provide their own input clock.
*/
if (test_mode_pin(MODE_PIN9))
return -EINVAL;
clk = clk_get(NULL, "extal");
if (IS_ERR(clk))
return PTR_ERR(clk);
ret = clk_set_rate(clk, 33333333);
clk_put(clk);
/*
* 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)
{
fpga_write_reg(0xa5a5, SRSTR);
}
static void sdk7786_power_off(void)
{
fpga_write_reg(fpga_read_reg(PWRCR) | PWRCR_PDWNREQ, PWRCR);
/*
* It can take up to 20us for the R8C to do its job, back off and
* wait a bit until we've been shut off. Even though newer FPGA
* versions don't set the ACK bit, the latency issue remains.
*/
while ((fpga_read_reg(PWRCR) & PWRCR_PDWNACK) == 0)
cpu_sleep();
}
/* Initialize the board */
static void __init sdk7786_setup(char **cmdline_p)
{
pr_info("Renesas Technology Europe SDK7786 support:\n");
regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
sdk7786_fpga_init();
sdk7786_nmi_init();
pr_info("\tPCB revision:\t%d\n", fpga_read_reg(PCBRR) & 0xf);
machine_ops.restart = sdk7786_restart;
pm_power_off = sdk7786_power_off;
register_smp_ops(&shx3_smp_ops);
}
/*
* The Machine Vector
*/
static struct sh_machine_vector mv_sdk7786 __initmv = {
.mv_name = "SDK7786",
.mv_setup = sdk7786_setup,
.mv_mode_pins = sdk7786_mode_pins,
.mv_clk_init = sdk7786_clk_init,
.mv_init_irq = sdk7786_init_irq,
};

View File

@@ -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);