aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/board
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/board')
-rw-r--r--drivers/staging/board/Kconfig1
-rw-r--r--drivers/staging/board/Makefile3
-rw-r--r--drivers/staging/board/armadillo800eva.c105
-rw-r--r--drivers/staging/board/board.c136
-rw-r--r--drivers/staging/board/board.h27
-rw-r--r--drivers/staging/board/kzm9d.c10
6 files changed, 277 insertions, 5 deletions
diff --git a/drivers/staging/board/Kconfig b/drivers/staging/board/Kconfig
index 0a89ad16371f..b8ee81840666 100644
--- a/drivers/staging/board/Kconfig
+++ b/drivers/staging/board/Kconfig
@@ -1,7 +1,6 @@
config STAGING_BOARD
bool "Staging Board Support"
depends on OF_ADDRESS
- depends on BROKEN
help
Select to enable per-board staging support code.
diff --git a/drivers/staging/board/Makefile b/drivers/staging/board/Makefile
index 65d39ecfad63..6842745feb94 100644
--- a/drivers/staging/board/Makefile
+++ b/drivers/staging/board/Makefile
@@ -1,2 +1,3 @@
obj-y := board.o
-obj-$(CONFIG_ARCH_EMEV2) += kzm9d.o
+obj-$(CONFIG_ARCH_EMEV2) += kzm9d.o
+obj-$(CONFIG_ARCH_R8A7740) += armadillo800eva.o
diff --git a/drivers/staging/board/armadillo800eva.c b/drivers/staging/board/armadillo800eva.c
new file mode 100644
index 000000000000..81df77bd55cc
--- /dev/null
+++ b/drivers/staging/board/armadillo800eva.c
@@ -0,0 +1,105 @@
+/*
+ * Staging board support for Armadillo 800 eva.
+ * Enable not-yet-DT-capable devices here.
+ *
+ * Based on board-armadillo800eva.c
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/videodev2.h>
+
+#include <video/sh_mobile_lcdc.h>
+
+#include "board.h"
+
+
+static struct fb_videomode lcdc0_mode = {
+ .name = "AMPIER/AM-800480",
+ .xres = 800,
+ .yres = 480,
+ .left_margin = 88,
+ .right_margin = 40,
+ .hsync_len = 128,
+ .upper_margin = 20,
+ .lower_margin = 5,
+ .vsync_len = 5,
+ .sync = 0,
+};
+
+static struct sh_mobile_lcdc_info lcdc0_info = {
+ .clock_source = LCDC_CLK_BUS,
+ .ch[0] = {
+ .chan = LCDC_CHAN_MAINLCD,
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .interface_type = RGB24,
+ .clock_divider = 5,
+ .flags = 0,
+ .lcd_modes = &lcdc0_mode,
+ .num_modes = 1,
+ .panel_cfg = {
+ .width = 111,
+ .height = 68,
+ },
+ },
+};
+
+static struct resource lcdc0_resources[] = {
+ [0] = {
+ .name = "LCD0",
+ .start = 0xfe940000,
+ .end = 0xfe943fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 177 + 32,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device lcdc0_device = {
+ .name = "sh_mobile_lcdc_fb",
+ .num_resources = ARRAY_SIZE(lcdc0_resources),
+ .resource = lcdc0_resources,
+ .id = 0,
+ .dev = {
+ .platform_data = &lcdc0_info,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+static const struct board_staging_clk lcdc0_clocks[] __initconst = {
+ { "lcdc0", NULL, "sh_mobile_lcdc_fb.0" },
+};
+
+static const struct board_staging_dev armadillo800eva_devices[] __initconst = {
+ {
+ .pdev = &lcdc0_device,
+ .clocks = lcdc0_clocks,
+ .nclocks = ARRAY_SIZE(lcdc0_clocks),
+ .domain = "a4lc",
+ },
+};
+
+static void __init armadillo800eva_init(void)
+{
+ board_staging_gic_setup_xlate("arm,cortex-a9-gic", 32);
+ board_staging_register_devices(armadillo800eva_devices,
+ ARRAY_SIZE(armadillo800eva_devices));
+}
+
+board_staging("renesas,armadillo800eva", armadillo800eva_init);
diff --git a/drivers/staging/board/board.c b/drivers/staging/board/board.c
index d5a6abc84519..29d456e29f38 100644
--- a/drivers/staging/board/board.c
+++ b/drivers/staging/board/board.c
@@ -1,10 +1,30 @@
+/*
+ * Copyright (C) 2014 Magnus Damm
+ * Copyright (C) 2015 Glider bvba
+ *
+ * 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) "board_staging: " fmt
+
+#include <linux/clkdev.h>
#include <linux/init.h>
+#include <linux/irq.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+
#include "board.h"
+static struct device_node *irqc_node __initdata;
+static unsigned int irqc_base __initdata;
+
static bool find_by_address(u64 base_address)
{
struct device_node *dn = of_find_all_nodes(NULL);
@@ -38,3 +58,119 @@ bool __init board_staging_dt_node_available(const struct resource *resource,
return false; /* Nothing found */
}
+
+int __init board_staging_gic_setup_xlate(const char *gic_match,
+ unsigned int base)
+{
+ WARN_ON(irqc_node);
+
+ irqc_node = of_find_compatible_node(NULL, NULL, gic_match);
+
+ WARN_ON(!irqc_node);
+ if (!irqc_node)
+ return -ENOENT;
+
+ irqc_base = base;
+ return 0;
+}
+
+static void __init gic_fixup_resource(struct resource *res)
+{
+ struct of_phandle_args irq_data;
+ unsigned int hwirq = res->start;
+ unsigned int virq;
+
+ if (resource_type(res) != IORESOURCE_IRQ || !irqc_node)
+ return;
+
+ irq_data.np = irqc_node;
+ irq_data.args_count = 3;
+ irq_data.args[0] = 0;
+ irq_data.args[1] = hwirq - irqc_base;
+ switch (res->flags &
+ (IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE |
+ IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_HIGHLEVEL)) {
+ case IORESOURCE_IRQ_LOWEDGE:
+ irq_data.args[2] = IRQ_TYPE_EDGE_FALLING;
+ break;
+ case IORESOURCE_IRQ_HIGHEDGE:
+ irq_data.args[2] = IRQ_TYPE_EDGE_RISING;
+ break;
+ case IORESOURCE_IRQ_LOWLEVEL:
+ irq_data.args[2] = IRQ_TYPE_LEVEL_LOW;
+ break;
+ case IORESOURCE_IRQ_HIGHLEVEL:
+ default:
+ irq_data.args[2] = IRQ_TYPE_LEVEL_HIGH;
+ break;
+ }
+
+ virq = irq_create_of_mapping(&irq_data);
+ if (WARN_ON(!virq))
+ return;
+
+ pr_debug("hwirq %u -> virq %u\n", hwirq, virq);
+ res->start = virq;
+}
+
+void __init board_staging_gic_fixup_resources(struct resource *res,
+ unsigned int nres)
+{
+ unsigned int i;
+
+ for (i = 0; i < nres; i++)
+ gic_fixup_resource(&res[i]);
+}
+
+int __init board_staging_register_clock(const struct board_staging_clk *bsc)
+{
+ int error;
+
+ pr_debug("Aliasing clock %s for con_id %s dev_id %s\n", bsc->clk,
+ bsc->con_id, bsc->dev_id);
+ error = clk_add_alias(bsc->con_id, bsc->dev_id, bsc->clk, NULL);
+ if (error)
+ pr_err("Failed to alias clock %s (%d)\n", bsc->clk, error);
+
+ return error;
+}
+
+int __init board_staging_register_device(const struct board_staging_dev *dev)
+{
+ struct platform_device *pdev = dev->pdev;
+ unsigned int i;
+ int error;
+
+ pr_debug("Trying to register device %s\n", pdev->name);
+ if (board_staging_dt_node_available(pdev->resource,
+ pdev->num_resources)) {
+ pr_warn("Skipping %s, already in DT\n", pdev->name);
+ return -EEXIST;
+ }
+
+ board_staging_gic_fixup_resources(pdev->resource, pdev->num_resources);
+
+ for (i = 0; i < dev->nclocks; i++)
+ board_staging_register_clock(&dev->clocks[i]);
+
+ error = platform_device_register(pdev);
+ if (error) {
+ pr_err("Failed to register device %s (%d)\n", pdev->name,
+ error);
+ return error;
+ }
+
+ if (dev->domain)
+ __pm_genpd_name_add_device(dev->domain, &pdev->dev, NULL);
+
+ return error;
+}
+
+void __init board_staging_register_devices(const struct board_staging_dev *devs,
+ unsigned int ndevs)
+{
+ unsigned int i;
+
+ for (i = 0; i < ndevs; i++)
+ board_staging_register_device(&devs[i]);
+}
diff --git a/drivers/staging/board/board.h b/drivers/staging/board/board.h
index 2390ed6c31a4..42ed12513220 100644
--- a/drivers/staging/board/board.h
+++ b/drivers/staging/board/board.h
@@ -1,10 +1,35 @@
#ifndef __BOARD_H__
#define __BOARD_H__
+
#include <linux/init.h>
#include <linux/of.h>
+struct board_staging_clk {
+ const char *clk;
+ const char *con_id;
+ const char *dev_id;
+};
+
+struct board_staging_dev {
+ /* Platform Device */
+ struct platform_device *pdev;
+ /* Clocks (optional) */
+ const struct board_staging_clk *clocks;
+ unsigned int nclocks;
+ /* Generic PM Domain (optional) */
+ const char *domain;
+};
+
+struct resource;
+
bool board_staging_dt_node_available(const struct resource *resource,
unsigned int num_resources);
+int board_staging_gic_setup_xlate(const char *gic_match, unsigned int base);
+void board_staging_gic_fixup_resources(struct resource *res, unsigned int nres);
+int board_staging_register_clock(const struct board_staging_clk *bsc);
+int board_staging_register_device(const struct board_staging_dev *dev);
+void board_staging_register_devices(const struct board_staging_dev *devs,
+ unsigned int ndevs);
#define board_staging(str, fn) \
static int __init runtime_board_check(void) \
@@ -15,6 +40,6 @@ static int __init runtime_board_check(void) \
return 0; \
} \
\
-late_initcall(runtime_board_check)
+device_initcall(runtime_board_check)
#endif /* __BOARD_H__ */
diff --git a/drivers/staging/board/kzm9d.c b/drivers/staging/board/kzm9d.c
index 533f3026e17a..8d1eb09bc66e 100644
--- a/drivers/staging/board/kzm9d.c
+++ b/drivers/staging/board/kzm9d.c
@@ -4,16 +4,22 @@
#include <linux/platform_device.h>
#include "board.h"
-static const struct resource usbs1_res[] __initconst = {
+static struct resource usbs1_res[] __initdata = {
DEFINE_RES_MEM(0xe2800000, 0x2000),
DEFINE_RES_IRQ(159),
};
static void __init kzm9d_init(void)
{
- if (!board_staging_dt_node_available(usbs1_res, ARRAY_SIZE(usbs1_res)))
+ board_staging_gic_setup_xlate("arm,cortex-a9-gic", 32);
+
+ if (!board_staging_dt_node_available(usbs1_res,
+ ARRAY_SIZE(usbs1_res))) {
+ board_staging_gic_fixup_resources(usbs1_res,
+ ARRAY_SIZE(usbs1_res));
platform_device_register_simple("emxx_udc", -1, usbs1_res,
ARRAY_SIZE(usbs1_res));
+ }
}
board_staging("renesas,kzm9d", kzm9d_init);