diff options
author | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-11 10:41:07 +0300 |
---|---|---|
committer | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-13 08:17:18 +0300 |
commit | e09b41010ba33a20a87472ee821fa407a5b8da36 (patch) | |
tree | d10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/drivers/staging/board | |
parent | f93b97fd65072de626c074dbe099a1fff05ce060 (diff) |
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page.
During the rebasing, the following patch collided:
Force tick interrupt and get rid of softirq magic(I70131fb85).
Collisions have been removed because its logic was found on the
source already.
Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769
Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/drivers/staging/board')
-rw-r--r-- | kernel/drivers/staging/board/Kconfig | 3 | ||||
-rw-r--r-- | kernel/drivers/staging/board/Makefile | 3 | ||||
-rw-r--r-- | kernel/drivers/staging/board/armadillo800eva.c | 105 | ||||
-rw-r--r-- | kernel/drivers/staging/board/board.c | 170 | ||||
-rw-r--r-- | kernel/drivers/staging/board/board.h | 27 | ||||
-rw-r--r-- | kernel/drivers/staging/board/kzm9d.c | 10 |
6 files changed, 312 insertions, 6 deletions
diff --git a/kernel/drivers/staging/board/Kconfig b/kernel/drivers/staging/board/Kconfig index 0a89ad163..3f287c48e 100644 --- a/kernel/drivers/staging/board/Kconfig +++ b/kernel/drivers/staging/board/Kconfig @@ -1,7 +1,6 @@ config STAGING_BOARD bool "Staging Board Support" - depends on OF_ADDRESS - depends on BROKEN + depends on OF_ADDRESS && OF_IRQ && CLKDEV_LOOKUP help Select to enable per-board staging support code. diff --git a/kernel/drivers/staging/board/Makefile b/kernel/drivers/staging/board/Makefile index 65d39ecfa..6842745fe 100644 --- a/kernel/drivers/staging/board/Makefile +++ b/kernel/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/kernel/drivers/staging/board/armadillo800eva.c b/kernel/drivers/staging/board/armadillo800eva.c new file mode 100644 index 000000000..9c41652ee --- /dev/null +++ b/kernel/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 = "/system-controller@e6180000/pm-domains/c5/a4lc@1" + }, +}; + +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/kernel/drivers/staging/board/board.c b/kernel/drivers/staging/board/board.c index d5a6abc84..965afc79a 100644 --- a/kernel/drivers/staging/board/board.c +++ b/kernel/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,153 @@ 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; +} + +#ifdef CONFIG_PM_GENERIC_DOMAINS_OF +static int board_staging_add_dev_domain(struct platform_device *pdev, + const char *domain) +{ + struct of_phandle_args pd_args; + struct generic_pm_domain *pd; + struct device_node *np; + + np = of_find_node_by_path(domain); + if (!np) { + pr_err("Cannot find domain node %s\n", domain); + return -ENOENT; + } + + pd_args.np = np; + pd_args.args_count = 0; + pd = of_genpd_get_from_provider(&pd_args); + if (IS_ERR(pd)) { + pr_err("Cannot find genpd %s (%ld)\n", domain, PTR_ERR(pd)); + return PTR_ERR(pd); + + } + pr_debug("Found genpd %s for device %s\n", pd->name, pdev->name); + + return pm_genpd_add_device(pd, &pdev->dev); +} +#else +static inline int board_staging_add_dev_domain(struct platform_device *pdev, + const char *domain) +{ + return 0; +} +#endif + +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]); + + if (dev->domain) + board_staging_add_dev_domain(pdev, dev->domain); + + error = platform_device_register(pdev); + if (error) { + pr_err("Failed to register device %s (%d)\n", pdev->name, + error); + return error; + } + + 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/kernel/drivers/staging/board/board.h b/kernel/drivers/staging/board/board.h index 2390ed6c3..42ed12513 100644 --- a/kernel/drivers/staging/board/board.h +++ b/kernel/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/kernel/drivers/staging/board/kzm9d.c b/kernel/drivers/staging/board/kzm9d.c index 533f3026e..8d1eb09bc 100644 --- a/kernel/drivers/staging/board/kzm9d.c +++ b/kernel/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); |