diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-12-03 15:02:06 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-12-03 15:02:06 -0800 |
commit | 12e057530821c9839d0d0272cdda555fb36869d1 (patch) | |
tree | 77409404febc6c3fd10027cd34d4ff869853b54f | |
parent | 4b1f40738f349875cd568ca6aa9a099659d8b718 (diff) | |
download | ltsi-kernel-12e057530821c9839d0d0272cdda555fb36869d1.tar.gz |
3.4: Armadillo 800 and Marzen patches added
207 files changed, 25190 insertions, 0 deletions
diff --git a/patches.armadillo800/0001-ARM-shmobile-add-common-DMAEngine-definitions.patch b/patches.armadillo800/0001-ARM-shmobile-add-common-DMAEngine-definitions.patch new file mode 100644 index 0000000000000..5316285a382f3 --- /dev/null +++ b/patches.armadillo800/0001-ARM-shmobile-add-common-DMAEngine-definitions.patch @@ -0,0 +1,115 @@ +From 4d3626f914a2b4023a3edf428640e578527ac0c8 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 25 Jun 2012 03:43:00 -0700 +Subject: ARM: shmobile: add common DMAEngine definitions + +Current shmobile have DMAEngine specific settings on each CPU code, +but SH-ARM DMAC use same value. + +This patch adds new dma-register.h header to share definitions +and reduce a waste of code on SH-ARM architecture. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 5ca1d44f6a99b29ab164a06f4ec71950d6939fb5) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/include/mach/dma-register.h | 84 ++++++++++++++++++++++ + 1 file changed, 84 insertions(+) + create mode 100644 arch/arm/mach-shmobile/include/mach/dma-register.h + +diff --git a/arch/arm/mach-shmobile/include/mach/dma-register.h b/arch/arm/mach-shmobile/include/mach/dma-register.h +new file mode 100644 +index 0000000..97c40bd +--- /dev/null ++++ b/arch/arm/mach-shmobile/include/mach/dma-register.h +@@ -0,0 +1,84 @@ ++/* ++ * SH-ARM CPU-specific DMA definitions, used by both DMA drivers ++ * ++ * Copyright (C) 2012 Renesas Solutions Corp ++ * ++ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> ++ * ++ * Based on arch/sh/include/cpu-sh4/cpu/dma-register.h ++ * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef DMA_REGISTER_H ++#define DMA_REGISTER_H ++ ++/* ++ * Direct Memory Access Controller ++ */ ++ ++/* Transmit sizes and respective CHCR register values */ ++enum { ++ XMIT_SZ_8BIT = 0, ++ XMIT_SZ_16BIT = 1, ++ XMIT_SZ_32BIT = 2, ++ XMIT_SZ_64BIT = 7, ++ XMIT_SZ_128BIT = 3, ++ XMIT_SZ_256BIT = 4, ++ XMIT_SZ_512BIT = 5, ++}; ++ ++/* log2(size / 8) - used to calculate number of transfers */ ++static const unsigned int dma_ts_shift[] = { ++ [XMIT_SZ_8BIT] = 0, ++ [XMIT_SZ_16BIT] = 1, ++ [XMIT_SZ_32BIT] = 2, ++ [XMIT_SZ_64BIT] = 3, ++ [XMIT_SZ_128BIT] = 4, ++ [XMIT_SZ_256BIT] = 5, ++ [XMIT_SZ_512BIT] = 6, ++}; ++ ++#define TS_LOW_BIT 0x3 /* --xx */ ++#define TS_HI_BIT 0xc /* xx-- */ ++ ++#define TS_LOW_SHIFT (3) ++#define TS_HI_SHIFT (20 - 2) /* 2 bits for shifted low TS */ ++ ++#define TS_INDEX2VAL(i) \ ++ ((((i) & TS_LOW_BIT) << TS_LOW_SHIFT) |\ ++ (((i) & TS_HI_BIT) << TS_HI_SHIFT)) ++ ++#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz))) ++#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz))) ++ ++ ++/* ++ * USB High-Speed DMAC ++ */ ++/* Transmit sizes and respective CHCR register values */ ++enum { ++ USBTS_XMIT_SZ_8BYTE = 0, ++ USBTS_XMIT_SZ_16BYTE = 1, ++ USBTS_XMIT_SZ_32BYTE = 2, ++}; ++ ++/* log2(size / 8) - used to calculate number of transfers */ ++static const unsigned int dma_usbts_shift[] = { ++ [USBTS_XMIT_SZ_8BYTE] = 3, ++ [USBTS_XMIT_SZ_16BYTE] = 4, ++ [USBTS_XMIT_SZ_32BYTE] = 5, ++}; ++ ++#define USBTS_LOW_BIT 0x3 /* --xx */ ++#define USBTS_HI_BIT 0x0 /* ---- */ ++ ++#define USBTS_LOW_SHIFT 6 ++#define USBTS_HI_SHIFT 0 ++ ++#define USBTS_INDEX2VAL(i) (((i) & 3) << 6) ++ ++#endif /* DMA_REGISTER_H */ +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0002-ARM-shmobile-soc-core-add-R-mobile-PM-domain-common-.patch b/patches.armadillo800/0002-ARM-shmobile-soc-core-add-R-mobile-PM-domain-common-.patch new file mode 100644 index 0000000000000..2acaf3de704cf --- /dev/null +++ b/patches.armadillo800/0002-ARM-shmobile-soc-core-add-R-mobile-PM-domain-common-.patch @@ -0,0 +1,260 @@ +From c13b4e8e39cad46f37b794ba12b8a97569767e25 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 5 Jul 2012 01:24:46 -0700 +Subject: ARM: shmobile: soc-core: add R-mobile PM domain common APIs + +This patch adds Renesas R-mobile series common PM domain APIs. +R-mobile CPU can use/switch this API + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 8f45b112fc66ef6869ccca4c3966976982f496a9) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/Makefile | 1 + + arch/arm/mach-shmobile/include/mach/pm-rmobile.h | 44 ++++++ + arch/arm/mach-shmobile/pm-rmobile.c | 167 +++++++++++++++++++++++ + 3 files changed, 212 insertions(+) + create mode 100644 arch/arm/mach-shmobile/include/mach/pm-rmobile.h + create mode 100644 arch/arm/mach-shmobile/pm-rmobile.c + +diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile +index e7c2590..53846a1e 100644 +--- a/arch/arm/mach-shmobile/Makefile ++++ b/arch/arm/mach-shmobile/Makefile +@@ -37,6 +37,7 @@ obj-$(CONFIG_ARCH_R8A7740) += entry-intc.o + # PM objects + obj-$(CONFIG_SUSPEND) += suspend.o + obj-$(CONFIG_CPU_IDLE) += cpuidle.o ++obj-$(CONFIG_ARCH_SHMOBILE) += pm-rmobile.o + obj-$(CONFIG_ARCH_SH7372) += pm-sh7372.o sleep-sh7372.o + obj-$(CONFIG_ARCH_R8A7779) += pm-r8a7779.o + +diff --git a/arch/arm/mach-shmobile/include/mach/pm-rmobile.h b/arch/arm/mach-shmobile/include/mach/pm-rmobile.h +new file mode 100644 +index 0000000..5a40284 +--- /dev/null ++++ b/arch/arm/mach-shmobile/include/mach/pm-rmobile.h +@@ -0,0 +1,44 @@ ++/* ++ * Copyright (C) 2012 Renesas Solutions Corp. ++ * ++ * Kuninori Morimoto <morimoto.kuninori@renesas.com> ++ * ++ * 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. ++ */ ++#ifndef PM_RMOBILE_H ++#define PM_RMOBILE_H ++ ++#include <linux/pm_domain.h> ++ ++struct platform_device; ++ ++struct rmobile_pm_domain { ++ struct generic_pm_domain genpd; ++ struct dev_power_governor *gov; ++ int (*suspend)(void); ++ void (*resume)(void); ++ unsigned int bit_shift; ++ bool no_debug; ++}; ++ ++static inline ++struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d) ++{ ++ return container_of(d, struct rmobile_pm_domain, genpd); ++} ++ ++#ifdef CONFIG_PM ++extern void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd); ++extern void rmobile_add_device_to_domain(struct rmobile_pm_domain *rmobile_pd, ++ struct platform_device *pdev); ++extern void rmobile_pm_add_subdomain(struct rmobile_pm_domain *rmobile_pd, ++ struct rmobile_pm_domain *rmobile_sd); ++#else ++#define rmobile_init_pm_domain(pd) do { } while (0) ++#define rmobile_add_device_to_domain(pd, pdev) do { } while (0) ++#define rmobile_pm_add_subdomain(pd, sd) do { } while (0) ++#endif /* CONFIG_PM */ ++ ++#endif /* PM_RMOBILE_H */ +diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c +new file mode 100644 +index 0000000..a856254 +--- /dev/null ++++ b/arch/arm/mach-shmobile/pm-rmobile.c +@@ -0,0 +1,167 @@ ++/* ++ * rmobile power management support ++ * ++ * Copyright (C) 2012 Renesas Solutions Corp. ++ * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> ++ * ++ * based on pm-sh7372.c ++ * Copyright (C) 2011 Magnus Damm ++ * ++ * 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/console.h> ++#include <linux/delay.h> ++#include <linux/platform_device.h> ++#include <linux/pm.h> ++#include <linux/pm_clock.h> ++#include <asm/io.h> ++#include <mach/pm-rmobile.h> ++ ++/* SYSC */ ++#define SPDCR 0xe6180008 ++#define SWUCR 0xe6180014 ++#define PSTR 0xe6180080 ++ ++#define PSTR_RETRIES 100 ++#define PSTR_DELAY_US 10 ++ ++#ifdef CONFIG_PM ++static int rmobile_pd_power_down(struct generic_pm_domain *genpd) ++{ ++ struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd); ++ unsigned int mask = 1 << rmobile_pd->bit_shift; ++ ++ if (rmobile_pd->suspend) { ++ int ret = rmobile_pd->suspend(); ++ ++ if (ret) ++ return ret; ++ } ++ ++ if (__raw_readl(PSTR) & mask) { ++ unsigned int retry_count; ++ __raw_writel(mask, SPDCR); ++ ++ for (retry_count = PSTR_RETRIES; retry_count; retry_count--) { ++ if (!(__raw_readl(SPDCR) & mask)) ++ break; ++ cpu_relax(); ++ } ++ } ++ ++ if (!rmobile_pd->no_debug) ++ pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", ++ genpd->name, mask, __raw_readl(PSTR)); ++ ++ return 0; ++} ++ ++static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd, ++ bool do_resume) ++{ ++ unsigned int mask = 1 << rmobile_pd->bit_shift; ++ unsigned int retry_count; ++ int ret = 0; ++ ++ if (__raw_readl(PSTR) & mask) ++ goto out; ++ ++ __raw_writel(mask, SWUCR); ++ ++ for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) { ++ if (!(__raw_readl(SWUCR) & mask)) ++ break; ++ if (retry_count > PSTR_RETRIES) ++ udelay(PSTR_DELAY_US); ++ else ++ cpu_relax(); ++ } ++ if (!retry_count) ++ ret = -EIO; ++ ++ if (!rmobile_pd->no_debug) ++ pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n", ++ rmobile_pd->genpd.name, mask, __raw_readl(PSTR)); ++ ++out: ++ if (ret == 0 && rmobile_pd->resume && do_resume) ++ rmobile_pd->resume(); ++ ++ return ret; ++} ++ ++static int rmobile_pd_power_up(struct generic_pm_domain *genpd) ++{ ++ return __rmobile_pd_power_up(to_rmobile_pd(genpd), true); ++} ++ ++static bool rmobile_pd_active_wakeup(struct device *dev) ++{ ++ bool (*active_wakeup)(struct device *dev); ++ ++ active_wakeup = dev_gpd_data(dev)->ops.active_wakeup; ++ return active_wakeup ? active_wakeup(dev) : true; ++} ++ ++static int rmobile_pd_stop_dev(struct device *dev) ++{ ++ int (*stop)(struct device *dev); ++ ++ stop = dev_gpd_data(dev)->ops.stop; ++ if (stop) { ++ int ret = stop(dev); ++ if (ret) ++ return ret; ++ } ++ return pm_clk_suspend(dev); ++} ++ ++static int rmobile_pd_start_dev(struct device *dev) ++{ ++ int (*start)(struct device *dev); ++ int ret; ++ ++ ret = pm_clk_resume(dev); ++ if (ret) ++ return ret; ++ ++ start = dev_gpd_data(dev)->ops.start; ++ if (start) ++ ret = start(dev); ++ ++ return ret; ++} ++ ++void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) ++{ ++ struct generic_pm_domain *genpd = &rmobile_pd->genpd; ++ struct dev_power_governor *gov = rmobile_pd->gov; ++ ++ pm_genpd_init(genpd, gov ? : &simple_qos_governor, false); ++ genpd->dev_ops.stop = rmobile_pd_stop_dev; ++ genpd->dev_ops.start = rmobile_pd_start_dev; ++ genpd->dev_ops.active_wakeup = rmobile_pd_active_wakeup; ++ genpd->dev_irq_safe = true; ++ genpd->power_off = rmobile_pd_power_down; ++ genpd->power_on = rmobile_pd_power_up; ++ __rmobile_pd_power_up(rmobile_pd, false); ++} ++ ++void rmobile_add_device_to_domain(struct rmobile_pm_domain *rmobile_pd, ++ struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ ++ pm_genpd_add_device(&rmobile_pd->genpd, dev); ++ if (pm_clk_no_clocks(dev)) ++ pm_clk_add(dev, NULL); ++} ++ ++void rmobile_pm_add_subdomain(struct rmobile_pm_domain *rmobile_pd, ++ struct rmobile_pm_domain *rmobile_sd) ++{ ++ pm_genpd_add_subdomain(&rmobile_pd->genpd, &rmobile_sd->genpd); ++} ++#endif /* CONFIG_PM */ +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0003-media-V4L2-sh_mobile_ceu-manage-lower-8bit-bus.patch b/patches.armadillo800/0003-media-V4L2-sh_mobile_ceu-manage-lower-8bit-bus.patch new file mode 100644 index 0000000000000..e133ecf33aa80 --- /dev/null +++ b/patches.armadillo800/0003-media-V4L2-sh_mobile_ceu-manage-lower-8bit-bus.patch @@ -0,0 +1,55 @@ +From 657ed37c21c4b58b2ce736343d1c653a842f7299 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 8 May 2012 00:00:07 -0300 +Subject: [media] V4L2: sh_mobile_ceu: manage lower 8bit bus + +CAMCR::DTIF feild controls camera bus as upper8bit/16bit/lower8bit. +This patch manages unmanaged lower 8bit bus + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> +(cherry picked from commit 2564f67bc8d56e5c7fc2970f80f41f2d38db3e21) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/media/video/sh_mobile_ceu_camera.c | 8 +++++--- + include/media/sh_mobile_ceu.h | 1 + + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c +index 424dfac..4e0b654 100644 +--- a/drivers/media/video/sh_mobile_ceu_camera.c ++++ b/drivers/media/video/sh_mobile_ceu_camera.c +@@ -881,11 +881,13 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd) + + value |= common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW ? 1 << 1 : 0; + value |= common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW ? 1 << 0 : 0; +- value |= pcdev->is_16bit ? 1 << 12 : 0; + +- /* CSI2 mode */ +- if (pcdev->pdata->csi2) ++ if (pcdev->pdata->csi2) /* CSI2 mode */ + value |= 3 << 12; ++ else if (pcdev->is_16bit) ++ value |= 1 << 12; ++ else if (pcdev->pdata->flags & SH_CEU_FLAG_LOWER_8BIT) ++ value |= 2 << 12; + + ceu_write(pcdev, CAMCR, value); + +diff --git a/include/media/sh_mobile_ceu.h b/include/media/sh_mobile_ceu.h +index a90a765..6fdb6ad 100644 +--- a/include/media/sh_mobile_ceu.h ++++ b/include/media/sh_mobile_ceu.h +@@ -5,6 +5,7 @@ + #define SH_CEU_FLAG_USE_16BIT_BUS (1 << 1) /* use 16bit bus width */ + #define SH_CEU_FLAG_HSYNC_LOW (1 << 2) /* default High if possible */ + #define SH_CEU_FLAG_VSYNC_LOW (1 << 3) /* default High if possible */ ++#define SH_CEU_FLAG_LOWER_8BIT (1 << 4) /* default upper 8bit */ + + struct device; + struct resource; +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0004-regulator-support-multiple-dummy-fixed-regulators.patch b/patches.armadillo800/0004-regulator-support-multiple-dummy-fixed-regulators.patch new file mode 100644 index 0000000000000..fb5e5111c4832 --- /dev/null +++ b/patches.armadillo800/0004-regulator-support-multiple-dummy-fixed-regulators.patch @@ -0,0 +1,96 @@ +From 5d792a5a2daa8e2d397c0b5f45ac76c9e0d175ff Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Tue, 19 Jun 2012 17:43:56 +0200 +Subject: regulator: support multiple dummy fixed regulators + +Currently regulator_register_fixed() uses a constant name to register a +fixed dummy regulator. This is sufficient in principle, since there is no +reason to register multiple such regulators. The user can simply supply all +consumers in one array and use it to initialise such a regulator. However, +in some cases it can be convenient to register multiple such regulators. +This is also a prerequisite for the upcoming patch, that will add a voltage +parameter to this function. The original function is provided as a wrapper +macro. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit dfad84aeab5f71b33a12e6803a809f698bdef5a2) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/regulator/fixed-helper.c | 14 +++++++++++--- + include/linux/regulator/fixed.h | 7 +++++-- + 2 files changed, 16 insertions(+), 5 deletions(-) + +diff --git a/drivers/regulator/fixed-helper.c b/drivers/regulator/fixed-helper.c +index cacd33c..3aa268d 100644 +--- a/drivers/regulator/fixed-helper.c ++++ b/drivers/regulator/fixed-helper.c +@@ -1,4 +1,5 @@ + #include <linux/slab.h> ++#include <linux/string.h> + #include <linux/platform_device.h> + #include <linux/regulator/machine.h> + #include <linux/regulator/fixed.h> +@@ -13,16 +14,18 @@ static void regulator_fixed_release(struct device *dev) + { + struct fixed_regulator_data *data = container_of(dev, + struct fixed_regulator_data, pdev.dev); ++ kfree(data->cfg.supply_name); + kfree(data); + } + + /** +- * regulator_register_fixed - register a no-op fixed regulator ++ * regulator_register_fixed_name - register a no-op fixed regulator + * @id: platform device id ++ * @name: name to be used for the regulator + * @supplies: consumers for this regulator + * @num_supplies: number of consumers + */ +-struct platform_device *regulator_register_fixed(int id, ++struct platform_device *regulator_register_always_on(int id, const char *name, + struct regulator_consumer_supply *supplies, int num_supplies) + { + struct fixed_regulator_data *data; +@@ -31,7 +34,12 @@ struct platform_device *regulator_register_fixed(int id, + if (!data) + return NULL; + +- data->cfg.supply_name = "fixed-dummy"; ++ data->cfg.supply_name = kstrdup(name, GFP_KERNEL); ++ if (!data->cfg.supply_name) { ++ kfree(data); ++ return NULL; ++ } ++ + data->cfg.microvolts = 0; + data->cfg.gpio = -EINVAL; + data->cfg.enabled_at_boot = 1; +diff --git a/include/linux/regulator/fixed.h b/include/linux/regulator/fixed.h +index 936a7d8..7bb456c 100644 +--- a/include/linux/regulator/fixed.h ++++ b/include/linux/regulator/fixed.h +@@ -51,14 +51,17 @@ struct fixed_voltage_config { + struct regulator_consumer_supply; + + #if IS_ENABLED(CONFIG_REGULATOR) +-struct platform_device *regulator_register_fixed(int id, ++struct platform_device *regulator_register_always_on(int id, const char *name, + struct regulator_consumer_supply *supplies, int num_supplies); + #else +-static inline struct platform_device *regulator_register_fixed(int id, ++static inline struct platform_device *regulator_register_always_on(int id, const char *name, + struct regulator_consumer_supply *supplies, int num_supplies) + { + return NULL; + } + #endif + ++#define regulator_register_fixed(id, s, ns) regulator_register_always_on(id, \ ++ "fixed-dummy", s, ns) ++ + #endif +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0005-regulator-extend-the-fixed-dummy-voltage-regulator-t.patch b/patches.armadillo800/0005-regulator-extend-the-fixed-dummy-voltage-regulator-t.patch new file mode 100644 index 0000000000000..dccde558658f1 --- /dev/null +++ b/patches.armadillo800/0005-regulator-extend-the-fixed-dummy-voltage-regulator-t.patch @@ -0,0 +1,70 @@ +From c5249f06fd57ea88ef47b750dc11a6f683bd5e5d Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Tue, 19 Jun 2012 17:44:39 +0200 +Subject: regulator: extend the fixed dummy voltage regulator to accept voltage + +Trivially extend the regulator_register_always_on() helper function to be +even more useful by adding a voltage parameter to it. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 15719ccc274981b19ad8fe9ac20c94249de8a257) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/regulator/fixed-helper.c | 5 +++-- + include/linux/regulator/fixed.h | 6 +++--- + 2 files changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/regulator/fixed-helper.c b/drivers/regulator/fixed-helper.c +index 3aa268d..f9d0279 100644 +--- a/drivers/regulator/fixed-helper.c ++++ b/drivers/regulator/fixed-helper.c +@@ -24,9 +24,10 @@ static void regulator_fixed_release(struct device *dev) + * @name: name to be used for the regulator + * @supplies: consumers for this regulator + * @num_supplies: number of consumers ++ * @uv: voltage in microvolts + */ + struct platform_device *regulator_register_always_on(int id, const char *name, +- struct regulator_consumer_supply *supplies, int num_supplies) ++ struct regulator_consumer_supply *supplies, int num_supplies, int uv) + { + struct fixed_regulator_data *data; + +@@ -40,7 +41,7 @@ struct platform_device *regulator_register_always_on(int id, const char *name, + return NULL; + } + +- data->cfg.microvolts = 0; ++ data->cfg.microvolts = uv; + data->cfg.gpio = -EINVAL; + data->cfg.enabled_at_boot = 1; + data->cfg.init_data = &data->init_data; +diff --git a/include/linux/regulator/fixed.h b/include/linux/regulator/fixed.h +index 7bb456c..f6372ee 100644 +--- a/include/linux/regulator/fixed.h ++++ b/include/linux/regulator/fixed.h +@@ -52,16 +52,16 @@ struct regulator_consumer_supply; + + #if IS_ENABLED(CONFIG_REGULATOR) + struct platform_device *regulator_register_always_on(int id, const char *name, +- struct regulator_consumer_supply *supplies, int num_supplies); ++ struct regulator_consumer_supply *supplies, int num_supplies, int uv); + #else + static inline struct platform_device *regulator_register_always_on(int id, const char *name, +- struct regulator_consumer_supply *supplies, int num_supplies) ++ struct regulator_consumer_supply *supplies, int num_supplies, int uv) + { + return NULL; + } + #endif + + #define regulator_register_fixed(id, s, ns) regulator_register_always_on(id, \ +- "fixed-dummy", s, ns) ++ "fixed-dummy", s, ns, 0) + + #endif +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0006-Input-gpio_keys-remove-useless-reinitialization-of-p.patch b/patches.armadillo800/0006-Input-gpio_keys-remove-useless-reinitialization-of-p.patch new file mode 100644 index 0000000000000..0f2761ddaffb0 --- /dev/null +++ b/patches.armadillo800/0006-Input-gpio_keys-remove-useless-reinitialization-of-p.patch @@ -0,0 +1,32 @@ +From 5f0a6815e3a7c5e73486b7b0a7ffffcf78b81cee Mon Sep 17 00:00:00 2001 +From: Tobias Klauser <tklauser@distanz.ch> +Date: Mon, 11 Jun 2012 23:55:32 -0700 +Subject: Input: gpio_keys - remove useless reinitialization of pdata->nbuttons + +pdata is zeroed using memset just a few lines before, so there is no +need to set the nbuttons member to 0 again. + +Signed-off-by: Tobias Klauser <tklauser@distanz.ch> +Signed-off-by: Dmitry Torokhov <dtor@mail.ru> +(cherry picked from commit 4eceb14f669cb9e9d189019e8fcbf73577fe77a7) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/input/keyboard/gpio_keys.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c +index 62bfce4..cbb1add 100644 +--- a/drivers/input/keyboard/gpio_keys.c ++++ b/drivers/input/keyboard/gpio_keys.c +@@ -559,7 +559,6 @@ static int gpio_keys_get_devtree_pdata(struct device *dev, + pdata->rep = !!of_get_property(node, "autorepeat", NULL); + + /* First count the subnodes */ +- pdata->nbuttons = 0; + pp = NULL; + while ((pp = of_get_next_child(node, pp))) + pdata->nbuttons++; +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0007-Input-st1232-add-device-tree-support.patch b/patches.armadillo800/0007-Input-st1232-add-device-tree-support.patch new file mode 100644 index 0000000000000..d0a9ee2bf9618 --- /dev/null +++ b/patches.armadillo800/0007-Input-st1232-add-device-tree-support.patch @@ -0,0 +1,49 @@ +From ccbea8cbb6f976a4ed42dfba5648bfb543f520d1 Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Tue, 3 Apr 2012 11:30:28 -0700 +Subject: Input: st1232 - add device tree support + +This patch enables DT support for the st1232 driver +which is primarily used on the sh7372 Mackerel board. + +[dtor@mail.ru: chnaged to use CONFIG_OF and of_match_ptr] +Signed-off-by: Magnus Damm <damm@opensource.se> +Acked-by: Arnd Bergmann <arnd@arndb.de> +Signed-off-by: Dmitry Torokhov <dtor@mail.ru> +(cherry picked from commit e6293d2f8a6cd427a1ef4ddecb16b1d5ae1929cd) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/input/touchscreen/st1232.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c +index cbbf71b..216fabb 100644 +--- a/drivers/input/touchscreen/st1232.c ++++ b/drivers/input/touchscreen/st1232.c +@@ -255,6 +255,14 @@ static const struct i2c_device_id st1232_ts_id[] = { + }; + MODULE_DEVICE_TABLE(i2c, st1232_ts_id); + ++#ifdef CONFIG_OF ++static const struct of_device_id st1232_ts_dt_ids[] __devinitconst = { ++ { .compatible = "sitronix,st1232", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids); ++#endif ++ + static struct i2c_driver st1232_ts_driver = { + .probe = st1232_ts_probe, + .remove = __devexit_p(st1232_ts_remove), +@@ -262,6 +270,7 @@ static struct i2c_driver st1232_ts_driver = { + .driver = { + .name = ST1232_TS_NAME, + .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(st1232_ts_dt_ids), + #ifdef CONFIG_PM + .pm = &st1232_ts_pm_ops, + #endif +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0008-Input-st1232-switch-to-using-SIMPLE_DEV_PM_OPS.patch b/patches.armadillo800/0008-Input-st1232-switch-to-using-SIMPLE_DEV_PM_OPS.patch new file mode 100644 index 0000000000000..95252d1ed1bb0 --- /dev/null +++ b/patches.armadillo800/0008-Input-st1232-switch-to-using-SIMPLE_DEV_PM_OPS.patch @@ -0,0 +1,57 @@ +From 456b9180124a8edec6c90cbd4d2b3f7c8a09a6f7 Mon Sep 17 00:00:00 2001 +From: Dmitry Torokhov <dmitry.torokhov@gmail.com> +Date: Tue, 3 Apr 2012 11:30:28 -0700 +Subject: Input: st1232 - switch to using SIMPLE_DEV_PM_OPS + +Acked-by: Rafael J. Wysocki <rjw@sisk.pl> +Reviewed-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Dmitry Torokhov <dtor@mail.ru> +(cherry picked from commit b3571400395e318306165eabbfbe05a4c3e4366c) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/input/touchscreen/st1232.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c +index 216fabb..6cb68a1 100644 +--- a/drivers/input/touchscreen/st1232.c ++++ b/drivers/input/touchscreen/st1232.c +@@ -218,7 +218,7 @@ static int __devexit st1232_ts_remove(struct i2c_client *client) + return 0; + } + +-#ifdef CONFIG_PM ++#ifdef CONFIG_PM_SLEEP + static int st1232_ts_suspend(struct device *dev) + { + struct i2c_client *client = to_i2c_client(dev); +@@ -243,12 +243,11 @@ static int st1232_ts_resume(struct device *dev) + return 0; + } + +-static const struct dev_pm_ops st1232_ts_pm_ops = { +- .suspend = st1232_ts_suspend, +- .resume = st1232_ts_resume, +-}; + #endif + ++static SIMPLE_DEV_PM_OPS(st1232_ts_pm_ops, ++ st1232_ts_suspend, st1232_ts_resume); ++ + static const struct i2c_device_id st1232_ts_id[] = { + { ST1232_TS_NAME, 0 }, + { } +@@ -271,9 +270,7 @@ static struct i2c_driver st1232_ts_driver = { + .name = ST1232_TS_NAME, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(st1232_ts_dt_ids), +-#ifdef CONFIG_PM + .pm = &st1232_ts_pm_ops, +-#endif + }, + }; + +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0009-net-sh_eth-add-support-R8A7740.patch b/patches.armadillo800/0009-net-sh_eth-add-support-R8A7740.patch new file mode 100644 index 0000000000000..24501ce745b1b --- /dev/null +++ b/patches.armadillo800/0009-net-sh_eth-add-support-R8A7740.patch @@ -0,0 +1,209 @@ +From 38480ba305384441ebefad2684028756f7eab8b2 Mon Sep 17 00:00:00 2001 +From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Date: Wed, 4 Apr 2012 18:37:10 +0000 +Subject: net: sh_eth: add support R8A7740 + +The R8A7740 has a Gigabit Ethernet MAC. This patch supports it. + +Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Tested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +(cherry picked from commit 73a0d907301ece200d32b4e8ba2da2ca296b507f) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/net/ethernet/renesas/Kconfig | 7 ++- + drivers/net/ethernet/renesas/sh_eth.c | 114 +++++++++++++++++++++++++++++++++- + drivers/net/ethernet/renesas/sh_eth.h | 5 +- + 3 files changed, 120 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig +index 3fb2355..46df3a0 100644 +--- a/drivers/net/ethernet/renesas/Kconfig ++++ b/drivers/net/ethernet/renesas/Kconfig +@@ -4,11 +4,11 @@ + + config SH_ETH + tristate "Renesas SuperH Ethernet support" +- depends on SUPERH && \ ++ depends on (SUPERH || ARCH_SHMOBILE) && \ + (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \ + CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \ + CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7734 || \ +- CPU_SUBTYPE_SH7757) ++ CPU_SUBTYPE_SH7757 || ARCH_R8A7740) + select CRC32 + select NET_CORE + select MII +@@ -17,4 +17,5 @@ config SH_ETH + ---help--- + Renesas SuperH Ethernet device driver. + This driver supporting CPUs are: +- - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763 and SH7757. ++ - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763, SH7757, ++ and R8A7740. +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index d63e09b..be3c221 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -386,6 +386,114 @@ static void sh_eth_reset_hw_crc(struct net_device *ndev) + sh_eth_write(ndev, 0x0, CSMR); + } + ++#elif defined(CONFIG_ARCH_R8A7740) ++#define SH_ETH_HAS_TSU 1 ++static void sh_eth_chip_reset(struct net_device *ndev) ++{ ++ struct sh_eth_private *mdp = netdev_priv(ndev); ++ unsigned long mii; ++ ++ /* reset device */ ++ sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR); ++ mdelay(1); ++ ++ switch (mdp->phy_interface) { ++ case PHY_INTERFACE_MODE_GMII: ++ mii = 2; ++ break; ++ case PHY_INTERFACE_MODE_MII: ++ mii = 1; ++ break; ++ case PHY_INTERFACE_MODE_RMII: ++ default: ++ mii = 0; ++ break; ++ } ++ sh_eth_write(ndev, mii, RMII_MII); ++} ++ ++static void sh_eth_reset(struct net_device *ndev) ++{ ++ int cnt = 100; ++ ++ sh_eth_write(ndev, EDSR_ENALL, EDSR); ++ sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR); ++ while (cnt > 0) { ++ if (!(sh_eth_read(ndev, EDMR) & 0x3)) ++ break; ++ mdelay(1); ++ cnt--; ++ } ++ if (cnt == 0) ++ printk(KERN_ERR "Device reset fail\n"); ++ ++ /* Table Init */ ++ sh_eth_write(ndev, 0x0, TDLAR); ++ sh_eth_write(ndev, 0x0, TDFAR); ++ sh_eth_write(ndev, 0x0, TDFXR); ++ sh_eth_write(ndev, 0x0, TDFFR); ++ sh_eth_write(ndev, 0x0, RDLAR); ++ sh_eth_write(ndev, 0x0, RDFAR); ++ sh_eth_write(ndev, 0x0, RDFXR); ++ sh_eth_write(ndev, 0x0, RDFFR); ++} ++ ++static void sh_eth_set_duplex(struct net_device *ndev) ++{ ++ struct sh_eth_private *mdp = netdev_priv(ndev); ++ ++ if (mdp->duplex) /* Full */ ++ sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR); ++ else /* Half */ ++ sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR); ++} ++ ++static void sh_eth_set_rate(struct net_device *ndev) ++{ ++ struct sh_eth_private *mdp = netdev_priv(ndev); ++ ++ switch (mdp->speed) { ++ case 10: /* 10BASE */ ++ sh_eth_write(ndev, GECMR_10, GECMR); ++ break; ++ case 100:/* 100BASE */ ++ sh_eth_write(ndev, GECMR_100, GECMR); ++ break; ++ case 1000: /* 1000BASE */ ++ sh_eth_write(ndev, GECMR_1000, GECMR); ++ break; ++ default: ++ break; ++ } ++} ++ ++/* R8A7740 */ ++static struct sh_eth_cpu_data sh_eth_my_cpu_data = { ++ .chip_reset = sh_eth_chip_reset, ++ .set_duplex = sh_eth_set_duplex, ++ .set_rate = sh_eth_set_rate, ++ ++ .ecsr_value = ECSR_ICD | ECSR_MPD, ++ .ecsipr_value = ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP, ++ .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff, ++ ++ .tx_check = EESR_TC1 | EESR_FTC, ++ .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \ ++ EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \ ++ EESR_ECI, ++ .tx_error_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \ ++ EESR_TFE, ++ ++ .apr = 1, ++ .mpr = 1, ++ .tpauser = 1, ++ .bculr = 1, ++ .hw_swap = 1, ++ .no_trimd = 1, ++ .no_ade = 1, ++ .tsu = 1, ++}; ++ + #elif defined(CONFIG_CPU_SUBTYPE_SH7619) + #define SH_ETH_RESET_DEFAULT 1 + static struct sh_eth_cpu_data sh_eth_my_cpu_data = { +@@ -443,7 +551,7 @@ static void sh_eth_reset(struct net_device *ndev) + } + #endif + +-#if defined(CONFIG_CPU_SH4) ++#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) + static void sh_eth_set_receive_align(struct sk_buff *skb) + { + int reserve; +@@ -919,6 +1027,10 @@ static int sh_eth_rx(struct net_device *ndev) + desc_status = edmac_to_cpu(mdp, rxdesc->status); + pkt_len = rxdesc->frame_length; + ++#if defined(CONFIG_ARCH_R8A7740) ++ desc_status >>= 16; ++#endif ++ + if (--boguscnt < 0) + break; + +diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h +index 0fa14afc..57b8e1f 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.h ++++ b/drivers/net/ethernet/renesas/sh_eth.h +@@ -372,7 +372,7 @@ static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = { + }; + + /* Driver's parameters */ +-#if defined(CONFIG_CPU_SH4) ++#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) + #define SH4_SKB_RX_ALIGN 32 + #else + #define SH2_SH3_SKB_RX_ALIGN 2 +@@ -381,7 +381,8 @@ static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = { + /* + * Register's bits + */ +-#if defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763) ++#if defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763) ||\ ++ defined(CONFIG_ARCH_R8A7740) + /* EDSR */ + enum EDSR_BIT { + EDSR_ENT = 0x01, EDSR_ENR = 0x02, +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0010-net-sh_eth-fix-the-rxdesc-pointer-when-rx-descriptor.patch b/patches.armadillo800/0010-net-sh_eth-fix-the-rxdesc-pointer-when-rx-descriptor.patch new file mode 100644 index 0000000000000..f06a9706150d8 --- /dev/null +++ b/patches.armadillo800/0010-net-sh_eth-fix-the-rxdesc-pointer-when-rx-descriptor.patch @@ -0,0 +1,48 @@ +From 02098572c84a88121b0baeb2b96cea47f17f2e3e Mon Sep 17 00:00:00 2001 +From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Date: Mon, 28 May 2012 23:07:55 +0000 +Subject: net: sh_eth: fix the rxdesc pointer when rx descriptor empty happens + +When Receive Descriptor Empty happens, rxdesc pointer of the driver +and actual next descriptor of the controller may be mismatch. +This patch fixes it. + +Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +(cherry picked from commit 79fba9f51755c704c0a7d7b7f0df10874dc0a744) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/net/ethernet/renesas/sh_eth.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index be3c221..667169b 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -1101,8 +1101,12 @@ static int sh_eth_rx(struct net_device *ndev) + + /* Restart Rx engine if stopped. */ + /* If we don't need to check status, don't. -KDU */ +- if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R)) ++ if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R)) { ++ /* fix the values for the next receiving */ ++ mdp->cur_rx = mdp->dirty_rx = (sh_eth_read(ndev, RDFAR) - ++ sh_eth_read(ndev, RDLAR)) >> 4; + sh_eth_write(ndev, EDRRR_R, EDRRR); ++ } + + return 0; + } +@@ -1199,8 +1203,6 @@ static void sh_eth_error(struct net_device *ndev, int intr_status) + /* Receive Descriptor Empty int */ + ndev->stats.rx_over_errors++; + +- if (sh_eth_read(ndev, EDRRR) ^ EDRRR_R) +- sh_eth_write(ndev, EDRRR_R, EDRRR); + if (netif_msg_rx_err(mdp)) + dev_err(&ndev->dev, "Receive Descriptor Empty\n"); + } +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0011-net-sh_eth-fix-the-condition-to-fix-the-cur_tx-dirty.patch b/patches.armadillo800/0011-net-sh_eth-fix-the-condition-to-fix-the-cur_tx-dirty.patch new file mode 100644 index 0000000000000..9d3e463e2e06b --- /dev/null +++ b/patches.armadillo800/0011-net-sh_eth-fix-the-condition-to-fix-the-cur_tx-dirty.patch @@ -0,0 +1,65 @@ +From 1c70638e065f5a6bba99f0e27a3b4a4931c77681 Mon Sep 17 00:00:00 2001 +From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Date: Wed, 20 Jun 2012 15:26:34 +0000 +Subject: net: sh_eth: fix the condition to fix the cur_tx/dirty_rx + +The following commit couldn't work if the RMCR is not set to 1. + +"net: sh_eth: fix the rxdesc pointer when rx descriptor empty happens" +commit id 79fba9f51755c704c0a7d7b7f0df10874dc0a744 + +If RMCR is not set, the controller will clear the EDRRR after it received +a frame. In this case, the driver doesn't need to fix the value of +cur_rx/dirty_rx. The driver only needs it when the controll detects +receive descriptors are empty. + +Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Tested-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: David S. Miller <davem@davemloft.net> +(cherry picked from commit a18e08bdcf845efb7344cea146e683df746bbfb4) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/net/ethernet/renesas/sh_eth.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index 667169b..79bf09b 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -1011,7 +1011,7 @@ static int sh_eth_txfree(struct net_device *ndev) + } + + /* Packet receive function */ +-static int sh_eth_rx(struct net_device *ndev) ++static int sh_eth_rx(struct net_device *ndev, u32 intr_status) + { + struct sh_eth_private *mdp = netdev_priv(ndev); + struct sh_eth_rxdesc *rxdesc; +@@ -1102,9 +1102,11 @@ static int sh_eth_rx(struct net_device *ndev) + /* Restart Rx engine if stopped. */ + /* If we don't need to check status, don't. -KDU */ + if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R)) { +- /* fix the values for the next receiving */ +- mdp->cur_rx = mdp->dirty_rx = (sh_eth_read(ndev, RDFAR) - +- sh_eth_read(ndev, RDLAR)) >> 4; ++ /* fix the values for the next receiving if RDE is set */ ++ if (intr_status & EESR_RDE) ++ mdp->cur_rx = mdp->dirty_rx = ++ (sh_eth_read(ndev, RDFAR) - ++ sh_eth_read(ndev, RDLAR)) >> 4; + sh_eth_write(ndev, EDRRR_R, EDRRR); + } + +@@ -1273,7 +1275,7 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) + EESR_RTSF | /* short frame recv */ + EESR_PRE | /* PHY-LSI recv error */ + EESR_CERF)){ /* recv frame CRC error */ +- sh_eth_rx(ndev); ++ sh_eth_rx(ndev, intr_status); + } + + /* Tx Check */ +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0012-net-sh-eth-Add-support-selecting-MII-function-for-SH.patch b/patches.armadillo800/0012-net-sh-eth-Add-support-selecting-MII-function-for-SH.patch new file mode 100644 index 0000000000000..66b1134781ac5 --- /dev/null +++ b/patches.armadillo800/0012-net-sh-eth-Add-support-selecting-MII-function-for-SH.patch @@ -0,0 +1,196 @@ +From a9d45f3559e2b48428446114ae6817f8a4883de8 Mon Sep 17 00:00:00 2001 +From: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> +Date: Mon, 25 Jun 2012 17:34:14 +0000 +Subject: net/sh-eth: Add support selecting MII function for SH7734 and R8A7740 + +Ethernet IP of SH7734 and R8A7740 has selecting MII register. +The user needs to change a value according to MII to be used. +This adds the function to change the value of this register. + +Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +(cherry picked from commit 5e7a76be0e48217aff6b6f34bdcce4725db999e2) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/net/ethernet/renesas/sh_eth.c | 108 ++++++++++++++++++++-------------- + drivers/net/ethernet/renesas/sh_eth.h | 1 + + 2 files changed, 66 insertions(+), 43 deletions(-) + +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index 79bf09b..8d696e0 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -49,6 +49,34 @@ + NETIF_MSG_RX_ERR| \ + NETIF_MSG_TX_ERR) + ++#if defined(CONFIG_CPU_SUBTYPE_SH7734) || \ ++ defined(CONFIG_CPU_SUBTYPE_SH7763) || \ ++ defined(CONFIG_ARCH_R8A7740) ++static void sh_eth_select_mii(struct net_device *ndev) ++{ ++ u32 value = 0x0; ++ struct sh_eth_private *mdp = netdev_priv(ndev); ++ ++ switch (mdp->phy_interface) { ++ case PHY_INTERFACE_MODE_GMII: ++ value = 0x2; ++ break; ++ case PHY_INTERFACE_MODE_MII: ++ value = 0x1; ++ break; ++ case PHY_INTERFACE_MODE_RMII: ++ value = 0x0; ++ break; ++ default: ++ pr_warn("PHY interface mode was not setup. Set to MII.\n"); ++ value = 0x1; ++ break; ++ } ++ ++ sh_eth_write(ndev, value, RMII_MII); ++} ++#endif ++ + /* There is CPU dependent code */ + #if defined(CONFIG_CPU_SUBTYPE_SH7724) + #define SH_ETH_RESET_DEFAULT 1 +@@ -283,6 +311,7 @@ static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp) + #elif defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763) + #define SH_ETH_HAS_TSU 1 + static void sh_eth_reset_hw_crc(struct net_device *ndev); ++ + static void sh_eth_chip_reset(struct net_device *ndev) + { + struct sh_eth_private *mdp = netdev_priv(ndev); +@@ -292,35 +321,6 @@ static void sh_eth_chip_reset(struct net_device *ndev) + mdelay(1); + } + +-static void sh_eth_reset(struct net_device *ndev) +-{ +- int cnt = 100; +- +- sh_eth_write(ndev, EDSR_ENALL, EDSR); +- sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR); +- while (cnt > 0) { +- if (!(sh_eth_read(ndev, EDMR) & 0x3)) +- break; +- mdelay(1); +- cnt--; +- } +- if (cnt == 0) +- printk(KERN_ERR "Device reset fail\n"); +- +- /* Table Init */ +- sh_eth_write(ndev, 0x0, TDLAR); +- sh_eth_write(ndev, 0x0, TDFAR); +- sh_eth_write(ndev, 0x0, TDFXR); +- sh_eth_write(ndev, 0x0, TDFFR); +- sh_eth_write(ndev, 0x0, RDLAR); +- sh_eth_write(ndev, 0x0, RDFAR); +- sh_eth_write(ndev, 0x0, RDFXR); +- sh_eth_write(ndev, 0x0, RDFFR); +- +- /* Reset HW CRC register */ +- sh_eth_reset_hw_crc(ndev); +-} +- + static void sh_eth_set_duplex(struct net_device *ndev) + { + struct sh_eth_private *mdp = netdev_priv(ndev); +@@ -377,9 +377,43 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { + .tsu = 1, + #if defined(CONFIG_CPU_SUBTYPE_SH7734) + .hw_crc = 1, ++ .select_mii = 1, + #endif + }; + ++static void sh_eth_reset(struct net_device *ndev) ++{ ++ int cnt = 100; ++ ++ sh_eth_write(ndev, EDSR_ENALL, EDSR); ++ sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR); ++ while (cnt > 0) { ++ if (!(sh_eth_read(ndev, EDMR) & 0x3)) ++ break; ++ mdelay(1); ++ cnt--; ++ } ++ if (cnt == 0) ++ printk(KERN_ERR "Device reset fail\n"); ++ ++ /* Table Init */ ++ sh_eth_write(ndev, 0x0, TDLAR); ++ sh_eth_write(ndev, 0x0, TDFAR); ++ sh_eth_write(ndev, 0x0, TDFXR); ++ sh_eth_write(ndev, 0x0, TDFFR); ++ sh_eth_write(ndev, 0x0, RDLAR); ++ sh_eth_write(ndev, 0x0, RDFAR); ++ sh_eth_write(ndev, 0x0, RDFXR); ++ sh_eth_write(ndev, 0x0, RDFFR); ++ ++ /* Reset HW CRC register */ ++ sh_eth_reset_hw_crc(ndev); ++ ++ /* Select MII mode */ ++ if (sh_eth_my_cpu_data.select_mii) ++ sh_eth_select_mii(ndev); ++} ++ + static void sh_eth_reset_hw_crc(struct net_device *ndev) + { + if (sh_eth_my_cpu_data.hw_crc) +@@ -391,25 +425,12 @@ static void sh_eth_reset_hw_crc(struct net_device *ndev) + static void sh_eth_chip_reset(struct net_device *ndev) + { + struct sh_eth_private *mdp = netdev_priv(ndev); +- unsigned long mii; + + /* reset device */ + sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR); + mdelay(1); + +- switch (mdp->phy_interface) { +- case PHY_INTERFACE_MODE_GMII: +- mii = 2; +- break; +- case PHY_INTERFACE_MODE_MII: +- mii = 1; +- break; +- case PHY_INTERFACE_MODE_RMII: +- default: +- mii = 0; +- break; +- } +- sh_eth_write(ndev, mii, RMII_MII); ++ sh_eth_select_mii(ndev); + } + + static void sh_eth_reset(struct net_device *ndev) +@@ -492,6 +513,7 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { + .no_trimd = 1, + .no_ade = 1, + .tsu = 1, ++ .select_mii = 1, + }; + + #elif defined(CONFIG_CPU_SUBTYPE_SH7619) +diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h +index 57b8e1f..d6763b1392 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.h ++++ b/drivers/net/ethernet/renesas/sh_eth.h +@@ -757,6 +757,7 @@ struct sh_eth_cpu_data { + unsigned no_trimd:1; /* E-DMAC DO NOT have TRIMD */ + unsigned no_ade:1; /* E-DMAC DO NOT have ADE bit in EESR */ + unsigned hw_crc:1; /* E-DMAC have CSMR */ ++ unsigned select_mii:1; /* EtherC have RMII_MII (MII select register) */ + }; + + struct sh_eth_private { +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0013-net-sh-eth-Check-return-value-of-sh_eth_reset-when-c.patch b/patches.armadillo800/0013-net-sh-eth-Check-return-value-of-sh_eth_reset-when-c.patch new file mode 100644 index 0000000000000..1cca1a6b8fa9a --- /dev/null +++ b/patches.armadillo800/0013-net-sh-eth-Check-return-value-of-sh_eth_reset-when-c.patch @@ -0,0 +1,215 @@ +From d9b780ce68b329aa745868803ec0419a3fd6975f Mon Sep 17 00:00:00 2001 +From: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> +Date: Mon, 25 Jun 2012 17:35:12 +0000 +Subject: net/sh-eth: Check return value of sh_eth_reset when chip reset fail + +The sh_eth_reset function resets chip, but this performs nothing when failed. +This changes sh_eth_reset return an error, when this failed in reset. + +Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +(cherry picked from commit 5cee1d37c9f565f1aa515408863dbb13db67dab9) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/net/ethernet/renesas/sh_eth.c | 88 ++++++++++++++++++++++------------- + 1 file changed, 56 insertions(+), 32 deletions(-) + +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index 8d696e0..326cb91 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -130,6 +130,8 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { + #elif defined(CONFIG_CPU_SUBTYPE_SH7757) + #define SH_ETH_HAS_BOTH_MODULES 1 + #define SH_ETH_HAS_TSU 1 ++static int sh_eth_check_reset(struct net_device *ndev); ++ + static void sh_eth_set_duplex(struct net_device *ndev) + { + struct sh_eth_private *mdp = netdev_priv(ndev); +@@ -204,23 +206,19 @@ static void sh_eth_chip_reset_giga(struct net_device *ndev) + } + + static int sh_eth_is_gether(struct sh_eth_private *mdp); +-static void sh_eth_reset(struct net_device *ndev) ++static int sh_eth_reset(struct net_device *ndev) + { + struct sh_eth_private *mdp = netdev_priv(ndev); +- int cnt = 100; ++ int ret = 0; + + if (sh_eth_is_gether(mdp)) { + sh_eth_write(ndev, 0x03, EDSR); + sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, + EDMR); +- while (cnt > 0) { +- if (!(sh_eth_read(ndev, EDMR) & 0x3)) +- break; +- mdelay(1); +- cnt--; +- } +- if (cnt < 0) +- printk(KERN_ERR "Device reset fail\n"); ++ ++ ret = sh_eth_check_reset(ndev); ++ if (ret) ++ goto out; + + /* Table Init */ + sh_eth_write(ndev, 0x0, TDLAR); +@@ -238,6 +236,9 @@ static void sh_eth_reset(struct net_device *ndev) + sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER, + EDMR); + } ++ ++out: ++ return ret; + } + + static void sh_eth_set_duplex_giga(struct net_device *ndev) +@@ -310,6 +311,7 @@ static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp) + + #elif defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763) + #define SH_ETH_HAS_TSU 1 ++static int sh_eth_check_reset(struct net_device *ndev); + static void sh_eth_reset_hw_crc(struct net_device *ndev); + + static void sh_eth_chip_reset(struct net_device *ndev) +@@ -381,20 +383,16 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { + #endif + }; + +-static void sh_eth_reset(struct net_device *ndev) ++static int sh_eth_reset(struct net_device *ndev) + { +- int cnt = 100; ++ int ret = 0; + + sh_eth_write(ndev, EDSR_ENALL, EDSR); + sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR); +- while (cnt > 0) { +- if (!(sh_eth_read(ndev, EDMR) & 0x3)) +- break; +- mdelay(1); +- cnt--; +- } +- if (cnt == 0) +- printk(KERN_ERR "Device reset fail\n"); ++ ++ ret = sh_eth_check_reset(ndev); ++ if (ret) ++ goto out; + + /* Table Init */ + sh_eth_write(ndev, 0x0, TDLAR); +@@ -412,6 +410,8 @@ static void sh_eth_reset(struct net_device *ndev) + /* Select MII mode */ + if (sh_eth_my_cpu_data.select_mii) + sh_eth_select_mii(ndev); ++out: ++ return ret; + } + + static void sh_eth_reset_hw_crc(struct net_device *ndev) +@@ -422,6 +422,8 @@ static void sh_eth_reset_hw_crc(struct net_device *ndev) + + #elif defined(CONFIG_ARCH_R8A7740) + #define SH_ETH_HAS_TSU 1 ++static int sh_eth_check_reset(struct net_device *ndev); ++ + static void sh_eth_chip_reset(struct net_device *ndev) + { + struct sh_eth_private *mdp = netdev_priv(ndev); +@@ -433,20 +435,16 @@ static void sh_eth_chip_reset(struct net_device *ndev) + sh_eth_select_mii(ndev); + } + +-static void sh_eth_reset(struct net_device *ndev) ++static int sh_eth_reset(struct net_device *ndev) + { +- int cnt = 100; ++ int ret = 0; + + sh_eth_write(ndev, EDSR_ENALL, EDSR); + sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR); +- while (cnt > 0) { +- if (!(sh_eth_read(ndev, EDMR) & 0x3)) +- break; +- mdelay(1); +- cnt--; +- } +- if (cnt == 0) +- printk(KERN_ERR "Device reset fail\n"); ++ ++ ret = sh_eth_check_reset(ndev); ++ if (ret) ++ goto out; + + /* Table Init */ + sh_eth_write(ndev, 0x0, TDLAR); +@@ -457,6 +455,9 @@ static void sh_eth_reset(struct net_device *ndev) + sh_eth_write(ndev, 0x0, RDFAR); + sh_eth_write(ndev, 0x0, RDFXR); + sh_eth_write(ndev, 0x0, RDFFR); ++ ++out: ++ return ret; + } + + static void sh_eth_set_duplex(struct net_device *ndev) +@@ -565,11 +566,31 @@ static void sh_eth_set_default_cpu_data(struct sh_eth_cpu_data *cd) + + #if defined(SH_ETH_RESET_DEFAULT) + /* Chip Reset */ +-static void sh_eth_reset(struct net_device *ndev) ++static int sh_eth_reset(struct net_device *ndev) + { + sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER, EDMR); + mdelay(3); + sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER, EDMR); ++ ++ return 0; ++} ++#else ++static int sh_eth_check_reset(struct net_device *ndev) ++{ ++ int ret = 0; ++ int cnt = 100; ++ ++ while (cnt > 0) { ++ if (!(sh_eth_read(ndev, EDMR) & 0x3)) ++ break; ++ mdelay(1); ++ cnt--; ++ } ++ if (cnt < 0) { ++ printk(KERN_ERR "Device reset fail\n"); ++ ret = -ETIMEDOUT; ++ } ++ return ret; + } + #endif + +@@ -924,7 +945,9 @@ static int sh_eth_dev_init(struct net_device *ndev) + u32 val; + + /* Soft Reset */ +- sh_eth_reset(ndev); ++ ret = sh_eth_reset(ndev); ++ if (ret) ++ goto out; + + /* Descriptor format */ + sh_eth_ring_format(ndev); +@@ -998,6 +1021,7 @@ static int sh_eth_dev_init(struct net_device *ndev) + + netif_start_queue(ndev); + ++out: + return ret; + } + +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0014-net-sh_eth-remove-unnecessary-function.patch b/patches.armadillo800/0014-net-sh_eth-remove-unnecessary-function.patch new file mode 100644 index 0000000000000..029365f01b9be --- /dev/null +++ b/patches.armadillo800/0014-net-sh_eth-remove-unnecessary-function.patch @@ -0,0 +1,94 @@ +From da239ac021220b753bc1f21495ed187275f935aa Mon Sep 17 00:00:00 2001 +From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Date: Tue, 26 Jun 2012 19:59:51 +0000 +Subject: net: sh_eth: remove unnecessary function + +The sh_eth_timer() called mod_timer() for itself. So, this patch +removes the function. + +Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +(cherry picked from commit c26502680e59af556211fc3fd3ae0f2aa5d98440) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/net/ethernet/renesas/sh_eth.c | 22 ---------------------- + drivers/net/ethernet/renesas/sh_eth.h | 1 - + 2 files changed, 23 deletions(-) + +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index 326cb91..cf0bc31 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -1339,14 +1339,6 @@ other_irq: + return ret; + } + +-static void sh_eth_timer(unsigned long data) +-{ +- struct net_device *ndev = (struct net_device *)data; +- struct sh_eth_private *mdp = netdev_priv(ndev); +- +- mod_timer(&mdp->timer, jiffies + (10 * HZ)); +-} +- + /* PHY state control function */ + static void sh_eth_adjust_link(struct net_device *ndev) + { +@@ -1594,11 +1586,6 @@ static int sh_eth_open(struct net_device *ndev) + if (ret) + goto out_free_irq; + +- /* Set the timer to check for link beat. */ +- init_timer(&mdp->timer); +- mdp->timer.expires = (jiffies + (24 * HZ)) / 10;/* 2.4 sec. */ +- setup_timer(&mdp->timer, sh_eth_timer, (unsigned long)ndev); +- + return ret; + + out_free_irq: +@@ -1623,9 +1610,6 @@ static void sh_eth_tx_timeout(struct net_device *ndev) + /* tx_errors count up */ + ndev->stats.tx_errors++; + +- /* timer off */ +- del_timer_sync(&mdp->timer); +- + /* Free all the skbuffs in the Rx queue. */ + for (i = 0; i < RX_RING_SIZE; i++) { + rxdesc = &mdp->rx_ring[i]; +@@ -1643,10 +1627,6 @@ static void sh_eth_tx_timeout(struct net_device *ndev) + + /* device init */ + sh_eth_dev_init(ndev); +- +- /* timer on */ +- mdp->timer.expires = (jiffies + (24 * HZ)) / 10;/* 2.4 sec. */ +- add_timer(&mdp->timer); + } + + /* Packet transmit function */ +@@ -1719,8 +1699,6 @@ static int sh_eth_close(struct net_device *ndev) + + free_irq(ndev->irq, ndev); + +- del_timer_sync(&mdp->timer); +- + /* Free all the skbuffs in the Rx queue. */ + sh_eth_ring_free(ndev); + +diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h +index d6763b1392..5af3f2a 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.h ++++ b/drivers/net/ethernet/renesas/sh_eth.h +@@ -772,7 +772,6 @@ struct sh_eth_private { + struct sh_eth_txdesc *tx_ring; + struct sk_buff **rx_skbuff; + struct sk_buff **tx_skbuff; +- struct timer_list timer; + spinlock_t lock; + u32 cur_rx, dirty_rx; /* Producer/consumer ring indices */ + u32 cur_tx, dirty_tx; +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0015-net-sh_eth-remove-unnecessary-members-definitions.patch b/patches.armadillo800/0015-net-sh_eth-remove-unnecessary-members-definitions.patch new file mode 100644 index 0000000000000..95923c02d6925 --- /dev/null +++ b/patches.armadillo800/0015-net-sh_eth-remove-unnecessary-members-definitions.patch @@ -0,0 +1,140 @@ +From c0de8fd97587b151f04aeb92c1946d30e04b3f8a Mon Sep 17 00:00:00 2001 +From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Date: Tue, 26 Jun 2012 19:59:58 +0000 +Subject: net: sh_eth: remove unnecessary members/definitions + +This patch removes unnecessary members in sh_th_private. +This patch also removes unnecessary definitions in sh_eth.h + +Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +(cherry picked from commit 2ecbb783c3bf5a63f555c39deef308dcc1902b7f) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/net/ethernet/renesas/sh_eth.c | 7 +--- + drivers/net/ethernet/renesas/sh_eth.h | 69 ----------------------------------- + 2 files changed, 1 insertion(+), 75 deletions(-) + +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index cf0bc31..43e76d2 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -941,7 +941,6 @@ static int sh_eth_dev_init(struct net_device *ndev) + { + int ret = 0; + struct sh_eth_private *mdp = netdev_priv(ndev); +- u_int32_t rx_int_var, tx_int_var; + u32 val; + + /* Soft Reset */ +@@ -971,9 +970,7 @@ static int sh_eth_dev_init(struct net_device *ndev) + /* Frame recv control */ + sh_eth_write(ndev, mdp->cd->rmcr_value, RMCR); + +- rx_int_var = mdp->rx_int_var = DESC_I_RINT8 | DESC_I_RINT5; +- tx_int_var = mdp->tx_int_var = DESC_I_TINT2; +- sh_eth_write(ndev, rx_int_var | tx_int_var, TRSCER); ++ sh_eth_write(ndev, DESC_I_RINT8 | DESC_I_RINT5 | DESC_I_TINT2, TRSCER); + + if (mdp->cd->bculr) + sh_eth_write(ndev, 0x800, BCULR); /* Burst sycle set */ +@@ -2336,8 +2333,6 @@ static int sh_eth_drv_probe(struct platform_device *pdev) + + /* debug message level */ + mdp->msg_enable = SH_ETH_DEF_MSG_ENABLE; +- mdp->post_rx = POST_RX >> (devno << 1); +- mdp->post_fw = POST_FW >> (devno << 1); + + /* read and set MAC address */ + read_mac_address(ndev, pd->mac_addr); +diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h +index 5af3f2a..37a0702 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.h ++++ b/drivers/net/ethernet/renesas/sh_eth.h +@@ -585,71 +585,6 @@ enum RPADIR_BIT { + /* FDR */ + #define DEFAULT_FDR_INIT 0x00000707 + +-enum phy_offsets { +- PHY_CTRL = 0, PHY_STAT = 1, PHY_IDT1 = 2, PHY_IDT2 = 3, +- PHY_ANA = 4, PHY_ANL = 5, PHY_ANE = 6, +- PHY_16 = 16, +-}; +- +-/* PHY_CTRL */ +-enum PHY_CTRL_BIT { +- PHY_C_RESET = 0x8000, PHY_C_LOOPBK = 0x4000, PHY_C_SPEEDSL = 0x2000, +- PHY_C_ANEGEN = 0x1000, PHY_C_PWRDN = 0x0800, PHY_C_ISO = 0x0400, +- PHY_C_RANEG = 0x0200, PHY_C_DUPLEX = 0x0100, PHY_C_COLT = 0x0080, +-}; +-#define DM9161_PHY_C_ANEGEN 0 /* auto nego special */ +- +-/* PHY_STAT */ +-enum PHY_STAT_BIT { +- PHY_S_100T4 = 0x8000, PHY_S_100X_F = 0x4000, PHY_S_100X_H = 0x2000, +- PHY_S_10T_F = 0x1000, PHY_S_10T_H = 0x0800, PHY_S_ANEGC = 0x0020, +- PHY_S_RFAULT = 0x0010, PHY_S_ANEGA = 0x0008, PHY_S_LINK = 0x0004, +- PHY_S_JAB = 0x0002, PHY_S_EXTD = 0x0001, +-}; +- +-/* PHY_ANA */ +-enum PHY_ANA_BIT { +- PHY_A_NP = 0x8000, PHY_A_ACK = 0x4000, PHY_A_RF = 0x2000, +- PHY_A_FCS = 0x0400, PHY_A_T4 = 0x0200, PHY_A_FDX = 0x0100, +- PHY_A_HDX = 0x0080, PHY_A_10FDX = 0x0040, PHY_A_10HDX = 0x0020, +- PHY_A_SEL = 0x001e, +-}; +-/* PHY_ANL */ +-enum PHY_ANL_BIT { +- PHY_L_NP = 0x8000, PHY_L_ACK = 0x4000, PHY_L_RF = 0x2000, +- PHY_L_FCS = 0x0400, PHY_L_T4 = 0x0200, PHY_L_FDX = 0x0100, +- PHY_L_HDX = 0x0080, PHY_L_10FDX = 0x0040, PHY_L_10HDX = 0x0020, +- PHY_L_SEL = 0x001f, +-}; +- +-/* PHY_ANE */ +-enum PHY_ANE_BIT { +- PHY_E_PDF = 0x0010, PHY_E_LPNPA = 0x0008, PHY_E_NPA = 0x0004, +- PHY_E_PRX = 0x0002, PHY_E_LPANEGA = 0x0001, +-}; +- +-/* DM9161 */ +-enum PHY_16_BIT { +- PHY_16_BP4B45 = 0x8000, PHY_16_BPSCR = 0x4000, PHY_16_BPALIGN = 0x2000, +- PHY_16_BP_ADPOK = 0x1000, PHY_16_Repeatmode = 0x0800, +- PHY_16_TXselect = 0x0400, +- PHY_16_Rsvd = 0x0200, PHY_16_RMIIEnable = 0x0100, +- PHY_16_Force100LNK = 0x0080, +- PHY_16_APDLED_CTL = 0x0040, PHY_16_COLLED_CTL = 0x0020, +- PHY_16_RPDCTR_EN = 0x0010, +- PHY_16_ResetStMch = 0x0008, PHY_16_PreamSupr = 0x0004, +- PHY_16_Sleepmode = 0x0002, +- PHY_16_RemoteLoopOut = 0x0001, +-}; +- +-#define POST_RX 0x08 +-#define POST_FW 0x04 +-#define POST0_RX (POST_RX) +-#define POST0_FW (POST_FW) +-#define POST1_RX (POST_RX >> 2) +-#define POST1_FW (POST_FW >> 2) +-#define POST_ALL (POST0_RX | POST0_FW | POST1_RX | POST1_FW) +- + /* ARSTR */ + enum ARSTR_BIT { ARSTR_ARSTR = 0x00000001, }; + +@@ -786,10 +721,6 @@ struct sh_eth_private { + int msg_enable; + int speed; + int duplex; +- u32 rx_int_var, tx_int_var; /* interrupt control variables */ +- char post_rx; /* POST receive */ +- char post_fw; /* POST forward */ +- struct net_device_stats tsu_stats; /* TSU forward status */ + int port; /* for TSU */ + int vlan_num_ids; /* for VLAN tag filter */ + +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0016-net-sh_eth-fix-up-the-buffer-pointers.patch b/patches.armadillo800/0016-net-sh_eth-fix-up-the-buffer-pointers.patch new file mode 100644 index 0000000000000..5e09276e07266 --- /dev/null +++ b/patches.armadillo800/0016-net-sh_eth-fix-up-the-buffer-pointers.patch @@ -0,0 +1,94 @@ +From ec575069aff289fc8d05d09b897bb05e55e90adf Mon Sep 17 00:00:00 2001 +From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Date: Tue, 26 Jun 2012 20:00:01 +0000 +Subject: net: sh_eth: fix up the buffer pointers + +After freeing the buffer, the driver should change the value of +the pointer to NULL. + +Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +(cherry picked from commit 91c77550000a7d888aaf9f9ac13e3e3485d18560) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/net/ethernet/renesas/sh_eth.c | 31 ++++++++++++++++++++++++------- + 1 file changed, 24 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index 43e76d2..2dd2ff5 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -788,6 +788,7 @@ static void sh_eth_ring_free(struct net_device *ndev) + } + } + kfree(mdp->rx_skbuff); ++ mdp->rx_skbuff = NULL; + + /* Free Tx skb ringbuffer */ + if (mdp->tx_skbuff) { +@@ -797,6 +798,7 @@ static void sh_eth_ring_free(struct net_device *ndev) + } + } + kfree(mdp->tx_skbuff); ++ mdp->tx_skbuff = NULL; + } + + /* format skb and descriptor buffer */ +@@ -933,10 +935,31 @@ desc_ring_free: + skb_ring_free: + /* Free Rx and Tx skb ring buffer */ + sh_eth_ring_free(ndev); ++ mdp->tx_ring = NULL; ++ mdp->rx_ring = NULL; + + return ret; + } + ++static void sh_eth_free_dma_buffer(struct sh_eth_private *mdp) ++{ ++ int ringsize; ++ ++ if (mdp->rx_ring) { ++ ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE; ++ dma_free_coherent(NULL, ringsize, mdp->rx_ring, ++ mdp->rx_desc_dma); ++ mdp->rx_ring = NULL; ++ } ++ ++ if (mdp->tx_ring) { ++ ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE; ++ dma_free_coherent(NULL, ringsize, mdp->tx_ring, ++ mdp->tx_desc_dma); ++ mdp->tx_ring = NULL; ++ } ++} ++ + static int sh_eth_dev_init(struct net_device *ndev) + { + int ret = 0; +@@ -1677,7 +1700,6 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev) + static int sh_eth_close(struct net_device *ndev) + { + struct sh_eth_private *mdp = netdev_priv(ndev); +- int ringsize; + + netif_stop_queue(ndev); + +@@ -1700,12 +1722,7 @@ static int sh_eth_close(struct net_device *ndev) + sh_eth_ring_free(ndev); + + /* free DMA buffer */ +- ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE; +- dma_free_coherent(NULL, ringsize, mdp->rx_ring, mdp->rx_desc_dma); +- +- /* free DMA buffer */ +- ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE; +- dma_free_coherent(NULL, ringsize, mdp->tx_ring, mdp->tx_desc_dma); ++ sh_eth_free_dma_buffer(mdp); + + pm_runtime_put_sync(&mdp->pdev->dev); + +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0017-net-sh_eth-add-support-for-set_ringparam-get_ringpar.patch b/patches.armadillo800/0017-net-sh_eth-add-support-for-set_ringparam-get_ringpar.patch new file mode 100644 index 0000000000000..d1a976c408bd4 --- /dev/null +++ b/patches.armadillo800/0017-net-sh_eth-add-support-for-set_ringparam-get_ringpar.patch @@ -0,0 +1,407 @@ +From 53432c5cc072269a7e3ac40d2731da16434a24b2 Mon Sep 17 00:00:00 2001 +From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Date: Tue, 26 Jun 2012 20:00:03 +0000 +Subject: net: sh_eth: add support for set_ringparam/get_ringparam + +This patch supports the ethtool's set_ringparam() and get_ringparam(). + +Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +(cherry picked from commit 525b8075edda9c2ab4b81e210505bd7487ea6e56) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/net/ethernet/renesas/sh_eth.c | 139 ++++++++++++++++++++++++++-------- + drivers/net/ethernet/renesas/sh_eth.h | 6 ++ + 2 files changed, 112 insertions(+), 33 deletions(-) + +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index 2dd2ff5..af0b867 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -782,7 +782,7 @@ static void sh_eth_ring_free(struct net_device *ndev) + + /* Free Rx skb ringbuffer */ + if (mdp->rx_skbuff) { +- for (i = 0; i < RX_RING_SIZE; i++) { ++ for (i = 0; i < mdp->num_rx_ring; i++) { + if (mdp->rx_skbuff[i]) + dev_kfree_skb(mdp->rx_skbuff[i]); + } +@@ -792,7 +792,7 @@ static void sh_eth_ring_free(struct net_device *ndev) + + /* Free Tx skb ringbuffer */ + if (mdp->tx_skbuff) { +- for (i = 0; i < TX_RING_SIZE; i++) { ++ for (i = 0; i < mdp->num_tx_ring; i++) { + if (mdp->tx_skbuff[i]) + dev_kfree_skb(mdp->tx_skbuff[i]); + } +@@ -809,8 +809,8 @@ static void sh_eth_ring_format(struct net_device *ndev) + struct sk_buff *skb; + struct sh_eth_rxdesc *rxdesc = NULL; + struct sh_eth_txdesc *txdesc = NULL; +- int rx_ringsize = sizeof(*rxdesc) * RX_RING_SIZE; +- int tx_ringsize = sizeof(*txdesc) * TX_RING_SIZE; ++ int rx_ringsize = sizeof(*rxdesc) * mdp->num_rx_ring; ++ int tx_ringsize = sizeof(*txdesc) * mdp->num_tx_ring; + + mdp->cur_rx = mdp->cur_tx = 0; + mdp->dirty_rx = mdp->dirty_tx = 0; +@@ -818,7 +818,7 @@ static void sh_eth_ring_format(struct net_device *ndev) + memset(mdp->rx_ring, 0, rx_ringsize); + + /* build Rx ring buffer */ +- for (i = 0; i < RX_RING_SIZE; i++) { ++ for (i = 0; i < mdp->num_rx_ring; i++) { + /* skb */ + mdp->rx_skbuff[i] = NULL; + skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz); +@@ -844,7 +844,7 @@ static void sh_eth_ring_format(struct net_device *ndev) + } + } + +- mdp->dirty_rx = (u32) (i - RX_RING_SIZE); ++ mdp->dirty_rx = (u32) (i - mdp->num_rx_ring); + + /* Mark the last entry as wrapping the ring. */ + rxdesc->status |= cpu_to_edmac(mdp, RD_RDEL); +@@ -852,7 +852,7 @@ static void sh_eth_ring_format(struct net_device *ndev) + memset(mdp->tx_ring, 0, tx_ringsize); + + /* build Tx ring buffer */ +- for (i = 0; i < TX_RING_SIZE; i++) { ++ for (i = 0; i < mdp->num_tx_ring; i++) { + mdp->tx_skbuff[i] = NULL; + txdesc = &mdp->tx_ring[i]; + txdesc->status = cpu_to_edmac(mdp, TD_TFP); +@@ -886,7 +886,7 @@ static int sh_eth_ring_init(struct net_device *ndev) + mdp->rx_buf_sz += NET_IP_ALIGN; + + /* Allocate RX and TX skb rings */ +- mdp->rx_skbuff = kmalloc(sizeof(*mdp->rx_skbuff) * RX_RING_SIZE, ++ mdp->rx_skbuff = kmalloc(sizeof(*mdp->rx_skbuff) * mdp->num_rx_ring, + GFP_KERNEL); + if (!mdp->rx_skbuff) { + dev_err(&ndev->dev, "Cannot allocate Rx skb\n"); +@@ -894,7 +894,7 @@ static int sh_eth_ring_init(struct net_device *ndev) + return ret; + } + +- mdp->tx_skbuff = kmalloc(sizeof(*mdp->tx_skbuff) * TX_RING_SIZE, ++ mdp->tx_skbuff = kmalloc(sizeof(*mdp->tx_skbuff) * mdp->num_tx_ring, + GFP_KERNEL); + if (!mdp->tx_skbuff) { + dev_err(&ndev->dev, "Cannot allocate Tx skb\n"); +@@ -903,7 +903,7 @@ static int sh_eth_ring_init(struct net_device *ndev) + } + + /* Allocate all Rx descriptors. */ +- rx_ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE; ++ rx_ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring; + mdp->rx_ring = dma_alloc_coherent(NULL, rx_ringsize, &mdp->rx_desc_dma, + GFP_KERNEL); + +@@ -917,7 +917,7 @@ static int sh_eth_ring_init(struct net_device *ndev) + mdp->dirty_rx = 0; + + /* Allocate all Tx descriptors. */ +- tx_ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE; ++ tx_ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring; + mdp->tx_ring = dma_alloc_coherent(NULL, tx_ringsize, &mdp->tx_desc_dma, + GFP_KERNEL); + if (!mdp->tx_ring) { +@@ -946,21 +946,21 @@ static void sh_eth_free_dma_buffer(struct sh_eth_private *mdp) + int ringsize; + + if (mdp->rx_ring) { +- ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE; ++ ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring; + dma_free_coherent(NULL, ringsize, mdp->rx_ring, + mdp->rx_desc_dma); + mdp->rx_ring = NULL; + } + + if (mdp->tx_ring) { +- ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE; ++ ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring; + dma_free_coherent(NULL, ringsize, mdp->tx_ring, + mdp->tx_desc_dma); + mdp->tx_ring = NULL; + } + } + +-static int sh_eth_dev_init(struct net_device *ndev) ++static int sh_eth_dev_init(struct net_device *ndev, bool start) + { + int ret = 0; + struct sh_eth_private *mdp = netdev_priv(ndev); +@@ -1008,7 +1008,8 @@ static int sh_eth_dev_init(struct net_device *ndev) + RFLR); + + sh_eth_write(ndev, sh_eth_read(ndev, EESR), EESR); +- sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR); ++ if (start) ++ sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR); + + /* PAUSE Prohibition */ + val = (sh_eth_read(ndev, ECMR) & ECMR_DM) | +@@ -1023,7 +1024,8 @@ static int sh_eth_dev_init(struct net_device *ndev) + sh_eth_write(ndev, mdp->cd->ecsr_value, ECSR); + + /* E-MAC Interrupt Enable register */ +- sh_eth_write(ndev, mdp->cd->ecsipr_value, ECSIPR); ++ if (start) ++ sh_eth_write(ndev, mdp->cd->ecsipr_value, ECSIPR); + + /* Set MAC address */ + update_mac_address(ndev); +@@ -1036,10 +1038,12 @@ static int sh_eth_dev_init(struct net_device *ndev) + if (mdp->cd->tpauser) + sh_eth_write(ndev, TPAUSER_UNLIMITED, TPAUSER); + +- /* Setting the Rx mode will start the Rx process. */ +- sh_eth_write(ndev, EDRRR_R, EDRRR); ++ if (start) { ++ /* Setting the Rx mode will start the Rx process. */ ++ sh_eth_write(ndev, EDRRR_R, EDRRR); + +- netif_start_queue(ndev); ++ netif_start_queue(ndev); ++ } + + out: + return ret; +@@ -1054,7 +1058,7 @@ static int sh_eth_txfree(struct net_device *ndev) + int entry = 0; + + for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) { +- entry = mdp->dirty_tx % TX_RING_SIZE; ++ entry = mdp->dirty_tx % mdp->num_tx_ring; + txdesc = &mdp->tx_ring[entry]; + if (txdesc->status & cpu_to_edmac(mdp, TD_TACT)) + break; +@@ -1067,7 +1071,7 @@ static int sh_eth_txfree(struct net_device *ndev) + freeNum++; + } + txdesc->status = cpu_to_edmac(mdp, TD_TFP); +- if (entry >= TX_RING_SIZE - 1) ++ if (entry >= mdp->num_tx_ring - 1) + txdesc->status |= cpu_to_edmac(mdp, TD_TDLE); + + ndev->stats.tx_packets++; +@@ -1082,8 +1086,8 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status) + struct sh_eth_private *mdp = netdev_priv(ndev); + struct sh_eth_rxdesc *rxdesc; + +- int entry = mdp->cur_rx % RX_RING_SIZE; +- int boguscnt = (mdp->dirty_rx + RX_RING_SIZE) - mdp->cur_rx; ++ int entry = mdp->cur_rx % mdp->num_rx_ring; ++ int boguscnt = (mdp->dirty_rx + mdp->num_rx_ring) - mdp->cur_rx; + struct sk_buff *skb; + u16 pkt_len = 0; + u32 desc_status; +@@ -1134,13 +1138,13 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status) + ndev->stats.rx_bytes += pkt_len; + } + rxdesc->status |= cpu_to_edmac(mdp, RD_RACT); +- entry = (++mdp->cur_rx) % RX_RING_SIZE; ++ entry = (++mdp->cur_rx) % mdp->num_rx_ring; + rxdesc = &mdp->rx_ring[entry]; + } + + /* Refill the Rx ring buffers. */ + for (; mdp->cur_rx - mdp->dirty_rx > 0; mdp->dirty_rx++) { +- entry = mdp->dirty_rx % RX_RING_SIZE; ++ entry = mdp->dirty_rx % mdp->num_rx_ring; + rxdesc = &mdp->rx_ring[entry]; + /* The size of the buffer is 16 byte boundary. */ + rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16); +@@ -1157,7 +1161,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status) + skb_checksum_none_assert(skb); + rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4)); + } +- if (entry >= RX_RING_SIZE - 1) ++ if (entry >= mdp->num_rx_ring - 1) + rxdesc->status |= + cpu_to_edmac(mdp, RD_RACT | RD_RFP | RD_RDEL); + else +@@ -1557,6 +1561,71 @@ static void sh_eth_get_strings(struct net_device *ndev, u32 stringset, u8 *data) + } + } + ++static void sh_eth_get_ringparam(struct net_device *ndev, ++ struct ethtool_ringparam *ring) ++{ ++ struct sh_eth_private *mdp = netdev_priv(ndev); ++ ++ ring->rx_max_pending = RX_RING_MAX; ++ ring->tx_max_pending = TX_RING_MAX; ++ ring->rx_pending = mdp->num_rx_ring; ++ ring->tx_pending = mdp->num_tx_ring; ++} ++ ++static int sh_eth_set_ringparam(struct net_device *ndev, ++ struct ethtool_ringparam *ring) ++{ ++ struct sh_eth_private *mdp = netdev_priv(ndev); ++ int ret; ++ ++ if (ring->tx_pending > TX_RING_MAX || ++ ring->rx_pending > RX_RING_MAX || ++ ring->tx_pending < TX_RING_MIN || ++ ring->rx_pending < RX_RING_MIN) ++ return -EINVAL; ++ if (ring->rx_mini_pending || ring->rx_jumbo_pending) ++ return -EINVAL; ++ ++ if (netif_running(ndev)) { ++ netif_tx_disable(ndev); ++ /* Disable interrupts by clearing the interrupt mask. */ ++ sh_eth_write(ndev, 0x0000, EESIPR); ++ /* Stop the chip's Tx and Rx processes. */ ++ sh_eth_write(ndev, 0, EDTRR); ++ sh_eth_write(ndev, 0, EDRRR); ++ synchronize_irq(ndev->irq); ++ } ++ ++ /* Free all the skbuffs in the Rx queue. */ ++ sh_eth_ring_free(ndev); ++ /* Free DMA buffer */ ++ sh_eth_free_dma_buffer(mdp); ++ ++ /* Set new parameters */ ++ mdp->num_rx_ring = ring->rx_pending; ++ mdp->num_tx_ring = ring->tx_pending; ++ ++ ret = sh_eth_ring_init(ndev); ++ if (ret < 0) { ++ dev_err(&ndev->dev, "%s: sh_eth_ring_init failed.\n", __func__); ++ return ret; ++ } ++ ret = sh_eth_dev_init(ndev, false); ++ if (ret < 0) { ++ dev_err(&ndev->dev, "%s: sh_eth_dev_init failed.\n", __func__); ++ return ret; ++ } ++ ++ if (netif_running(ndev)) { ++ sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR); ++ /* Setting the Rx mode will start the Rx process. */ ++ sh_eth_write(ndev, EDRRR_R, EDRRR); ++ netif_wake_queue(ndev); ++ } ++ ++ return 0; ++} ++ + static const struct ethtool_ops sh_eth_ethtool_ops = { + .get_settings = sh_eth_get_settings, + .set_settings = sh_eth_set_settings, +@@ -1567,6 +1636,8 @@ static const struct ethtool_ops sh_eth_ethtool_ops = { + .get_strings = sh_eth_get_strings, + .get_ethtool_stats = sh_eth_get_ethtool_stats, + .get_sset_count = sh_eth_get_sset_count, ++ .get_ringparam = sh_eth_get_ringparam, ++ .set_ringparam = sh_eth_set_ringparam, + }; + + /* network device open function */ +@@ -1597,7 +1668,7 @@ static int sh_eth_open(struct net_device *ndev) + goto out_free_irq; + + /* device init */ +- ret = sh_eth_dev_init(ndev); ++ ret = sh_eth_dev_init(ndev, true); + if (ret) + goto out_free_irq; + +@@ -1631,7 +1702,7 @@ static void sh_eth_tx_timeout(struct net_device *ndev) + ndev->stats.tx_errors++; + + /* Free all the skbuffs in the Rx queue. */ +- for (i = 0; i < RX_RING_SIZE; i++) { ++ for (i = 0; i < mdp->num_rx_ring; i++) { + rxdesc = &mdp->rx_ring[i]; + rxdesc->status = 0; + rxdesc->addr = 0xBADF00D0; +@@ -1639,14 +1710,14 @@ static void sh_eth_tx_timeout(struct net_device *ndev) + dev_kfree_skb(mdp->rx_skbuff[i]); + mdp->rx_skbuff[i] = NULL; + } +- for (i = 0; i < TX_RING_SIZE; i++) { ++ for (i = 0; i < mdp->num_tx_ring; i++) { + if (mdp->tx_skbuff[i]) + dev_kfree_skb(mdp->tx_skbuff[i]); + mdp->tx_skbuff[i] = NULL; + } + + /* device init */ +- sh_eth_dev_init(ndev); ++ sh_eth_dev_init(ndev, true); + } + + /* Packet transmit function */ +@@ -1658,7 +1729,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev) + unsigned long flags; + + spin_lock_irqsave(&mdp->lock, flags); +- if ((mdp->cur_tx - mdp->dirty_tx) >= (TX_RING_SIZE - 4)) { ++ if ((mdp->cur_tx - mdp->dirty_tx) >= (mdp->num_tx_ring - 4)) { + if (!sh_eth_txfree(ndev)) { + if (netif_msg_tx_queued(mdp)) + dev_warn(&ndev->dev, "TxFD exhausted.\n"); +@@ -1669,7 +1740,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev) + } + spin_unlock_irqrestore(&mdp->lock, flags); + +- entry = mdp->cur_tx % TX_RING_SIZE; ++ entry = mdp->cur_tx % mdp->num_tx_ring; + mdp->tx_skbuff[entry] = skb; + txdesc = &mdp->tx_ring[entry]; + /* soft swap. */ +@@ -1683,7 +1754,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev) + else + txdesc->buffer_length = skb->len; + +- if (entry >= TX_RING_SIZE - 1) ++ if (entry >= mdp->num_tx_ring - 1) + txdesc->status |= cpu_to_edmac(mdp, TD_TACT | TD_TDLE); + else + txdesc->status |= cpu_to_edmac(mdp, TD_TACT); +@@ -2313,6 +2384,8 @@ static int sh_eth_drv_probe(struct platform_device *pdev) + ether_setup(ndev); + + mdp = netdev_priv(ndev); ++ mdp->num_tx_ring = TX_RING_SIZE; ++ mdp->num_rx_ring = RX_RING_SIZE; + mdp->addr = ioremap(res->start, resource_size(res)); + if (mdp->addr == NULL) { + ret = -ENOMEM; +diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h +index 37a0702..bae84fd 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.h ++++ b/drivers/net/ethernet/renesas/sh_eth.h +@@ -27,6 +27,10 @@ + #define TX_TIMEOUT (5*HZ) + #define TX_RING_SIZE 64 /* Tx ring size */ + #define RX_RING_SIZE 64 /* Rx ring size */ ++#define TX_RING_MIN 64 ++#define RX_RING_MIN 64 ++#define TX_RING_MAX 1024 ++#define RX_RING_MAX 1024 + #define ETHERSMALL 60 + #define PKT_BUF_SZ 1538 + #define SH_ETH_TSU_TIMEOUT_MS 500 +@@ -701,6 +705,8 @@ struct sh_eth_private { + const u16 *reg_offset; + void __iomem *addr; + void __iomem *tsu_addr; ++ u32 num_rx_ring; ++ u32 num_tx_ring; + dma_addr_t rx_desc_dma; + dma_addr_t tx_desc_dma; + struct sh_eth_rxdesc *rx_ring; +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0018-net-sh_eth-Add-eth-support-for-R8A7779-device.patch b/patches.armadillo800/0018-net-sh_eth-Add-eth-support-for-R8A7779-device.patch new file mode 100644 index 0000000000000..91821e19678b7 --- /dev/null +++ b/patches.armadillo800/0018-net-sh_eth-Add-eth-support-for-R8A7779-device.patch @@ -0,0 +1,71 @@ +From 404932d6f9282b0b5acf10d854fd65611f884521 Mon Sep 17 00:00:00 2001 +From: Phil Edworthy <PHIL.EDWORTHY@renesas.com> +Date: Tue, 14 Aug 2012 20:33:29 +0000 +Subject: net: sh_eth: Add eth support for R8A7779 device + +Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +(cherry picked from commit d0418bb7123f44b23d69ac349eec7daf9103472f) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/net/ethernet/renesas/Kconfig | 4 ++-- + drivers/net/ethernet/renesas/sh_eth.c | 11 ++++++++--- + 2 files changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig +index 46df3a0..24c2305 100644 +--- a/drivers/net/ethernet/renesas/Kconfig ++++ b/drivers/net/ethernet/renesas/Kconfig +@@ -8,7 +8,7 @@ config SH_ETH + (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \ + CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \ + CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7734 || \ +- CPU_SUBTYPE_SH7757 || ARCH_R8A7740) ++ CPU_SUBTYPE_SH7757 || ARCH_R8A7740 || ARCH_R8A7779) + select CRC32 + select NET_CORE + select MII +@@ -18,4 +18,4 @@ config SH_ETH + Renesas SuperH Ethernet device driver. + This driver supporting CPUs are: + - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763, SH7757, +- and R8A7740. ++ R8A7740 and R8A7779. +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index af0b867..bad8f2e 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -78,7 +78,7 @@ static void sh_eth_select_mii(struct net_device *ndev) + #endif + + /* There is CPU dependent code */ +-#if defined(CONFIG_CPU_SUBTYPE_SH7724) ++#if defined(CONFIG_CPU_SUBTYPE_SH7724) || defined(CONFIG_ARCH_R8A7779) + #define SH_ETH_RESET_DEFAULT 1 + static void sh_eth_set_duplex(struct net_device *ndev) + { +@@ -93,13 +93,18 @@ static void sh_eth_set_duplex(struct net_device *ndev) + static void sh_eth_set_rate(struct net_device *ndev) + { + struct sh_eth_private *mdp = netdev_priv(ndev); ++ unsigned int bits = ECMR_RTM; ++ ++#if defined(CONFIG_ARCH_R8A7779) ++ bits |= ECMR_ELB; ++#endif + + switch (mdp->speed) { + case 10: /* 10BASE */ +- sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_RTM, ECMR); ++ sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~bits, ECMR); + break; + case 100:/* 100BASE */ +- sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_RTM, ECMR); ++ sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | bits, ECMR); + break; + default: + break; +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0019-ASoC-add-generic-simple-card-support.patch b/patches.armadillo800/0019-ASoC-add-generic-simple-card-support.patch new file mode 100644 index 0000000000000..23ec1ddda3048 --- /dev/null +++ b/patches.armadillo800/0019-ASoC-add-generic-simple-card-support.patch @@ -0,0 +1,239 @@ +From e824e077a91eecb30f3a4124516811ffc382b5a8 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 8 Apr 2012 21:17:50 -0700 +Subject: ASoC: add generic simple-card support + +Current ASoC requires card.c file to each platforms in order to +specifies its CPU and Codecs pair. +But the differences between these were only value/strings of setting. +In order to reduce duplicate driver, this patch adds generic/simple-card. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit f2390880ec0264a0ed26b32c23bc23435b4297da) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/sound/simple_card.h | 38 ++++++++++++++ + sound/soc/Kconfig | 3 ++ + sound/soc/Makefile | 1 + + sound/soc/generic/Kconfig | 4 ++ + sound/soc/generic/Makefile | 3 ++ + sound/soc/generic/simple-card.c | 114 ++++++++++++++++++++++++++++++++++++++++ + 6 files changed, 163 insertions(+) + create mode 100644 include/sound/simple_card.h + create mode 100644 sound/soc/generic/Kconfig + create mode 100644 sound/soc/generic/Makefile + create mode 100644 sound/soc/generic/simple-card.c + +diff --git a/include/sound/simple_card.h b/include/sound/simple_card.h +new file mode 100644 +index 0000000..4b62b8d +--- /dev/null ++++ b/include/sound/simple_card.h +@@ -0,0 +1,38 @@ ++/* ++ * ASoC simple sound card support ++ * ++ * Copyright (C) 2012 Renesas Solutions Corp. ++ * 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 version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef __SIMPLE_CARD_H ++#define __SIMPLE_CARD_H ++ ++#include <sound/soc.h> ++ ++struct asoc_simple_dai_init_info { ++ unsigned int fmt; ++ unsigned int cpu_daifmt; ++ unsigned int codec_daifmt; ++ unsigned int sysclk; ++}; ++ ++struct asoc_simple_card_info { ++ const char *name; ++ const char *card; ++ const char *cpu_dai; ++ const char *codec; ++ const char *platform; ++ const char *codec_dai; ++ struct asoc_simple_dai_init_info *init; /* for snd_link.init */ ++ ++ /* used in simple-card.c */ ++ struct snd_soc_dai_link snd_link; ++ struct snd_soc_card snd_card; ++}; ++ ++#endif /* __SIMPLE_CARD_H */ +diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig +index 91c9855..38be639 100644 +--- a/sound/soc/Kconfig ++++ b/sound/soc/Kconfig +@@ -52,5 +52,8 @@ source "sound/soc/txx9/Kconfig" + # Supported codecs + source "sound/soc/codecs/Kconfig" + ++# generic frame-work ++source "sound/soc/generic/Kconfig" ++ + endif # SND_SOC + +diff --git a/sound/soc/Makefile b/sound/soc/Makefile +index 2feaf37..b55db9c 100644 +--- a/sound/soc/Makefile ++++ b/sound/soc/Makefile +@@ -6,6 +6,7 @@ obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o + + obj-$(CONFIG_SND_SOC) += snd-soc-core.o + obj-$(CONFIG_SND_SOC) += codecs/ ++obj-$(CONFIG_SND_SOC) += generic/ + obj-$(CONFIG_SND_SOC) += atmel/ + obj-$(CONFIG_SND_SOC) += au1x/ + obj-$(CONFIG_SND_SOC) += blackfin/ +diff --git a/sound/soc/generic/Kconfig b/sound/soc/generic/Kconfig +new file mode 100644 +index 0000000..610f612 +--- /dev/null ++++ b/sound/soc/generic/Kconfig +@@ -0,0 +1,4 @@ ++config SND_SIMPLE_CARD ++ tristate "ASoC Simple sound card support" ++ help ++ This option enables generic simple sound card support +diff --git a/sound/soc/generic/Makefile b/sound/soc/generic/Makefile +new file mode 100644 +index 0000000..9c3b246 +--- /dev/null ++++ b/sound/soc/generic/Makefile +@@ -0,0 +1,3 @@ ++snd-soc-simple-card-objs := simple-card.o ++ ++obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o +diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c +new file mode 100644 +index 0000000..b4b4cab +--- /dev/null ++++ b/sound/soc/generic/simple-card.c +@@ -0,0 +1,114 @@ ++/* ++ * ASoC simple sound card support ++ * ++ * Copyright (C) 2012 Renesas Solutions Corp. ++ * 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 version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/platform_device.h> ++#include <linux/module.h> ++#include <sound/simple_card.h> ++ ++#define asoc_simple_get_card_info(p) \ ++ container_of(p->dai_link, struct asoc_simple_card_info, snd_link) ++ ++static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct asoc_simple_card_info *cinfo = asoc_simple_get_card_info(rtd); ++ struct asoc_simple_dai_init_info *iinfo = cinfo->init; ++ struct snd_soc_dai *codec = rtd->codec_dai; ++ struct snd_soc_dai *cpu = rtd->cpu_dai; ++ unsigned int cpu_daifmt = iinfo->fmt | iinfo->cpu_daifmt; ++ unsigned int codec_daifmt = iinfo->fmt | iinfo->codec_daifmt; ++ int ret; ++ ++ if (codec_daifmt) { ++ ret = snd_soc_dai_set_fmt(codec, codec_daifmt); ++ if (ret < 0) ++ return ret; ++ } ++ ++ if (iinfo->sysclk) { ++ ret = snd_soc_dai_set_sysclk(codec, 0, iinfo->sysclk, 0); ++ if (ret < 0) ++ return ret; ++ } ++ ++ if (cpu_daifmt) { ++ ret = snd_soc_dai_set_fmt(cpu, cpu_daifmt); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int asoc_simple_card_probe(struct platform_device *pdev) ++{ ++ struct asoc_simple_card_info *cinfo = pdev->dev.platform_data; ++ ++ if (!cinfo) { ++ dev_err(&pdev->dev, "no info for asoc-simple-card\n"); ++ return -EINVAL; ++ } ++ ++ if (!cinfo->name || ++ !cinfo->card || ++ !cinfo->cpu_dai || ++ !cinfo->codec || ++ !cinfo->platform || ++ !cinfo->codec_dai) { ++ dev_err(&pdev->dev, "insufficient asoc_simple_card_info settings\n"); ++ return -EINVAL; ++ } ++ ++ /* ++ * init snd_soc_dai_link ++ */ ++ cinfo->snd_link.name = cinfo->name; ++ cinfo->snd_link.stream_name = cinfo->name; ++ cinfo->snd_link.cpu_dai_name = cinfo->cpu_dai; ++ cinfo->snd_link.platform_name = cinfo->platform; ++ cinfo->snd_link.codec_name = cinfo->codec; ++ cinfo->snd_link.codec_dai_name = cinfo->codec_dai; ++ ++ /* enable snd_link.init if cinfo has settings */ ++ if (cinfo->init) ++ cinfo->snd_link.init = asoc_simple_card_dai_init; ++ ++ /* ++ * init snd_soc_card ++ */ ++ cinfo->snd_card.name = cinfo->card; ++ cinfo->snd_card.owner = THIS_MODULE; ++ cinfo->snd_card.dai_link = &cinfo->snd_link; ++ cinfo->snd_card.num_links = 1; ++ cinfo->snd_card.dev = &pdev->dev; ++ ++ return snd_soc_register_card(&cinfo->snd_card); ++} ++ ++static int asoc_simple_card_remove(struct platform_device *pdev) ++{ ++ struct asoc_simple_card_info *cinfo = pdev->dev.platform_data; ++ ++ return snd_soc_unregister_card(&cinfo->snd_card); ++} ++ ++static struct platform_driver asoc_simple_card = { ++ .driver = { ++ .name = "asoc-simple-card", ++ }, ++ .probe = asoc_simple_card_probe, ++ .remove = asoc_simple_card_remove, ++}; ++ ++module_platform_driver(asoc_simple_card); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("ASoC Simple Sound Card"); ++MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0020-ASoC-sh-fsi-use-simple-card-instead-of-fsi-ak4642.patch b/patches.armadillo800/0020-ASoC-sh-fsi-use-simple-card-instead-of-fsi-ak4642.patch new file mode 100644 index 0000000000000..a6129227a8f34 --- /dev/null +++ b/patches.armadillo800/0020-ASoC-sh-fsi-use-simple-card-instead-of-fsi-ak4642.patch @@ -0,0 +1,358 @@ +From 69dbe4e265126dd9dcd679d7f707c73fa86b88ef Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 8 Apr 2012 21:18:28 -0700 +Subject: ASoC: sh: fsi: use simple-card instead of fsi-ak4642 + +This patch uses simple-card driver instead of fsi-ak4642 on each board. +To select AK4642 driver, each boards select it on Kconfig. + +This patch removes fsi-ak4642 driver which is no longer needed + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit af8a2fe12fae1b59178dc96e396e5665bcbea7da) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/Kconfig | 2 + + arch/arm/mach-shmobile/board-ap4evb.c | 15 ++++- + arch/arm/mach-shmobile/board-mackerel.c | 15 ++++- + arch/sh/boards/Kconfig | 1 + + arch/sh/boards/mach-se/7724/setup.c | 15 ++++- + include/sound/sh_fsi.h | 12 ---- + sound/soc/sh/Kconfig | 8 --- + sound/soc/sh/Makefile | 2 - + sound/soc/sh/fsi-ak4642.c | 108 -------------------------------- + 9 files changed, 39 insertions(+), 139 deletions(-) + delete mode 100644 sound/soc/sh/fsi-ak4642.c + +diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig +index 34560ca..2cda0c2 100644 +--- a/arch/arm/mach-shmobile/Kconfig ++++ b/arch/arm/mach-shmobile/Kconfig +@@ -58,6 +58,7 @@ config MACH_AP4EVB + depends on ARCH_SH7372 + select ARCH_REQUIRE_GPIOLIB + select SH_LCD_MIPI_DSI ++ select SND_SOC_AK4642 if SND_SIMPLE_CARD + + choice + prompt "AP4EVB LCD panel selection" +@@ -82,6 +83,7 @@ config MACH_MACKEREL + bool "mackerel board" + depends on ARCH_SH7372 + select ARCH_REQUIRE_GPIOLIB ++ select SND_SOC_AK4642 if SND_SIMPLE_CARD + + config MACH_KOTA2 + bool "KOTA2 board" +diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c +index b56dde2..b397512 100644 +--- a/arch/arm/mach-shmobile/board-ap4evb.c ++++ b/arch/arm/mach-shmobile/board-ap4evb.c +@@ -50,6 +50,7 @@ + #include <media/soc_camera.h> + + #include <sound/sh_fsi.h> ++#include <sound/simple_card.h> + + #include <video/sh_mobile_hdmi.h> + #include <video/sh_mobile_lcdc.h> +@@ -785,17 +786,25 @@ static struct platform_device fsi_device = { + }, + }; + +-static struct fsi_ak4642_info fsi2_ak4643_info = { ++static struct asoc_simple_dai_init_info fsi2_ak4643_init_info = { ++ .fmt = SND_SOC_DAIFMT_LEFT_J, ++ .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM, ++ .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS, ++ .sysclk = 11289600, ++}; ++ ++static struct asoc_simple_card_info fsi2_ak4643_info = { + .name = "AK4643", + .card = "FSI2A-AK4643", + .cpu_dai = "fsia-dai", + .codec = "ak4642-codec.0-0013", + .platform = "sh_fsi2", +- .id = FSI_PORT_A, ++ .codec_dai = "ak4642-hifi", ++ .init = &fsi2_ak4643_init_info, + }; + + static struct platform_device fsi_ak4643_device = { +- .name = "fsi-ak4642-audio", ++ .name = "asoc-simple-card", + .dev = { + .platform_data = &fsi2_ak4643_info, + }, +diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c +index 8c6202b..b63de55 100644 +--- a/arch/arm/mach-shmobile/board-mackerel.c ++++ b/arch/arm/mach-shmobile/board-mackerel.c +@@ -53,6 +53,7 @@ + #include <media/soc_camera.h> + #include <media/soc_camera_platform.h> + #include <sound/sh_fsi.h> ++#include <sound/simple_card.h> + + #include <mach/common.h> + #include <mach/irqs.h> +@@ -941,17 +942,25 @@ static struct platform_device fsi_device = { + }, + }; + +-static struct fsi_ak4642_info fsi2_ak4643_info = { ++static struct asoc_simple_dai_init_info fsi2_ak4643_init_info = { ++ .fmt = SND_SOC_DAIFMT_LEFT_J, ++ .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM, ++ .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS, ++ .sysclk = 11289600, ++}; ++ ++static struct asoc_simple_card_info fsi2_ak4643_info = { + .name = "AK4643", + .card = "FSI2A-AK4643", + .cpu_dai = "fsia-dai", + .codec = "ak4642-codec.0-0013", + .platform = "sh_fsi2", +- .id = FSI_PORT_A, ++ .codec_dai = "ak4642-hifi", ++ .init = &fsi2_ak4643_init_info, + }; + + static struct platform_device fsi_ak4643_device = { +- .name = "fsi-ak4642-audio", ++ .name = "asoc-simple-card", + .dev = { + .platform_data = &fsi2_ak4643_info, + }, +diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig +index d893411..0da49f3 100644 +--- a/arch/sh/boards/Kconfig ++++ b/arch/sh/boards/Kconfig +@@ -54,6 +54,7 @@ config SH_7724_SOLUTION_ENGINE + select SOLUTION_ENGINE + depends on CPU_SUBTYPE_SH7724 + select ARCH_REQUIRE_GPIOLIB ++ select SND_SOC_AK4642 if SND_SIMPLE_CARD + help + Select 7724 SolutionEngine if configuring for a Hitachi SH7724 + evaluation board. +diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c +index c540b16..5cc5ed4 100644 +--- a/arch/sh/boards/mach-se/7724/setup.c ++++ b/arch/sh/boards/mach-se/7724/setup.c +@@ -28,6 +28,7 @@ + #include <video/sh_mobile_lcdc.h> + #include <media/sh_mobile_ceu.h> + #include <sound/sh_fsi.h> ++#include <sound/simple_card.h> + #include <asm/io.h> + #include <asm/heartbeat.h> + #include <asm/clock.h> +@@ -304,17 +305,25 @@ static struct platform_device fsi_device = { + }, + }; + +-static struct fsi_ak4642_info fsi_ak4642_info = { ++static struct asoc_simple_dai_init_info fsi2_ak4642_init_info = { ++ .fmt = SND_SOC_DAIFMT_LEFT_J, ++ .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM, ++ .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS, ++ .sysclk = 11289600, ++}; ++ ++static struct asoc_simple_card_info fsi_ak4642_info = { + .name = "AK4642", + .card = "FSIA-AK4642", + .cpu_dai = "fsia-dai", + .codec = "ak4642-codec.0-0012", + .platform = "sh_fsi.0", +- .id = FSI_PORT_A, ++ .codec_dai = "ak4642-hifi", ++ .init = &fsi2_ak4642_init_info, + }; + + static struct platform_device fsi_ak4642_device = { +- .name = "fsi-ak4642-audio", ++ .name = "asoc-simple-card", + .dev = { + .platform_data = &fsi_ak4642_info, + }, +diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h +index b457e87..956e30e 100644 +--- a/include/sound/sh_fsi.h ++++ b/include/sound/sh_fsi.h +@@ -84,16 +84,4 @@ struct sh_fsi_platform_info { + struct sh_fsi_port_info port_b; + }; + +-/* +- * for fsi-ak4642 +- */ +-struct fsi_ak4642_info { +- const char *name; +- const char *card; +- const char *cpu_dai; +- const char *codec; +- const char *platform; +- int id; +-}; +- + #endif /* __SOUND_FSI_H */ +diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig +index d8e06a6..c68b90b 100644 +--- a/sound/soc/sh/Kconfig ++++ b/sound/soc/sh/Kconfig +@@ -46,14 +46,6 @@ config SND_SH7760_AC97 + This option enables generic sound support for the first + AC97 unit of the SH7760. + +-config SND_FSI_AK4642 +- tristate "FSI-AK4642 sound support" +- depends on SND_SOC_SH4_FSI && I2C +- select SND_SOC_AK4642 +- help +- This option enables generic sound support for the +- FSI - AK4642 unit +- + config SND_FSI_DA7210 + tristate "FSI-DA7210 sound support" + depends on SND_SOC_SH4_FSI && I2C +diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile +index 94476d4..01808cd 100644 +--- a/sound/soc/sh/Makefile ++++ b/sound/soc/sh/Makefile +@@ -14,13 +14,11 @@ obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o + + ## boards + snd-soc-sh7760-ac97-objs := sh7760-ac97.o +-snd-soc-fsi-ak4642-objs := fsi-ak4642.o + snd-soc-fsi-da7210-objs := fsi-da7210.o + snd-soc-fsi-hdmi-objs := fsi-hdmi.o + snd-soc-migor-objs := migor.o + + obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o +-obj-$(CONFIG_SND_FSI_AK4642) += snd-soc-fsi-ak4642.o + obj-$(CONFIG_SND_FSI_DA7210) += snd-soc-fsi-da7210.o + obj-$(CONFIG_SND_FSI_HDMI) += snd-soc-fsi-hdmi.o + obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o +diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c +deleted file mode 100644 +index 97f540a..0000000 +--- a/sound/soc/sh/fsi-ak4642.c ++++ /dev/null +@@ -1,108 +0,0 @@ +-/* +- * FSI-AK464x sound support for ms7724se +- * +- * Copyright (C) 2009 Renesas Solutions Corp. +- * Kuninori Morimoto <morimoto.kuninori@renesas.com> +- * +- * 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/platform_device.h> +-#include <linux/module.h> +-#include <sound/sh_fsi.h> +- +-struct fsi_ak4642_data { +- const char *name; +- const char *card; +- const char *cpu_dai; +- const char *codec; +- const char *platform; +- int id; +-}; +- +-static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd) +-{ +- struct snd_soc_dai *codec = rtd->codec_dai; +- struct snd_soc_dai *cpu = rtd->cpu_dai; +- int ret; +- +- ret = snd_soc_dai_set_fmt(codec, SND_SOC_DAIFMT_LEFT_J | +- SND_SOC_DAIFMT_CBM_CFM); +- if (ret < 0) +- return ret; +- +- ret = snd_soc_dai_set_sysclk(codec, 0, 11289600, 0); +- if (ret < 0) +- return ret; +- +- ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_LEFT_J | +- SND_SOC_DAIFMT_CBS_CFS); +- +- return ret; +-} +- +-static struct snd_soc_dai_link fsi_dai_link = { +- .codec_dai_name = "ak4642-hifi", +- .init = fsi_ak4642_dai_init, +-}; +- +-static struct snd_soc_card fsi_soc_card = { +- .owner = THIS_MODULE, +- .dai_link = &fsi_dai_link, +- .num_links = 1, +-}; +- +-static struct platform_device *fsi_snd_device; +- +-static int fsi_ak4642_probe(struct platform_device *pdev) +-{ +- int ret = -ENOMEM; +- struct fsi_ak4642_info *pinfo = pdev->dev.platform_data; +- +- if (!pinfo) { +- dev_err(&pdev->dev, "no info for fsi ak4642\n"); +- goto out; +- } +- +- fsi_snd_device = platform_device_alloc("soc-audio", pinfo->id); +- if (!fsi_snd_device) +- goto out; +- +- fsi_dai_link.name = pinfo->name; +- fsi_dai_link.stream_name = pinfo->name; +- fsi_dai_link.cpu_dai_name = pinfo->cpu_dai; +- fsi_dai_link.platform_name = pinfo->platform; +- fsi_dai_link.codec_name = pinfo->codec; +- fsi_soc_card.name = pinfo->card; +- +- platform_set_drvdata(fsi_snd_device, &fsi_soc_card); +- ret = platform_device_add(fsi_snd_device); +- +- if (ret) +- platform_device_put(fsi_snd_device); +- +-out: +- return ret; +-} +- +-static int fsi_ak4642_remove(struct platform_device *pdev) +-{ +- platform_device_unregister(fsi_snd_device); +- return 0; +-} +- +-static struct platform_driver fsi_ak4642 = { +- .driver = { +- .name = "fsi-ak4642-audio", +- }, +- .probe = fsi_ak4642_probe, +- .remove = fsi_ak4642_remove, +-}; +- +-module_platform_driver(fsi_ak4642); +- +-MODULE_LICENSE("GPL"); +-MODULE_DESCRIPTION("Generic SH4 FSI-AK4642 sound card"); +-MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>"); +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0021-ASoC-sh-fsi-use-simple-card-instead-of-fsi-hdmi.patch b/patches.armadillo800/0021-ASoC-sh-fsi-use-simple-card-instead-of-fsi-hdmi.patch new file mode 100644 index 0000000000000..704a5a6ce8e5b --- /dev/null +++ b/patches.armadillo800/0021-ASoC-sh-fsi-use-simple-card-instead-of-fsi-hdmi.patch @@ -0,0 +1,246 @@ +From bd1e0d9b157b61d6a283ab31f175f6bab4277cfe Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 8 Apr 2012 21:18:58 -0700 +Subject: ASoC: sh: fsi: use simple-card instead of fsi-hdmi + +This patch uses simple-card driver instead of fsi-hdmi on each board. +This patch removes fsi-hdmi driver which is no longer needed + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit fa063b48046c1f30cb06898559bb34935ade74e1) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-ap4evb.c | 20 +++++- + arch/arm/mach-shmobile/board-mackerel.c | 20 +++++- + sound/soc/sh/Kconfig | 7 -- + sound/soc/sh/Makefile | 2 - + sound/soc/sh/fsi-hdmi.c | 118 -------------------------------- + 5 files changed, 38 insertions(+), 129 deletions(-) + delete mode 100644 sound/soc/sh/fsi-hdmi.c + +diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c +index b397512..8302265 100644 +--- a/arch/arm/mach-shmobile/board-ap4evb.c ++++ b/arch/arm/mach-shmobile/board-ap4evb.c +@@ -909,8 +909,26 @@ static struct platform_device lcdc1_device = { + }, + }; + ++static struct asoc_simple_dai_init_info fsi2_hdmi_init_info = { ++ .cpu_daifmt = SND_SOC_DAIFMT_CBM_CFM, ++}; ++ ++static struct asoc_simple_card_info fsi2_hdmi_info = { ++ .name = "HDMI", ++ .card = "FSI2B-HDMI", ++ .cpu_dai = "fsib-dai", ++ .codec = "sh-mobile-hdmi", ++ .platform = "sh_fsi2", ++ .codec_dai = "sh_mobile_hdmi-hifi", ++ .init = &fsi2_hdmi_init_info, ++}; ++ + static struct platform_device fsi_hdmi_device = { +- .name = "sh_fsi2_b_hdmi", ++ .name = "asoc-simple-card", ++ .id = 1, ++ .dev = { ++ .platform_data = &fsi2_hdmi_info, ++ }, + }; + + static struct gpio_led ap4evb_leds[] = { +diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c +index b63de55..fb27bac 100644 +--- a/arch/arm/mach-shmobile/board-mackerel.c ++++ b/arch/arm/mach-shmobile/board-mackerel.c +@@ -503,8 +503,26 @@ static struct platform_device hdmi_lcdc_device = { + }, + }; + ++static struct asoc_simple_dai_init_info fsi2_hdmi_init_info = { ++ .cpu_daifmt = SND_SOC_DAIFMT_CBM_CFM, ++}; ++ ++static struct asoc_simple_card_info fsi2_hdmi_info = { ++ .name = "HDMI", ++ .card = "FSI2B-HDMI", ++ .cpu_dai = "fsib-dai", ++ .codec = "sh-mobile-hdmi", ++ .platform = "sh_fsi2", ++ .codec_dai = "sh_mobile_hdmi-hifi", ++ .init = &fsi2_hdmi_init_info, ++}; ++ + static struct platform_device fsi_hdmi_device = { +- .name = "sh_fsi2_b_hdmi", ++ .name = "asoc-simple-card", ++ .id = 1, ++ .dev = { ++ .platform_data = &fsi2_hdmi_info, ++ }, + }; + + static void __init hdmi_init_pm_clock(void) +diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig +index c68b90b..9ef49c8 100644 +--- a/sound/soc/sh/Kconfig ++++ b/sound/soc/sh/Kconfig +@@ -54,13 +54,6 @@ config SND_FSI_DA7210 + This option enables generic sound support for the + FSI - DA7210 unit + +-config SND_FSI_HDMI +- tristate "FSI-HDMI sound support" +- depends on SND_SOC_SH4_FSI && FB_SH_MOBILE_HDMI +- help +- This option enables generic sound support for the +- FSI - HDMI unit +- + config SND_SIU_MIGOR + tristate "SIU sound support on Migo-R" + depends on SH_MIGOR +diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile +index 01808cd..f37fc3a 100644 +--- a/sound/soc/sh/Makefile ++++ b/sound/soc/sh/Makefile +@@ -15,10 +15,8 @@ obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o + ## boards + snd-soc-sh7760-ac97-objs := sh7760-ac97.o + snd-soc-fsi-da7210-objs := fsi-da7210.o +-snd-soc-fsi-hdmi-objs := fsi-hdmi.o + snd-soc-migor-objs := migor.o + + obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o + obj-$(CONFIG_SND_FSI_DA7210) += snd-soc-fsi-da7210.o +-obj-$(CONFIG_SND_FSI_HDMI) += snd-soc-fsi-hdmi.o + obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o +diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c +deleted file mode 100644 +index 6e41908..0000000 +--- a/sound/soc/sh/fsi-hdmi.c ++++ /dev/null +@@ -1,118 +0,0 @@ +-/* +- * FSI - HDMI sound support +- * +- * Copyright (C) 2010 Renesas Solutions Corp. +- * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +- * +- * 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/platform_device.h> +-#include <linux/module.h> +-#include <sound/sh_fsi.h> +- +-struct fsi_hdmi_data { +- const char *cpu_dai; +- const char *card; +- int id; +-}; +- +-static int fsi_hdmi_dai_init(struct snd_soc_pcm_runtime *rtd) +-{ +- struct snd_soc_dai *cpu = rtd->cpu_dai; +- int ret; +- +- ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_CBM_CFM); +- +- return ret; +-} +- +-static struct snd_soc_dai_link fsi_dai_link = { +- .name = "HDMI", +- .stream_name = "HDMI", +- .codec_dai_name = "sh_mobile_hdmi-hifi", +- .platform_name = "sh_fsi2", +- .codec_name = "sh-mobile-hdmi", +- .init = fsi_hdmi_dai_init, +-}; +- +-static struct snd_soc_card fsi_soc_card = { +- .owner = THIS_MODULE, +- .dai_link = &fsi_dai_link, +- .num_links = 1, +-}; +- +-static struct platform_device *fsi_snd_device; +- +-static int fsi_hdmi_probe(struct platform_device *pdev) +-{ +- int ret = -ENOMEM; +- const struct platform_device_id *id_entry; +- struct fsi_hdmi_data *pdata; +- +- id_entry = pdev->id_entry; +- if (!id_entry) { +- dev_err(&pdev->dev, "unknown fsi hdmi\n"); +- return -ENODEV; +- } +- +- pdata = (struct fsi_hdmi_data *)id_entry->driver_data; +- +- fsi_snd_device = platform_device_alloc("soc-audio", pdata->id); +- if (!fsi_snd_device) +- goto out; +- +- fsi_dai_link.cpu_dai_name = pdata->cpu_dai; +- fsi_soc_card.name = pdata->card; +- +- platform_set_drvdata(fsi_snd_device, &fsi_soc_card); +- ret = platform_device_add(fsi_snd_device); +- +- if (ret) +- platform_device_put(fsi_snd_device); +- +-out: +- return ret; +-} +- +-static int fsi_hdmi_remove(struct platform_device *pdev) +-{ +- platform_device_unregister(fsi_snd_device); +- return 0; +-} +- +-static struct fsi_hdmi_data fsi2_a_hdmi = { +- .cpu_dai = "fsia-dai", +- .card = "FSI2A-HDMI", +- .id = FSI_PORT_A, +-}; +- +-static struct fsi_hdmi_data fsi2_b_hdmi = { +- .cpu_dai = "fsib-dai", +- .card = "FSI2B-HDMI", +- .id = FSI_PORT_B, +-}; +- +-static struct platform_device_id fsi_id_table[] = { +- /* FSI 2 */ +- { "sh_fsi2_a_hdmi", (kernel_ulong_t)&fsi2_a_hdmi }, +- { "sh_fsi2_b_hdmi", (kernel_ulong_t)&fsi2_b_hdmi }, +- {}, +-}; +- +-static struct platform_driver fsi_hdmi = { +- .driver = { +- .name = "fsi-hdmi-audio", +- }, +- .probe = fsi_hdmi_probe, +- .remove = fsi_hdmi_remove, +- .id_table = fsi_id_table, +-}; +- +-module_platform_driver(fsi_hdmi); +- +-MODULE_LICENSE("GPL"); +-MODULE_DESCRIPTION("Generic SH4 FSI-HDMI sound card"); +-MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0022-ASoC-sh-fsi-use-simple-card-instead-of-fsi-da7210.patch b/patches.armadillo800/0022-ASoC-sh-fsi-use-simple-card-instead-of-fsi-da7210.patch new file mode 100644 index 0000000000000..037ab31121ecf --- /dev/null +++ b/patches.armadillo800/0022-ASoC-sh-fsi-use-simple-card-instead-of-fsi-da7210.patch @@ -0,0 +1,210 @@ +From 0baa4d444616c8bd593aaf36ca25639d66da129a Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 8 Apr 2012 21:19:25 -0700 +Subject: ASoC: sh: fsi: use simple-card instead of fsi-da7210 + +This patch uses simple-card driver instead of fsi-da7210 on each board. +To select DA7210 driver, each boards select it on Kconfig. + +This patch removes fsi-da7210 driver which is no longer needed + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 064bfada66779d95686cacdcbb17551e2c0bf66b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/sh/boards/Kconfig | 1 + + arch/sh/boards/mach-ecovec24/setup.c | 26 ++++++++++++ + sound/soc/sh/Kconfig | 8 ---- + sound/soc/sh/Makefile | 2 - + sound/soc/sh/fsi-da7210.c | 81 ------------------------------------ + 5 files changed, 27 insertions(+), 91 deletions(-) + delete mode 100644 sound/soc/sh/fsi-da7210.c + +diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig +index 0da49f3..c0241bd 100644 +--- a/arch/sh/boards/Kconfig ++++ b/arch/sh/boards/Kconfig +@@ -224,6 +224,7 @@ config SH_ECOVEC + bool "EcoVec" + depends on CPU_SUBTYPE_SH7724 + select ARCH_REQUIRE_GPIOLIB ++ select SND_SOC_DA7210 if SND_SIMPLE_CARD + help + Renesas "R0P7724LC0011/21RL (EcoVec)" support. + +diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c +index d12fe9d..299a40a 100644 +--- a/arch/sh/boards/mach-ecovec24/setup.c ++++ b/arch/sh/boards/mach-ecovec24/setup.c +@@ -32,6 +32,7 @@ + #include <linux/videodev2.h> + #include <video/sh_mobile_lcdc.h> + #include <sound/sh_fsi.h> ++#include <sound/simple_card.h> + #include <media/sh_mobile_ceu.h> + #include <media/soc_camera.h> + #include <media/tw9910.h> +@@ -809,6 +810,30 @@ static struct platform_device fsi_device = { + }, + }; + ++static struct asoc_simple_dai_init_info fsi_da7210_init_info = { ++ .fmt = SND_SOC_DAIFMT_I2S, ++ .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM, ++ .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS, ++}; ++ ++static struct asoc_simple_card_info fsi_da7210_info = { ++ .name = "DA7210", ++ .card = "FSIB-DA7210", ++ .cpu_dai = "fsib-dai", ++ .codec = "da7210.0-001a", ++ .platform = "sh_fsi.0", ++ .codec_dai = "da7210-hifi", ++ .init = &fsi_da7210_init_info, ++}; ++ ++static struct platform_device fsi_da7210_device = { ++ .name = "asoc-simple-card", ++ .dev = { ++ .platform_data = &fsi_da7210_info, ++ }, ++}; ++ ++ + /* IrDA */ + static struct resource irda_resources[] = { + [0] = { +@@ -945,6 +970,7 @@ static struct platform_device *ecovec_devices[] __initdata = { + &camera_devices[1], + &camera_devices[2], + &fsi_device, ++ &fsi_da7210_device, + &irda_device, + &vou_device, + #if defined(CONFIG_MMC_SH_MMCIF) || defined(CONFIG_MMC_SH_MMCIF_MODULE) +diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig +index 9ef49c8..c9fdf63 100644 +--- a/sound/soc/sh/Kconfig ++++ b/sound/soc/sh/Kconfig +@@ -46,14 +46,6 @@ config SND_SH7760_AC97 + This option enables generic sound support for the first + AC97 unit of the SH7760. + +-config SND_FSI_DA7210 +- tristate "FSI-DA7210 sound support" +- depends on SND_SOC_SH4_FSI && I2C +- select SND_SOC_DA7210 +- help +- This option enables generic sound support for the +- FSI - DA7210 unit +- + config SND_SIU_MIGOR + tristate "SIU sound support on Migo-R" + depends on SH_MIGOR +diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile +index f37fc3a..849b387 100644 +--- a/sound/soc/sh/Makefile ++++ b/sound/soc/sh/Makefile +@@ -14,9 +14,7 @@ obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o + + ## boards + snd-soc-sh7760-ac97-objs := sh7760-ac97.o +-snd-soc-fsi-da7210-objs := fsi-da7210.o + snd-soc-migor-objs := migor.o + + obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o +-obj-$(CONFIG_SND_FSI_DA7210) += snd-soc-fsi-da7210.o + obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o +diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c +deleted file mode 100644 +index 1dd3354..0000000 +--- a/sound/soc/sh/fsi-da7210.c ++++ /dev/null +@@ -1,81 +0,0 @@ +-/* +- * fsi-da7210.c +- * +- * Copyright (C) 2009 Renesas Solutions Corp. +- * Kuninori Morimoto <morimoto.kuninori@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; either version 2 of the License, or (at your +- * option) any later version. +- */ +- +-#include <linux/platform_device.h> +-#include <linux/module.h> +-#include <sound/sh_fsi.h> +- +-static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd) +-{ +- struct snd_soc_dai *codec = rtd->codec_dai; +- struct snd_soc_dai *cpu = rtd->cpu_dai; +- int ret; +- +- ret = snd_soc_dai_set_fmt(codec, +- SND_SOC_DAIFMT_I2S | +- SND_SOC_DAIFMT_CBM_CFM); +- if (ret < 0) +- return ret; +- +- ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_I2S | +- SND_SOC_DAIFMT_CBS_CFS); +- +- return ret; +-} +- +-static struct snd_soc_dai_link fsi_da7210_dai = { +- .name = "DA7210", +- .stream_name = "DA7210", +- .cpu_dai_name = "fsib-dai", /* FSI B */ +- .codec_dai_name = "da7210-hifi", +- .platform_name = "sh_fsi.0", +- .codec_name = "da7210-codec.0-001a", +- .init = fsi_da7210_init, +-}; +- +-static struct snd_soc_card fsi_soc_card = { +- .name = "FSI-DA7210", +- .owner = THIS_MODULE, +- .dai_link = &fsi_da7210_dai, +- .num_links = 1, +-}; +- +-static struct platform_device *fsi_da7210_snd_device; +- +-static int __init fsi_da7210_sound_init(void) +-{ +- int ret; +- +- fsi_da7210_snd_device = platform_device_alloc("soc-audio", FSI_PORT_B); +- if (!fsi_da7210_snd_device) +- return -ENOMEM; +- +- platform_set_drvdata(fsi_da7210_snd_device, &fsi_soc_card); +- ret = platform_device_add(fsi_da7210_snd_device); +- if (ret) +- platform_device_put(fsi_da7210_snd_device); +- +- return ret; +-} +- +-static void __exit fsi_da7210_sound_exit(void) +-{ +- platform_device_unregister(fsi_da7210_snd_device); +-} +- +-module_init(fsi_da7210_sound_init); +-module_exit(fsi_da7210_sound_exit); +- +-/* Module information */ +-MODULE_DESCRIPTION("ALSA SoC FSI DA2710"); +-MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>"); +-MODULE_LICENSE("GPL"); +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0023-ASoC-sh-fsi-use-register-field-macro-name-on-IN-OUT_.patch b/patches.armadillo800/0023-ASoC-sh-fsi-use-register-field-macro-name-on-IN-OUT_.patch new file mode 100644 index 0000000000000..56622e1385d2f --- /dev/null +++ b/patches.armadillo800/0023-ASoC-sh-fsi-use-register-field-macro-name-on-IN-OUT_.patch @@ -0,0 +1,27 @@ +From 09e74410c4effeb137a0aa05425057b740deb997 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 17 May 2012 17:33:49 -0700 +Subject: ASoC: sh: fsi: use register field macro name on IN/OUT_DMAC + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 4d62ec125be98f5a446444e4ce53f4f4e2e1baff) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -1218,8 +1218,8 @@ static int fsi_hw_startup(struct fsi_pri + * FSI2 chip can select it. + */ + if (fsi_ver >= 2) { +- fsi_reg_write(fsi, OUT_DMAC, (1 << 4)); +- fsi_reg_write(fsi, IN_DMAC, (1 << 4)); ++ fsi_reg_write(fsi, OUT_DMAC, VDMD_BACK); ++ fsi_reg_write(fsi, IN_DMAC, VDMD_BACK); + } + + /* irq clear */ diff --git a/patches.armadillo800/0024-ASoC-sh-fsi-add-fsi_version-and-removed-meaningless-.patch b/patches.armadillo800/0024-ASoC-sh-fsi-add-fsi_version-and-removed-meaningless-.patch new file mode 100644 index 0000000000000..71fc21e87acee --- /dev/null +++ b/patches.armadillo800/0024-ASoC-sh-fsi-add-fsi_version-and-removed-meaningless-.patch @@ -0,0 +1,105 @@ +From 9bc6d811db2dfc4f27805bc62d39e1bc319653e0 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 17 May 2012 17:34:16 -0700 +Subject: ASoC: sh: fsi: add fsi_version() and removed meaningless version + check + +This patch adds fsi_version() function for accessing version. + +And there were some meaningless version check which never hit. +This patch removed it. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 284c6f6547dd08d8f26e12f4014ec298faa7da03) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 26 ++++++++------------------ + 1 file changed, 8 insertions(+), 18 deletions(-) + +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -322,6 +322,10 @@ static void _fsi_master_mask_set(struct + /* + * basic function + */ ++static int fsi_version(struct fsi_master *master) ++{ ++ return master->core->ver; ++} + + static struct fsi_master *fsi_get_master(struct fsi_priv *fsi) + { +@@ -630,11 +634,6 @@ static void fsi_spdif_clk_ctrl(struct fs + struct fsi_master *master = fsi_get_master(fsi); + u32 mask, val; + +- if (master->core->ver < 2) { +- pr_err("fsi: register access err (%s)\n", __func__); +- return; +- } +- + mask = BP | SE; + val = enable ? mask : 0; + +@@ -649,9 +648,7 @@ static void fsi_spdif_clk_ctrl(struct fs + static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi, + long rate, int enable) + { +- struct fsi_master *master = fsi_get_master(fsi); + set_rate_func set_rate = fsi_get_info_set_rate(fsi); +- int fsi_ver = master->core->ver; + int ret; + + if (!set_rate) +@@ -683,10 +680,7 @@ static int fsi_set_master_clk(struct dev + data |= (0x3 << 12); + break; + case SH_FSI_ACKMD_32: +- if (fsi_ver < 2) +- dev_err(dev, "unsupported ACKMD\n"); +- else +- data |= (0x4 << 12); ++ data |= (0x4 << 12); + break; + } + +@@ -709,10 +703,7 @@ static int fsi_set_master_clk(struct dev + data |= (0x4 << 8); + break; + case SH_FSI_BPFMD_16: +- if (fsi_ver < 2) +- dev_err(dev, "unsupported ACKMD\n"); +- else +- data |= (0x7 << 8); ++ data |= (0x7 << 8); + break; + } + +@@ -1178,7 +1169,6 @@ static int fsi_hw_startup(struct fsi_pri + struct device *dev) + { + struct fsi_master *master = fsi_get_master(fsi); +- int fsi_ver = master->core->ver; + u32 flags = fsi_get_info_flags(fsi); + u32 data = 0; + +@@ -1217,7 +1207,7 @@ static int fsi_hw_startup(struct fsi_pri + * FSI driver assumed that data package is in-back. + * FSI2 chip can select it. + */ +- if (fsi_ver >= 2) { ++ if (fsi_version(master) >= 2) { + fsi_reg_write(fsi, OUT_DMAC, VDMD_BACK); + fsi_reg_write(fsi, IN_DMAC, VDMD_BACK); + } +@@ -1307,7 +1297,7 @@ static int fsi_set_fmt_spdif(struct fsi_ + struct fsi_master *master = fsi_get_master(fsi); + u32 data = 0; + +- if (master->core->ver < 2) ++ if (fsi_version(master) < 2) + return -EINVAL; + + data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM; diff --git a/patches.armadillo800/0025-ASoC-sh-fsi-use-same-format-for-IN-OUT.patch b/patches.armadillo800/0025-ASoC-sh-fsi-use-same-format-for-IN-OUT.patch new file mode 100644 index 0000000000000..9d9fe53798c8f --- /dev/null +++ b/patches.armadillo800/0025-ASoC-sh-fsi-use-same-format-for-IN-OUT.patch @@ -0,0 +1,83 @@ +From e41d8c0d85612475f270a3f0318570d4974f148f Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 17 May 2012 17:34:53 -0700 +Subject: ASoC: sh: fsi: use same format for IN/OUT + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 9c59dd342e4dd3c0bab5a9cad1aca7ed9501cbf8) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 22 ++++++---------------- + 1 file changed, 6 insertions(+), 16 deletions(-) + +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -212,8 +212,7 @@ struct fsi_priv { + struct fsi_stream playback; + struct fsi_stream capture; + +- u32 do_fmt; +- u32 di_fmt; ++ u32 fmt; + + int chan_num:16; + int clk_master:1; +@@ -1192,8 +1191,8 @@ static int fsi_hw_startup(struct fsi_pri + fsi_reg_write(fsi, CKG2, data); + + /* set format */ +- fsi_reg_write(fsi, DO_FMT, fsi->do_fmt); +- fsi_reg_write(fsi, DI_FMT, fsi->di_fmt); ++ fsi_reg_write(fsi, DO_FMT, fsi->fmt); ++ fsi_reg_write(fsi, DI_FMT, fsi->fmt); + + /* spdif ? */ + if (fsi_is_spdif(fsi)) { +@@ -1271,42 +1270,33 @@ static int fsi_dai_trigger(struct snd_pc + + static int fsi_set_fmt_dai(struct fsi_priv *fsi, unsigned int fmt) + { +- u32 data = 0; +- + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: +- data = CR_I2S; ++ fsi->fmt = CR_I2S; + fsi->chan_num = 2; + break; + case SND_SOC_DAIFMT_LEFT_J: +- data = CR_PCM; ++ fsi->fmt = CR_PCM; + fsi->chan_num = 2; + break; + default: + return -EINVAL; + } + +- fsi->do_fmt = data; +- fsi->di_fmt = data; +- + return 0; + } + + static int fsi_set_fmt_spdif(struct fsi_priv *fsi) + { + struct fsi_master *master = fsi_get_master(fsi); +- u32 data = 0; + + if (fsi_version(master) < 2) + return -EINVAL; + +- data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM; ++ fsi->fmt = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM; + fsi->chan_num = 2; + fsi->spdif = 1; + +- fsi->do_fmt = data; +- fsi->di_fmt = data; +- + return 0; + } + diff --git a/patches.armadillo800/0026-ASoC-sh-fsi-call-fsi_hw_startup-shutdown-from-fsi_da.patch b/patches.armadillo800/0026-ASoC-sh-fsi-call-fsi_hw_startup-shutdown-from-fsi_da.patch new file mode 100644 index 0000000000000..9d371ffffc786 --- /dev/null +++ b/patches.armadillo800/0026-ASoC-sh-fsi-call-fsi_hw_startup-shutdown-from-fsi_da.patch @@ -0,0 +1,53 @@ +From 30a251b30f73fdfa25d8e260c389bd688951b010 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 17 May 2012 17:35:34 -0700 +Subject: ASoC: sh: fsi: call fsi_hw_startup/shutdown from fsi_dai_trigger() + +fsi_hw_startup/shutdown() needs the setup of bus width, +but it is impossible to get parameter of snd_pcm_runtime at this timing. +So, these functions are changed so that be called from fsi_dai_trigger(). + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit f33238e96f619d9888713c07dcd92e4518879282) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -1233,7 +1233,9 @@ static int fsi_dai_startup(struct snd_pc + { + struct fsi_priv *fsi = fsi_get_priv(substream); + +- return fsi_hw_startup(fsi, fsi_stream_get(fsi, substream), dai->dev); ++ fsi->rate = 0; ++ ++ return 0; + } + + static void fsi_dai_shutdown(struct snd_pcm_substream *substream, +@@ -1241,7 +1243,6 @@ static void fsi_dai_shutdown(struct snd_ + { + struct fsi_priv *fsi = fsi_get_priv(substream); + +- fsi_hw_shutdown(fsi, dai->dev); + fsi->rate = 0; + } + +@@ -1255,11 +1256,13 @@ static int fsi_dai_trigger(struct snd_pc + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + fsi_stream_init(fsi, io, substream); ++ fsi_hw_startup(fsi, io, dai->dev); + ret = fsi_stream_transfer(io); + if (0 == ret) + fsi_stream_start(fsi, io); + break; + case SNDRV_PCM_TRIGGER_STOP: ++ fsi_hw_shutdown(fsi, dai->dev); + fsi_stream_stop(fsi, io); + fsi_stream_quit(fsi, io); + break; diff --git a/patches.armadillo800/0027-ASoC-sh-fsi-enable-chip-specific-data-transfer-mode.patch b/patches.armadillo800/0027-ASoC-sh-fsi-enable-chip-specific-data-transfer-mode.patch new file mode 100644 index 0000000000000..278811038c4ae --- /dev/null +++ b/patches.armadillo800/0027-ASoC-sh-fsi-enable-chip-specific-data-transfer-mode.patch @@ -0,0 +1,334 @@ +From 603569524ecf479df58238d5c3556bb0882361b1 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 17 May 2012 17:36:47 -0700 +Subject: ASoC: sh: fsi: enable chip specific data transfer mode + +SupherH FSI2 can use special data transfer, +but it depends on CPU-FSI2 connection style. + +We can use 16bit data stream mode if it was valid connection, +and it is required for 16bit data DMA transfer / SPDIF sound output. +We can use 24bit data transfer if it was invalid connection. + +We can select connection type if CPU is SH7372, +and it is always valid connection if latest SuperH. + +This patch adds new bus_option and fsi_bus_setup() +for supporting these feature. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 766812e6d5e2e23be1e212cf84902d5e834dd865) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/sound/sh_fsi.h | 6 + + sound/soc/sh/fsi.c | 177 +++++++++++++++++++++++++++++++++++++++---------- + 2 files changed, 148 insertions(+), 35 deletions(-) + +--- a/include/sound/sh_fsi.h ++++ b/include/sound/sh_fsi.h +@@ -21,10 +21,11 @@ + /* + * flags format + * +- * 0x000000BA ++ * 0x00000CBA + * + * A: inversion + * B: format mode ++ * C: chip specific + */ + + /* A: clock inversion */ +@@ -39,6 +40,9 @@ + #define SH_FSI_FMT_DAI (0 << 4) + #define SH_FSI_FMT_SPDIF (1 << 4) + ++/* C: chip specific */ ++#define SH_FSI_OPTION_MASK 0x00000F00 ++#define SH_FSI_ENABLE_STREAM_MODE (1 << 8) /* for 16bit data */ + + /* + * set_rate return value +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -133,6 +133,25 @@ + typedef int (*set_rate_func)(struct device *dev, int rate, int enable); + + /* ++ * bus options ++ * ++ * 0x000000BA ++ * ++ * A : sample widtht 16bit setting ++ * B : sample widtht 24bit setting ++ */ ++ ++#define SHIFT_16DATA 0 ++#define SHIFT_24DATA 4 ++ ++#define PACKAGE_24BITBUS_BACK 0 ++#define PACKAGE_24BITBUS_FRONT 1 ++#define PACKAGE_16BITBUS_STREAM 2 ++ ++#define BUSOP_SET(s, a) ((a) << SHIFT_ ## s ## DATA) ++#define BUSOP_GET(s, a) (((a) >> SHIFT_ ## s ## DATA) & 0xF) ++ ++/* + * FSI driver use below type name for variable + * + * xxx_num : number of data +@@ -190,6 +209,11 @@ struct fsi_stream { + int oerr_num; + + /* ++ * bus options ++ */ ++ u32 bus_option; ++ ++ /* + * thse are initialized by fsi_handler_init() + */ + struct fsi_stream_handler *handler; +@@ -499,6 +523,7 @@ static void fsi_stream_init(struct fsi_p + io->period_samples = fsi_frame2sample(fsi, runtime->period_size); + io->period_pos = 0; + io->sample_width = samples_to_bytes(runtime, 1); ++ io->bus_option = 0; + io->oerr_num = -1; /* ignore 1st err */ + io->uerr_num = -1; /* ignore 1st err */ + fsi_stream_handler_call(io, init, fsi, io); +@@ -526,6 +551,7 @@ static void fsi_stream_quit(struct fsi_p + io->period_samples = 0; + io->period_pos = 0; + io->sample_width = 0; ++ io->bus_option = 0; + io->oerr_num = 0; + io->uerr_num = 0; + spin_unlock_irqrestore(&master->lock, flags); +@@ -585,6 +611,53 @@ static int fsi_stream_remove(struct fsi_ + } + + /* ++ * format/bus/dma setting ++ */ ++static void fsi_format_bus_setup(struct fsi_priv *fsi, struct fsi_stream *io, ++ u32 bus, struct device *dev) ++{ ++ struct fsi_master *master = fsi_get_master(fsi); ++ int is_play = fsi_stream_is_play(fsi, io); ++ u32 fmt = fsi->fmt; ++ ++ if (fsi_version(master) >= 2) { ++ u32 dma = 0; ++ ++ /* ++ * FSI2 needs DMA/Bus setting ++ */ ++ switch (bus) { ++ case PACKAGE_24BITBUS_FRONT: ++ fmt |= CR_BWS_24; ++ dma |= VDMD_FRONT; ++ dev_dbg(dev, "24bit bus / package in front\n"); ++ break; ++ case PACKAGE_16BITBUS_STREAM: ++ fmt |= CR_BWS_16; ++ dma |= VDMD_STREAM; ++ dev_dbg(dev, "16bit bus / stream mode\n"); ++ break; ++ case PACKAGE_24BITBUS_BACK: ++ default: ++ fmt |= CR_BWS_24; ++ dma |= VDMD_BACK; ++ dev_dbg(dev, "24bit bus / package in back\n"); ++ break; ++ } ++ ++ if (is_play) ++ fsi_reg_write(fsi, OUT_DMAC, dma); ++ else ++ fsi_reg_write(fsi, IN_DMAC, dma); ++ } ++ ++ if (is_play) ++ fsi_reg_write(fsi, DO_FMT, fmt); ++ else ++ fsi_reg_write(fsi, DI_FMT, fmt); ++} ++ ++/* + * irq function + */ + +@@ -719,11 +792,26 @@ static int fsi_set_master_clk(struct dev + */ + static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples) + { +- u16 *buf = (u16 *)_buf; ++ u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE; + int i; + +- for (i = 0; i < samples; i++) +- fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8)); ++ if (enable_stream) { ++ /* ++ * stream mode ++ * see ++ * fsi_pio_push_init() ++ */ ++ u32 *buf = (u32 *)_buf; ++ ++ for (i = 0; i < samples / 2; i++) ++ fsi_reg_write(fsi, DODT, buf[i]); ++ } else { ++ /* normal mode */ ++ u16 *buf = (u16 *)_buf; ++ ++ for (i = 0; i < samples; i++) ++ fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8)); ++ } + } + + static void fsi_pio_pop16(struct fsi_priv *fsi, u8 *_buf, int samples) +@@ -863,12 +951,44 @@ static void fsi_pio_start_stop(struct fs + fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); + } + ++static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io) ++{ ++ u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE; ++ ++ /* ++ * we can use 16bit stream mode ++ * when "playback" and "16bit data" ++ * and platform allows "stream mode" ++ * see ++ * fsi_pio_push16() ++ */ ++ if (enable_stream) ++ io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) | ++ BUSOP_SET(16, PACKAGE_16BITBUS_STREAM); ++ else ++ io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) | ++ BUSOP_SET(16, PACKAGE_24BITBUS_BACK); ++ return 0; ++} ++ ++static int fsi_pio_pop_init(struct fsi_priv *fsi, struct fsi_stream *io) ++{ ++ /* ++ * always 24bit bus, package back when "capture" ++ */ ++ io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) | ++ BUSOP_SET(16, PACKAGE_24BITBUS_BACK); ++ return 0; ++} ++ + static struct fsi_stream_handler fsi_pio_push_handler = { ++ .init = fsi_pio_push_init, + .transfer = fsi_pio_push, + .start_stop = fsi_pio_start_stop, + }; + + static struct fsi_stream_handler fsi_pio_pop_handler = { ++ .init = fsi_pio_pop_init, + .transfer = fsi_pio_pop, + .start_stop = fsi_pio_start_stop, + }; +@@ -910,6 +1030,13 @@ static int fsi_dma_init(struct fsi_priv + enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ? + DMA_TO_DEVICE : DMA_FROM_DEVICE; + ++ /* ++ * 24bit data : 24bit bus / package in back ++ * 16bit data : 16bit bus / stream mode ++ */ ++ io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) | ++ BUSOP_SET(16, PACKAGE_16BITBUS_STREAM); ++ + io->dma = dma_map_single(dai->dev, runtime->dma_area, + snd_pcm_lib_buffer_bytes(io->substream), dir); + return 0; +@@ -1046,25 +1173,9 @@ static int fsi_dma_transfer(struct fsi_p + static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, + int start) + { +- u32 bws; +- u32 dma; ++ u32 enable = start ? DMA_ON : 0; + +- switch (io->sample_width * start) { +- case 2: +- bws = CR_BWS_16; +- dma = VDMD_STREAM | DMA_ON; +- break; +- case 4: +- bws = CR_BWS_24; +- dma = VDMD_BACK | DMA_ON; +- break; +- default: +- bws = 0; +- dma = 0; +- } +- +- fsi_reg_mask_set(fsi, DO_FMT, CR_BWS_MASK, bws); +- fsi_reg_write(fsi, OUT_DMAC, dma); ++ fsi_reg_mask_set(fsi, OUT_DMAC, DMA_ON, enable); + } + + static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io) +@@ -1167,7 +1278,6 @@ static int fsi_hw_startup(struct fsi_pri + struct fsi_stream *io, + struct device *dev) + { +- struct fsi_master *master = fsi_get_master(fsi); + u32 flags = fsi_get_info_flags(fsi); + u32 data = 0; + +@@ -1190,10 +1300,6 @@ static int fsi_hw_startup(struct fsi_pri + + fsi_reg_write(fsi, CKG2, data); + +- /* set format */ +- fsi_reg_write(fsi, DO_FMT, fsi->fmt); +- fsi_reg_write(fsi, DI_FMT, fsi->fmt); +- + /* spdif ? */ + if (fsi_is_spdif(fsi)) { + fsi_spdif_clk_ctrl(fsi, 1); +@@ -1201,15 +1307,18 @@ static int fsi_hw_startup(struct fsi_pri + } + + /* +- * FIXME +- * +- * FSI driver assumed that data package is in-back. +- * FSI2 chip can select it. ++ * get bus settings + */ +- if (fsi_version(master) >= 2) { +- fsi_reg_write(fsi, OUT_DMAC, VDMD_BACK); +- fsi_reg_write(fsi, IN_DMAC, VDMD_BACK); ++ data = 0; ++ switch (io->sample_width) { ++ case 2: ++ data = BUSOP_GET(16, io->bus_option); ++ break; ++ case 4: ++ data = BUSOP_GET(24, io->bus_option); ++ break; + } ++ fsi_format_bus_setup(fsi, io, data, dev); + + /* irq clear */ + fsi_irq_disable(fsi, io); +@@ -1296,7 +1405,7 @@ static int fsi_set_fmt_spdif(struct fsi_ + if (fsi_version(master) < 2) + return -EINVAL; + +- fsi->fmt = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM; ++ fsi->fmt = CR_DTMD_SPDIF_PCM | CR_PCM; + fsi->chan_num = 2; + fsi->spdif = 1; + diff --git a/patches.armadillo800/0028-ASoC-fsi-bugfix-enable-master-clock-control-on-DMA-s.patch b/patches.armadillo800/0028-ASoC-fsi-bugfix-enable-master-clock-control-on-DMA-s.patch new file mode 100644 index 0000000000000..380aeb5460603 --- /dev/null +++ b/patches.armadillo800/0028-ASoC-fsi-bugfix-enable-master-clock-control-on-DMA-s.patch @@ -0,0 +1,34 @@ +From 8dedb2aa24856018132764d9c3411c7600087b3e Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 24 May 2012 23:55:11 -0700 +Subject: ASoC: fsi: bugfix: enable master clock control on DMA stream + +DMA stream handler didn't care about master clock. +This patch fixes it up. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit e42bb9bfbb43366cd1899c9564d043c41ebd8852) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -1173,9 +1173,14 @@ static int fsi_dma_transfer(struct fsi_p + static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, + int start) + { ++ struct fsi_master *master = fsi_get_master(fsi); ++ u32 clk = fsi_is_port_a(fsi) ? CRA : CRB; + u32 enable = start ? DMA_ON : 0; + + fsi_reg_mask_set(fsi, OUT_DMAC, DMA_ON, enable); ++ ++ if (fsi_is_clk_master(fsi)) ++ fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); + } + + static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io) diff --git a/patches.armadillo800/0029-ASoC-fsi-bugfix-correct-dma-area.patch b/patches.armadillo800/0029-ASoC-fsi-bugfix-correct-dma-area.patch new file mode 100644 index 0000000000000..dcbbc64a78354 --- /dev/null +++ b/patches.armadillo800/0029-ASoC-fsi-bugfix-correct-dma-area.patch @@ -0,0 +1,66 @@ +From ce1ff80d007ef6f5c64c65fd0d44b587657ae0c6 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 28 May 2012 23:27:49 -0700 +Subject: ASoC: fsi: bugfix: correct dma area + +FSI driver is using dma_sync_single_xxx(), +but the dma area was not correct. +This patch fix it up. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 4a1b09b79b07cf70c72a091e8fe0660f68541f30) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -1053,6 +1053,13 @@ static int fsi_dma_quit(struct fsi_priv + return 0; + } + ++static dma_addr_t fsi_dma_get_area(struct fsi_stream *io) ++{ ++ struct snd_pcm_runtime *runtime = io->substream->runtime; ++ ++ return io->dma + samples_to_bytes(runtime, io->buff_sample_pos); ++} ++ + static void fsi_dma_complete(void *data) + { + struct fsi_stream *io = (struct fsi_stream *)data; +@@ -1062,7 +1069,7 @@ static void fsi_dma_complete(void *data) + enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ? + DMA_TO_DEVICE : DMA_FROM_DEVICE; + +- dma_sync_single_for_cpu(dai->dev, io->dma, ++ dma_sync_single_for_cpu(dai->dev, fsi_dma_get_area(io), + samples_to_bytes(runtime, io->period_samples), dir); + + io->buff_sample_pos += io->period_samples; +@@ -1079,13 +1086,6 @@ static void fsi_dma_complete(void *data) + snd_pcm_period_elapsed(io->substream); + } + +-static dma_addr_t fsi_dma_get_area(struct fsi_stream *io) +-{ +- struct snd_pcm_runtime *runtime = io->substream->runtime; +- +- return io->dma + samples_to_bytes(runtime, io->buff_sample_pos); +-} +- + static void fsi_dma_do_work(struct work_struct *work) + { + struct fsi_stream *io = container_of(work, struct fsi_stream, work); +@@ -1111,7 +1111,7 @@ static void fsi_dma_do_work(struct work_ + len = samples_to_bytes(runtime, io->period_samples); + buf = fsi_dma_get_area(io); + +- dma_sync_single_for_device(dai->dev, io->dma, len, dir); ++ dma_sync_single_for_device(dai->dev, buf, len, dir); + + sg_init_table(&sg, 1); + sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf)), diff --git a/patches.armadillo800/0030-ASoC-fsi-bugfix-ensure-dma-is-terminated.patch b/patches.armadillo800/0030-ASoC-fsi-bugfix-ensure-dma-is-terminated.patch new file mode 100644 index 0000000000000..a392175faca90 --- /dev/null +++ b/patches.armadillo800/0030-ASoC-fsi-bugfix-ensure-dma-is-terminated.patch @@ -0,0 +1,28 @@ +From d94ab970e6055b3e6f7cab54a405431e47445ae4 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 28 May 2012 23:28:22 -0700 +Subject: ASoC: fsi: bugfix: ensure dma is terminated + +FSI DMAEngine has to be stopped certainly at the start/stop time. +Without this patch, it will include noise on playback. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit fbe42f66c66c279b4ed9b8f515058a09bc731c49) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -1179,6 +1179,8 @@ static void fsi_dma_push_start_stop(stru + + fsi_reg_mask_set(fsi, OUT_DMAC, DMA_ON, enable); + ++ dmaengine_terminate_all(io->chan); ++ + if (fsi_is_clk_master(fsi)) + fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); + } diff --git a/patches.armadillo800/0031-ASoC-fsi-use-dmaengine-helper-functions.patch b/patches.armadillo800/0031-ASoC-fsi-use-dmaengine-helper-functions.patch new file mode 100644 index 0000000000000..8c331203fecaf --- /dev/null +++ b/patches.armadillo800/0031-ASoC-fsi-use-dmaengine-helper-functions.patch @@ -0,0 +1,74 @@ +From 341b5a7a28c7b1404b9875366b2b2c1dabd06ee8 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 28 May 2012 23:29:36 -0700 +Subject: ASoC: fsi: use dmaengine helper functions + +This patch used dmaengine helper functions instead of using hand setting. +And reduced local variables + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit 5514efdfe0384576ef38c66b1672b6826696fbf3) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 19 ++++--------------- + 1 file changed, 4 insertions(+), 15 deletions(-) + +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -1090,13 +1090,10 @@ static void fsi_dma_do_work(struct work_ + { + struct fsi_stream *io = container_of(work, struct fsi_stream, work); + struct fsi_priv *fsi = fsi_stream_to_priv(io); +- struct dma_chan *chan; + struct snd_soc_dai *dai; + struct dma_async_tx_descriptor *desc; +- struct scatterlist sg; + struct snd_pcm_runtime *runtime; + enum dma_data_direction dir; +- dma_cookie_t cookie; + int is_play = fsi_stream_is_play(fsi, io); + int len; + dma_addr_t buf; +@@ -1105,7 +1102,6 @@ static void fsi_dma_do_work(struct work_ + return; + + dai = fsi_get_dai(io->substream); +- chan = io->chan; + runtime = io->substream->runtime; + dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + len = samples_to_bytes(runtime, io->period_samples); +@@ -1113,14 +1109,8 @@ static void fsi_dma_do_work(struct work_ + + dma_sync_single_for_device(dai->dev, buf, len, dir); + +- sg_init_table(&sg, 1); +- sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf)), +- len , offset_in_page(buf)); +- sg_dma_address(&sg) = buf; +- sg_dma_len(&sg) = len; +- +- desc = dmaengine_prep_slave_sg(chan, &sg, 1, dir, +- DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ desc = dmaengine_prep_slave_single(io->chan, buf, len, dir, ++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!desc) { + dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n"); + return; +@@ -1129,13 +1119,12 @@ static void fsi_dma_do_work(struct work_ + desc->callback = fsi_dma_complete; + desc->callback_param = io; + +- cookie = desc->tx_submit(desc); +- if (cookie < 0) { ++ if (dmaengine_submit(desc) < 0) { + dev_err(dai->dev, "tx_submit() fail\n"); + return; + } + +- dma_async_issue_pending(chan); ++ dma_async_issue_pending(io->chan); + + /* + * FIXME diff --git a/patches.armadillo800/0032-ASoC-fsi-use-PIO-handler-if-DMA-handler-was-invalid.patch b/patches.armadillo800/0032-ASoC-fsi-use-PIO-handler-if-DMA-handler-was-invalid.patch new file mode 100644 index 0000000000000..4d8ccec3cbbba --- /dev/null +++ b/patches.armadillo800/0032-ASoC-fsi-use-PIO-handler-if-DMA-handler-was-invalid.patch @@ -0,0 +1,97 @@ +From 2c50008416a53374914d047b290c1f28842ce4b3 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 24 May 2012 23:56:19 -0700 +Subject: ASoC: fsi: use PIO handler if DMA handler was invalid + +PIO handler is not good performance, but works on all platform. +So, switch to PIO handler if DMA handler was invalid case. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +(cherry picked from commit b1226dc59d55ecde7fc9a338d8cb2a313821fac0) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 29 ++++++++++++++++++++--------- + 1 file changed, 20 insertions(+), 9 deletions(-) + +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -248,7 +248,7 @@ struct fsi_priv { + struct fsi_stream_handler { + int (*init)(struct fsi_priv *fsi, struct fsi_stream *io); + int (*quit)(struct fsi_priv *fsi, struct fsi_stream *io); +- int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io); ++ int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev); + int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io); + int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io); + void (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io, +@@ -572,16 +572,16 @@ static int fsi_stream_transfer(struct fs + #define fsi_stream_stop(fsi, io)\ + fsi_stream_handler_call(io, start_stop, fsi, io, 0) + +-static int fsi_stream_probe(struct fsi_priv *fsi) ++static int fsi_stream_probe(struct fsi_priv *fsi, struct device *dev) + { + struct fsi_stream *io; + int ret1, ret2; + + io = &fsi->playback; +- ret1 = fsi_stream_handler_call(io, probe, fsi, io); ++ ret1 = fsi_stream_handler_call(io, probe, fsi, io, dev); + + io = &fsi->capture; +- ret2 = fsi_stream_handler_call(io, probe, fsi, io); ++ ret2 = fsi_stream_handler_call(io, probe, fsi, io, dev); + + if (ret1 < 0) + return ret1; +@@ -1174,7 +1174,7 @@ static void fsi_dma_push_start_stop(stru + fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); + } + +-static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io) ++static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev) + { + dma_cap_mask_t mask; + +@@ -1182,8 +1182,19 @@ static int fsi_dma_probe(struct fsi_priv + dma_cap_set(DMA_SLAVE, mask); + + io->chan = dma_request_channel(mask, fsi_dma_filter, &io->slave); +- if (!io->chan) +- return -EIO; ++ if (!io->chan) { ++ ++ /* switch to PIO handler */ ++ if (fsi_stream_is_play(fsi, io)) ++ fsi->playback.handler = &fsi_pio_push_handler; ++ else ++ fsi->capture.handler = &fsi_pio_pop_handler; ++ ++ dev_info(dev, "switch handler (dma => pio)\n"); ++ ++ /* probe again */ ++ return fsi_stream_probe(fsi, dev); ++ } + + INIT_WORK(&io->work, fsi_dma_do_work); + +@@ -1673,7 +1684,7 @@ static int fsi_probe(struct platform_dev + master->fsia.master = master; + master->fsia.info = &info->port_a; + fsi_handler_init(&master->fsia); +- ret = fsi_stream_probe(&master->fsia); ++ ret = fsi_stream_probe(&master->fsia, &pdev->dev); + if (ret < 0) { + dev_err(&pdev->dev, "FSIA stream probe failed\n"); + goto exit_iounmap; +@@ -1684,7 +1695,7 @@ static int fsi_probe(struct platform_dev + master->fsib.master = master; + master->fsib.info = &info->port_b; + fsi_handler_init(&master->fsib); +- ret = fsi_stream_probe(&master->fsib); ++ ret = fsi_stream_probe(&master->fsib, &pdev->dev); + if (ret < 0) { + dev_err(&pdev->dev, "FSIB stream probe failed\n"); + goto exit_fsia; diff --git a/patches.armadillo800/0033-ASoC-fsi-prepare-for-conversion-to-the-shdma-base-li.patch b/patches.armadillo800/0033-ASoC-fsi-prepare-for-conversion-to-the-shdma-base-li.patch new file mode 100644 index 0000000000000..23f861ebc5a00 --- /dev/null +++ b/patches.armadillo800/0033-ASoC-fsi-prepare-for-conversion-to-the-shdma-base-li.patch @@ -0,0 +1,35 @@ +From 223018081111b56755835850e5dbc7a122f5f1b5 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 9 May 2012 17:09:20 +0200 +Subject: ASoC: fsi: prepare for conversion to the shdma base library + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Cc: Liam Girdwood <lrg@ti.com> +Cc: Mark Brown <broonie@opensource.wolfsonmicro.com> +Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit b8373147ed3ca01a968d81f22688f2836a9aeb6b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 53486ff..0540408 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -1631,8 +1631,8 @@ static void fsi_handler_init(struct fsi_priv *fsi) + fsi->capture.priv = fsi; + + if (fsi->info->tx_id) { +- fsi->playback.slave.slave_id = fsi->info->tx_id; +- fsi->playback.handler = &fsi_dma_push_handler; ++ fsi->playback.slave.shdma_slave.slave_id = fsi->info->tx_id; ++ fsi->playback.handler = &fsi_dma_push_handler; + } + } + +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0034-fbdev-sh_mobile_hdmi-add-hdmi_bit_set-function.patch b/patches.armadillo800/0034-fbdev-sh_mobile_hdmi-add-hdmi_bit_set-function.patch new file mode 100644 index 0000000000000..9e9dfefc9143c --- /dev/null +++ b/patches.armadillo800/0034-fbdev-sh_mobile_hdmi-add-hdmi_bit_set-function.patch @@ -0,0 +1,86 @@ +From 575ef93e0d64ff352f0bafc5038468b13796104b Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 7 May 2012 21:06:54 -0700 +Subject: fbdev: sh_mobile_hdmi: add hdmi_bit_set() function + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de> +(cherry picked from commit 3f521abd6cf1320d65a49cf9fc327b82168b5ba0) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/video/sh_mobile_hdmi.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c +index eafb19d..e201d6f 100644 +--- a/drivers/video/sh_mobile_hdmi.c ++++ b/drivers/video/sh_mobile_hdmi.c +@@ -236,6 +236,16 @@ static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg) + return ioread8(hdmi->base + reg); + } + ++static void hdmi_bit_set(struct sh_hdmi *hdmi, u8 mask, u8 data, u8 reg) ++{ ++ u8 val = hdmi_read(hdmi, reg); ++ ++ val &= ~mask; ++ val |= (data & mask); ++ ++ hdmi_write(hdmi, val, reg); ++} ++ + /* + * HDMI sound + */ +@@ -693,11 +703,11 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi) + msleep(10); + + /* PS mode b->d, reset PLLA and PLLB */ +- hdmi_write(hdmi, 0x4C, HDMI_SYSTEM_CTRL); ++ hdmi_bit_set(hdmi, 0xFC, 0x4C, HDMI_SYSTEM_CTRL); + + udelay(10); + +- hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL); ++ hdmi_bit_set(hdmi, 0xFC, 0x40, HDMI_SYSTEM_CTRL); + } + + static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi, +@@ -917,13 +927,13 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id) + u8 status1, status2, mask1, mask2; + + /* mode_b and PLLA and PLLB reset */ +- hdmi_write(hdmi, 0x2C, HDMI_SYSTEM_CTRL); ++ hdmi_bit_set(hdmi, 0xFC, 0x2C, HDMI_SYSTEM_CTRL); + + /* How long shall reset be held? */ + udelay(10); + + /* mode_b and PLLA and PLLB reset release */ +- hdmi_write(hdmi, 0x20, HDMI_SYSTEM_CTRL); ++ hdmi_bit_set(hdmi, 0xFC, 0x20, HDMI_SYSTEM_CTRL); + + status1 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_1); + status2 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_2); +@@ -1001,7 +1011,7 @@ static int sh_hdmi_display_on(struct sh_mobile_lcdc_entity *entity) + */ + if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) { + /* PS mode d->e. All functions are active */ +- hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL); ++ hdmi_bit_set(hdmi, 0xFC, 0x80, HDMI_SYSTEM_CTRL); + dev_dbg(hdmi->dev, "HDMI running\n"); + } + +@@ -1016,7 +1026,7 @@ static void sh_hdmi_display_off(struct sh_mobile_lcdc_entity *entity) + + dev_dbg(hdmi->dev, "%s(%p)\n", __func__, hdmi); + /* PS mode e->a */ +- hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL); ++ hdmi_bit_set(hdmi, 0xFC, 0x10, HDMI_SYSTEM_CTRL); + } + + static const struct sh_mobile_lcdc_entity_ops sh_hdmi_ops = { +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0035-fbdev-sh_mobile_hdmi-add-interrupt-output-option.patch b/patches.armadillo800/0035-fbdev-sh_mobile_hdmi-add-interrupt-output-option.patch new file mode 100644 index 0000000000000..e03a1158ef387 --- /dev/null +++ b/patches.armadillo800/0035-fbdev-sh_mobile_hdmi-add-interrupt-output-option.patch @@ -0,0 +1,64 @@ +From 1f09b960ec16950e3791ba297de136bedc56be51 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 7 May 2012 21:07:20 -0700 +Subject: fbdev: sh_mobile_hdmi: add interrupt output option + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de> +(cherry picked from commit e0defc86423d1b5652826c9317c36dfb6af1cd48) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/video/sh_mobile_hdmi.c | 7 +++++++ + include/video/sh_mobile_hdmi.h | 8 +++++++- + 2 files changed, 14 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c +index e201d6f..0bc39bc 100644 +--- a/drivers/video/sh_mobile_hdmi.c ++++ b/drivers/video/sh_mobile_hdmi.c +@@ -1186,6 +1186,13 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) + pm_runtime_enable(&pdev->dev); + pm_runtime_get_sync(&pdev->dev); + ++ /* init interrupt polarity */ ++ if (pdata->flags & HDMI_OUTPUT_PUSH_PULL) ++ hdmi_bit_set(hdmi, 0x02, 0x02, HDMI_SYSTEM_CTRL); ++ ++ if (pdata->flags & HDMI_OUTPUT_POLARITY_HI) ++ hdmi_bit_set(hdmi, 0x01, 0x01, HDMI_SYSTEM_CTRL); ++ + /* Product and revision IDs are 0 in sh-mobile version */ + dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n", + hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID)); +diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h +index 728f9de..2699635 100644 +--- a/include/video/sh_mobile_hdmi.h ++++ b/include/video/sh_mobile_hdmi.h +@@ -18,9 +18,10 @@ struct clk; + /* + * flags format + * +- * 0x0000000A ++ * 0x000000BA + * + * A: Audio source select ++ * B: Int output option + */ + + /* Audio source select */ +@@ -30,6 +31,11 @@ struct clk; + #define HDMI_SND_SRC_DSD (2 << 0) + #define HDMI_SND_SRC_HBR (3 << 0) + ++/* Int output option */ ++#define HDMI_OUTPUT_PUSH_PULL (1 << 4) /* System control : output mode */ ++#define HDMI_OUTPUT_POLARITY_HI (1 << 5) /* System control : output polarity */ ++ ++ + struct sh_mobile_hdmi_info { + unsigned int flags; + long (*clk_optimize_parent)(unsigned long target, unsigned long *best_freq, +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0036-fbdev-sh_mobile_hdmi-32bit-register-access-support.patch b/patches.armadillo800/0036-fbdev-sh_mobile_hdmi-32bit-register-access-support.patch new file mode 100644 index 0000000000000..d5517c4fda3d6 --- /dev/null +++ b/patches.armadillo800/0036-fbdev-sh_mobile_hdmi-32bit-register-access-support.patch @@ -0,0 +1,115 @@ +From 6fb22732c461a0efc337cc6cd03fda18e0b2d1cf Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 7 May 2012 21:07:49 -0700 +Subject: fbdev: sh_mobile_hdmi: 32bit register access support + +Latest SuperH HDMI allows 32bit access only. +But the data is 8bit. So, we can keep compatibility by switching 8/32 bit access. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de> +(cherry picked from commit db6668d83a265a15ffd79dbc8432598808b34bb4) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/video/sh_mobile_hdmi.c | 38 ++++++++++++++++++++++++++++++++++++-- + include/video/sh_mobile_hdmi.h | 5 ++++- + 2 files changed, 40 insertions(+), 3 deletions(-) + +diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c +index 0bc39bc..4d48a80 100644 +--- a/drivers/video/sh_mobile_hdmi.c ++++ b/drivers/video/sh_mobile_hdmi.c +@@ -222,20 +222,45 @@ struct sh_hdmi { + struct delayed_work edid_work; + struct fb_videomode mode; + struct fb_monspecs monspec; ++ ++ /* register access functions */ ++ void (*write)(struct sh_hdmi *hdmi, u8 data, u8 reg); ++ u8 (*read)(struct sh_hdmi *hdmi, u8 reg); + }; + + #define entity_to_sh_hdmi(e) container_of(e, struct sh_hdmi, entity) + +-static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg) ++static void __hdmi_write8(struct sh_hdmi *hdmi, u8 data, u8 reg) + { + iowrite8(data, hdmi->base + reg); + } + +-static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg) ++static u8 __hdmi_read8(struct sh_hdmi *hdmi, u8 reg) + { + return ioread8(hdmi->base + reg); + } + ++static void __hdmi_write32(struct sh_hdmi *hdmi, u8 data, u8 reg) ++{ ++ iowrite32((u32)data, hdmi->base + (reg * 4)); ++ udelay(100); ++} ++ ++static u8 __hdmi_read32(struct sh_hdmi *hdmi, u8 reg) ++{ ++ return (u8)ioread32(hdmi->base + (reg * 4)); ++} ++ ++static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg) ++{ ++ hdmi->write(hdmi, data, reg); ++} ++ ++static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg) ++{ ++ return hdmi->read(hdmi, reg); ++} ++ + static void hdmi_bit_set(struct sh_hdmi *hdmi, u8 mask, u8 data, u8 reg) + { + u8 val = hdmi_read(hdmi, reg); +@@ -1148,6 +1173,15 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) + goto egetclk; + } + ++ /* select register access functions */ ++ if (pdata->flags & HDMI_32BIT_REG) { ++ hdmi->write = __hdmi_write32; ++ hdmi->read = __hdmi_read32; ++ } else { ++ hdmi->write = __hdmi_write8; ++ hdmi->read = __hdmi_read8; ++ } ++ + /* An arbitrary relaxed pixclock just to get things started: from standard 480p */ + rate = clk_round_rate(hdmi->hdmi_clk, PICOS2KHZ(37037)); + if (rate > 0) +diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h +index 2699635..ce8a540 100644 +--- a/include/video/sh_mobile_hdmi.h ++++ b/include/video/sh_mobile_hdmi.h +@@ -18,10 +18,11 @@ struct clk; + /* + * flags format + * +- * 0x000000BA ++ * 0x00000CBA + * + * A: Audio source select + * B: Int output option ++ * C: Chip specific option + */ + + /* Audio source select */ +@@ -35,6 +36,8 @@ struct clk; + #define HDMI_OUTPUT_PUSH_PULL (1 << 4) /* System control : output mode */ + #define HDMI_OUTPUT_POLARITY_HI (1 << 5) /* System control : output polarity */ + ++/* Chip specific option */ ++#define HDMI_32BIT_REG (1 << 8) + + struct sh_mobile_hdmi_info { + unsigned int flags; +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0037-fbdev-sh_mobile_hdmi-add-HDMI-Control-Register-suppo.patch b/patches.armadillo800/0037-fbdev-sh_mobile_hdmi-add-HDMI-Control-Register-suppo.patch new file mode 100644 index 0000000000000..93db80ca9980c --- /dev/null +++ b/patches.armadillo800/0037-fbdev-sh_mobile_hdmi-add-HDMI-Control-Register-suppo.patch @@ -0,0 +1,264 @@ +From ccd4120f4b46b4f6c043108aa6f5bbb8f63f959e Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 7 May 2012 21:08:17 -0700 +Subject: fbdev: sh_mobile_hdmi: add HDMI Control Register support + +Latest SuperH HDMI uses not only HDMI Core Register (HTOP0) +but also HDMI Control Register (HTOP1). +This patch adds HDMI Control Register support. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de> +(cherry picked from commit c932b2731116f99a660817e8fa718c9da0798a9c) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/video/sh_mobile_hdmi.c | 152 ++++++++++++++++++++++++++++++++++++++++- + include/video/sh_mobile_hdmi.h | 1 + + 2 files changed, 152 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c +index 4d48a80..930e550 100644 +--- a/drivers/video/sh_mobile_hdmi.c ++++ b/drivers/video/sh_mobile_hdmi.c +@@ -31,6 +31,7 @@ + + #include "sh_mobile_lcdcfb.h" + ++/* HDMI Core Control Register (HTOP0) */ + #define HDMI_SYSTEM_CTRL 0x00 /* System control */ + #define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control, + bits 19..16 of 20-bit N for Audio Clock Regeneration packet */ +@@ -201,6 +202,68 @@ + #define HDMI_REVISION_ID 0xF1 /* Revision ID */ + #define HDMI_TEST_MODE 0xFE /* Test mode */ + ++/* HDMI Control Register (HTOP1) */ ++#define HDMI_HTOP1_TEST_MODE 0x0000 /* Test mode */ ++#define HDMI_HTOP1_VIDEO_INPUT 0x0008 /* VideoInput */ ++#define HDMI_HTOP1_CORE_RSTN 0x000C /* CoreResetn */ ++#define HDMI_HTOP1_PLLBW 0x0018 /* PLLBW */ ++#define HDMI_HTOP1_CLK_TO_PHY 0x001C /* Clk to Phy */ ++#define HDMI_HTOP1_VIDEO_INPUT2 0x0020 /* VideoInput2 */ ++#define HDMI_HTOP1_TISEMP0_1 0x0024 /* tisemp0-1 */ ++#define HDMI_HTOP1_TISEMP2_C 0x0028 /* tisemp2-c */ ++#define HDMI_HTOP1_TISIDRV 0x002C /* tisidrv */ ++#define HDMI_HTOP1_TISEN 0x0034 /* tisen */ ++#define HDMI_HTOP1_TISDREN 0x0038 /* tisdren */ ++#define HDMI_HTOP1_CISRANGE 0x003C /* cisrange */ ++#define HDMI_HTOP1_ENABLE_SELECTOR 0x0040 /* Enable Selector */ ++#define HDMI_HTOP1_MACRO_RESET 0x0044 /* Macro reset */ ++#define HDMI_HTOP1_PLL_CALIBRATION 0x0048 /* PLL calibration */ ++#define HDMI_HTOP1_RE_CALIBRATION 0x004C /* Re-calibration */ ++#define HDMI_HTOP1_CURRENT 0x0050 /* Current */ ++#define HDMI_HTOP1_PLL_LOCK_DETECT 0x0054 /* PLL lock detect */ ++#define HDMI_HTOP1_PHY_TEST_MODE 0x0058 /* PHY Test Mode */ ++#define HDMI_HTOP1_CLK_SET 0x0080 /* Clock Set */ ++#define HDMI_HTOP1_DDC_FAIL_SAFE 0x0084 /* DDC fail safe */ ++#define HDMI_HTOP1_PRBS 0x0088 /* PRBS */ ++#define HDMI_HTOP1_EDID_AINC_CONTROL 0x008C /* EDID ainc Control */ ++#define HDMI_HTOP1_HTOP_DCL_MODE 0x00FC /* Deep Coloer Mode */ ++#define HDMI_HTOP1_HTOP_DCL_FRC_COEF0 0x0100 /* Deep Color:FRC COEF0 */ ++#define HDMI_HTOP1_HTOP_DCL_FRC_COEF1 0x0104 /* Deep Color:FRC COEF1 */ ++#define HDMI_HTOP1_HTOP_DCL_FRC_COEF2 0x0108 /* Deep Color:FRC COEF2 */ ++#define HDMI_HTOP1_HTOP_DCL_FRC_COEF3 0x010C /* Deep Color:FRC COEF3 */ ++#define HDMI_HTOP1_HTOP_DCL_FRC_COEF0_C 0x0110 /* Deep Color:FRC COEF0C */ ++#define HDMI_HTOP1_HTOP_DCL_FRC_COEF1_C 0x0114 /* Deep Color:FRC COEF1C */ ++#define HDMI_HTOP1_HTOP_DCL_FRC_COEF2_C 0x0118 /* Deep Color:FRC COEF2C */ ++#define HDMI_HTOP1_HTOP_DCL_FRC_COEF3_C 0x011C /* Deep Color:FRC COEF3C */ ++#define HDMI_HTOP1_HTOP_DCL_FRC_MODE 0x0120 /* Deep Color:FRC Mode */ ++#define HDMI_HTOP1_HTOP_DCL_RECT_START1 0x0124 /* Deep Color:Rect Start1 */ ++#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE1 0x0128 /* Deep Color:Rect Size1 */ ++#define HDMI_HTOP1_HTOP_DCL_RECT_START2 0x012C /* Deep Color:Rect Start2 */ ++#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE2 0x0130 /* Deep Color:Rect Size2 */ ++#define HDMI_HTOP1_HTOP_DCL_RECT_START3 0x0134 /* Deep Color:Rect Start3 */ ++#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE3 0x0138 /* Deep Color:Rect Size3 */ ++#define HDMI_HTOP1_HTOP_DCL_RECT_START4 0x013C /* Deep Color:Rect Start4 */ ++#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE4 0x0140 /* Deep Color:Rect Size4 */ ++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_1 0x0144 /* Deep Color:Fil Para Y1_1 */ ++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_2 0x0148 /* Deep Color:Fil Para Y1_2 */ ++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_1 0x014C /* Deep Color:Fil Para CB1_1 */ ++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_2 0x0150 /* Deep Color:Fil Para CB1_2 */ ++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_1 0x0154 /* Deep Color:Fil Para CR1_1 */ ++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_2 0x0158 /* Deep Color:Fil Para CR1_2 */ ++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_1 0x015C /* Deep Color:Fil Para Y2_1 */ ++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_2 0x0160 /* Deep Color:Fil Para Y2_2 */ ++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_1 0x0164 /* Deep Color:Fil Para CB2_1 */ ++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_2 0x0168 /* Deep Color:Fil Para CB2_2 */ ++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_1 0x016C /* Deep Color:Fil Para CR2_1 */ ++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_2 0x0170 /* Deep Color:Fil Para CR2_2 */ ++#define HDMI_HTOP1_HTOP_DCL_COR_PARA_Y1 0x0174 /* Deep Color:Cor Para Y1 */ ++#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CB1 0x0178 /* Deep Color:Cor Para CB1 */ ++#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CR1 0x017C /* Deep Color:Cor Para CR1 */ ++#define HDMI_HTOP1_HTOP_DCL_COR_PARA_Y2 0x0180 /* Deep Color:Cor Para Y2 */ ++#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CB2 0x0184 /* Deep Color:Cor Para CB2 */ ++#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CR2 0x0188 /* Deep Color:Cor Para CR2 */ ++#define HDMI_HTOP1_EDID_DATA_READ 0x0200 /* EDID Data Read 128Byte:0x03FC */ ++ + enum hotplug_state { + HDMI_HOTPLUG_DISCONNECTED, + HDMI_HOTPLUG_CONNECTED, +@@ -211,6 +274,7 @@ struct sh_hdmi { + struct sh_mobile_lcdc_entity entity; + + void __iomem *base; ++ void __iomem *htop1; + enum hotplug_state hp_state; /* hot-plug status */ + u8 preprogrammed_vic; /* use a pre-programmed VIC or + the external mode */ +@@ -271,6 +335,17 @@ static void hdmi_bit_set(struct sh_hdmi *hdmi, u8 mask, u8 data, u8 reg) + hdmi_write(hdmi, val, reg); + } + ++static void hdmi_htop1_write(struct sh_hdmi *hdmi, u32 data, u32 reg) ++{ ++ iowrite32(data, hdmi->htop1 + reg); ++ udelay(100); ++} ++ ++static u32 hdmi_htop1_read(struct sh_hdmi *hdmi, u32 reg) ++{ ++ return ioread32(hdmi->htop1 + reg); ++} ++ + /* + * HDMI sound + */ +@@ -781,7 +856,9 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate, + /* Read EDID */ + dev_dbg(hdmi->dev, "Read back EDID code:"); + for (i = 0; i < 128; i++) { +- edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW); ++ edid[i] = (hdmi->htop1) ? ++ (u8)hdmi_htop1_read(hdmi, HDMI_HTOP1_EDID_DATA_READ + (i * 4)) : ++ hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW); + #ifdef DEBUG + if ((i % 16) == 0) { + printk(KERN_CONT "\n"); +@@ -1145,10 +1222,58 @@ out: + dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, hdmi); + } + ++static void sh_hdmi_htop1_init(struct sh_hdmi *hdmi) ++{ ++ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_MODE); ++ hdmi_htop1_write(hdmi, 0x0000000b, 0x0010); ++ hdmi_htop1_write(hdmi, 0x00006710, HDMI_HTOP1_HTOP_DCL_FRC_MODE); ++ hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_1); ++ hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_2); ++ hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_1); ++ hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_2); ++ hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_1); ++ hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_2); ++ hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_1); ++ hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_2); ++ hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_1); ++ hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_2); ++ hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_1); ++ hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_2); ++ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_Y1); ++ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CB1); ++ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CR1); ++ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_Y2); ++ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CB2); ++ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CR2); ++ hdmi_htop1_write(hdmi, 0x00000008, HDMI_HTOP1_CURRENT); ++ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_TISEMP0_1); ++ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_TISEMP2_C); ++ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_PHY_TEST_MODE); ++ hdmi_htop1_write(hdmi, 0x00000081, HDMI_HTOP1_TISIDRV); ++ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_PLLBW); ++ hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISEN); ++ hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISDREN); ++ hdmi_htop1_write(hdmi, 0x00000003, HDMI_HTOP1_ENABLE_SELECTOR); ++ hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_MACRO_RESET); ++ hdmi_htop1_write(hdmi, 0x00000016, HDMI_HTOP1_CISRANGE); ++ msleep(100); ++ hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_ENABLE_SELECTOR); ++ msleep(100); ++ hdmi_htop1_write(hdmi, 0x00000003, HDMI_HTOP1_ENABLE_SELECTOR); ++ hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_MACRO_RESET); ++ hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISEN); ++ hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISDREN); ++ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_VIDEO_INPUT); ++ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_CLK_TO_PHY); ++ hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_VIDEO_INPUT2); ++ hdmi_htop1_write(hdmi, 0x0000000a, HDMI_HTOP1_CLK_SET); ++} ++ + static int __init sh_hdmi_probe(struct platform_device *pdev) + { + struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ struct resource *htop1_res; + int irq = platform_get_irq(pdev, 0), ret; + struct sh_hdmi *hdmi; + long rate; +@@ -1156,6 +1281,15 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) + if (!res || !pdata || irq < 0) + return -ENODEV; + ++ htop1_res = NULL; ++ if (pdata->flags & HDMI_HAS_HTOP1) { ++ htop1_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (!htop1_res) { ++ dev_err(&pdev->dev, "htop1 needs register base\n"); ++ return -EINVAL; ++ } ++ } ++ + hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL); + if (!hdmi) { + dev_err(&pdev->dev, "Cannot allocate device data\n"); +@@ -1227,6 +1361,17 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) + if (pdata->flags & HDMI_OUTPUT_POLARITY_HI) + hdmi_bit_set(hdmi, 0x01, 0x01, HDMI_SYSTEM_CTRL); + ++ /* enable htop1 register if needed */ ++ if (htop1_res) { ++ hdmi->htop1 = ioremap(htop1_res->start, resource_size(htop1_res)); ++ if (!hdmi->htop1) { ++ dev_err(&pdev->dev, "control register region already claimed\n"); ++ ret = -ENOMEM; ++ goto emap_htop1; ++ } ++ sh_hdmi_htop1_init(hdmi); ++ } ++ + /* Product and revision IDs are 0 in sh-mobile version */ + dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n", + hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID)); +@@ -1250,6 +1395,9 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) + ecodec: + free_irq(irq, hdmi); + ereqirq: ++ if (hdmi->htop1) ++ iounmap(hdmi->htop1); ++emap_htop1: + pm_runtime_put(&pdev->dev); + pm_runtime_disable(&pdev->dev); + iounmap(hdmi->base); +@@ -1281,6 +1429,8 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev) + pm_runtime_disable(&pdev->dev); + clk_disable(hdmi->hdmi_clk); + clk_put(hdmi->hdmi_clk); ++ if (hdmi->htop1) ++ iounmap(hdmi->htop1); + iounmap(hdmi->base); + release_mem_region(res->start, resource_size(res)); + kfree(hdmi); +diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h +index ce8a540..63d20ef 100644 +--- a/include/video/sh_mobile_hdmi.h ++++ b/include/video/sh_mobile_hdmi.h +@@ -38,6 +38,7 @@ struct clk; + + /* Chip specific option */ + #define HDMI_32BIT_REG (1 << 8) ++#define HDMI_HAS_HTOP1 (1 << 9) + + struct sh_mobile_hdmi_info { + unsigned int flags; +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0038-fbdev-sh_mipi_dsi-fix-a-section-mismatch.patch b/patches.armadillo800/0038-fbdev-sh_mipi_dsi-fix-a-section-mismatch.patch new file mode 100644 index 0000000000000..ce1fee549114c --- /dev/null +++ b/patches.armadillo800/0038-fbdev-sh_mipi_dsi-fix-a-section-mismatch.patch @@ -0,0 +1,53 @@ +From 46a0acbafe13b92d4ea16ca47414ac22579f9827 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 14 Jun 2012 09:53:33 +0200 +Subject: fbdev: sh_mipi_dsi: fix a section mismatch + +sh_mipi_setup() is called from a .text function, therefore it cannot be +__init. Additionally, sh_mipi_remove() can be moved to the .devexit.text +section. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +(cherry picked from commit e6765ffa6897f7fb84469bab2e1be885c57ea519) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/video/sh_mipi_dsi.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c +index 4c6b844..3951fda 100644 +--- a/drivers/video/sh_mipi_dsi.c ++++ b/drivers/video/sh_mipi_dsi.c +@@ -127,8 +127,7 @@ static void sh_mipi_shutdown(struct platform_device *pdev) + sh_mipi_dsi_enable(mipi, false); + } + +-static int __init sh_mipi_setup(struct sh_mipi *mipi, +- struct sh_mipi_dsi_info *pdata) ++static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata) + { + void __iomem *base = mipi->base; + struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan; +@@ -551,7 +550,7 @@ efindslot: + return ret; + } + +-static int __exit sh_mipi_remove(struct platform_device *pdev) ++static int __devexit sh_mipi_remove(struct platform_device *pdev) + { + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); +@@ -592,7 +591,7 @@ static int __exit sh_mipi_remove(struct platform_device *pdev) + } + + static struct platform_driver sh_mipi_driver = { +- .remove = __exit_p(sh_mipi_remove), ++ .remove = __devexit_p(sh_mipi_remove), + .shutdown = sh_mipi_shutdown, + .driver = { + .name = "sh-mipi-dsi", +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0039-fbdev-sh_mobile_lcdc-Constify-sh_mobile_lcdc_fix-str.patch b/patches.armadillo800/0039-fbdev-sh_mobile_lcdc-Constify-sh_mobile_lcdc_fix-str.patch new file mode 100644 index 0000000000000..353350200bbce --- /dev/null +++ b/patches.armadillo800/0039-fbdev-sh_mobile_lcdc-Constify-sh_mobile_lcdc_fix-str.patch @@ -0,0 +1,31 @@ +From 285591af450384157206e46d4b676f8a5d095c4a Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Tue, 22 Nov 2011 00:56:58 +0100 +Subject: fbdev: sh_mobile_lcdc: Constify sh_mobile_lcdc_fix structure + +The structure is only read, make it const. + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +(cherry picked from commit 3281e54c80195b90ed12a5b6cddef4ab42e656e1) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/video/sh_mobile_lcdcfb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c +index e672698..5461abe 100644 +--- a/drivers/video/sh_mobile_lcdcfb.c ++++ b/drivers/video/sh_mobile_lcdcfb.c +@@ -1003,7 +1003,7 @@ static int sh_mobile_lcdc_setcolreg(u_int regno, + return 0; + } + +-static struct fb_fix_screeninfo sh_mobile_lcdc_fix = { ++static const struct fb_fix_screeninfo sh_mobile_lcdc_fix = { + .id = "SH Mobile LCDC", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0040-fbdev-sh_mobile_lcdc-Rename-fb-operation-handlers-wi.patch b/patches.armadillo800/0040-fbdev-sh_mobile_lcdc-Rename-fb-operation-handlers-wi.patch new file mode 100644 index 0000000000000..015ce4eaafe4f --- /dev/null +++ b/patches.armadillo800/0040-fbdev-sh_mobile_lcdc-Rename-fb-operation-handlers-wi.patch @@ -0,0 +1,168 @@ +From 2a41d02255f596307db8e41902cfec9877bfe493 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Tue, 22 Nov 2011 00:56:58 +0100 +Subject: fbdev: sh_mobile_lcdc: Rename fb operation handlers with a common + prefix + +Make all fb operation handlers start with sh_mobile_lcdc_ in preparation +for the multi-plane support. + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +(cherry picked from commit d7ad33421863308fe7ddf865737d4d83b64e5b81) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/video/sh_mobile_lcdcfb.c | 48 +++++++++++++++++++++------------------- + 1 file changed, 25 insertions(+), 23 deletions(-) + +diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c +index 5461abe..799f871 100644 +--- a/drivers/video/sh_mobile_lcdcfb.c ++++ b/drivers/video/sh_mobile_lcdcfb.c +@@ -384,8 +384,8 @@ sh_mobile_lcdc_must_reconfigure(struct sh_mobile_lcdc_chan *ch, + return true; + } + +-static int sh_mobile_check_var(struct fb_var_screeninfo *var, +- struct fb_info *info); ++static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, ++ struct fb_info *info); + + static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch, + enum sh_mobile_lcdc_entity_event event, +@@ -439,7 +439,7 @@ static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch, + fb_videomode_to_var(&var, mode); + var.bits_per_pixel = info->var.bits_per_pixel; + var.grayscale = info->var.grayscale; +- ret = sh_mobile_check_var(&var, info); ++ ret = sh_mobile_lcdc_check_var(&var, info); + break; + } + +@@ -585,7 +585,7 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) + return IRQ_HANDLED; + } + +-static int sh_mobile_wait_for_vsync(struct sh_mobile_lcdc_chan *ch) ++static int sh_mobile_lcdc_wait_for_vsync(struct sh_mobile_lcdc_chan *ch) + { + unsigned long ldintr; + int ret; +@@ -686,7 +686,7 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) + } + + /* +- * __sh_mobile_lcdc_start - Configure and tart the LCDC ++ * __sh_mobile_lcdc_start - Configure and start the LCDC + * @priv: LCDC device + * + * Configure all enabled channels and start the LCDC device. All external +@@ -1035,8 +1035,8 @@ static void sh_mobile_lcdc_imageblit(struct fb_info *info, + sh_mobile_lcdc_deferred_io_touch(info); + } + +-static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var, +- struct fb_info *info) ++static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var, ++ struct fb_info *info) + { + struct sh_mobile_lcdc_chan *ch = info->par; + struct sh_mobile_lcdc_priv *priv = ch->lcdc; +@@ -1099,14 +1099,15 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var, + return 0; + } + +-static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd, +- unsigned long arg) ++static int sh_mobile_lcdc_ioctl(struct fb_info *info, unsigned int cmd, ++ unsigned long arg) + { ++ struct sh_mobile_lcdc_chan *ch = info->par; + int retval; + + switch (cmd) { + case FBIO_WAITFORVSYNC: +- retval = sh_mobile_wait_for_vsync(info->par); ++ retval = sh_mobile_lcdc_wait_for_vsync(ch); + break; + + default: +@@ -1158,7 +1159,7 @@ static void sh_mobile_fb_reconfig(struct fb_info *info) + * Locking: both .fb_release() and .fb_open() are called with info->lock held if + * user == 1, or with console sem held, if user == 0. + */ +-static int sh_mobile_release(struct fb_info *info, int user) ++static int sh_mobile_lcdc_release(struct fb_info *info, int user) + { + struct sh_mobile_lcdc_chan *ch = info->par; + +@@ -1179,7 +1180,7 @@ static int sh_mobile_release(struct fb_info *info, int user) + return 0; + } + +-static int sh_mobile_open(struct fb_info *info, int user) ++static int sh_mobile_lcdc_open(struct fb_info *info, int user) + { + struct sh_mobile_lcdc_chan *ch = info->par; + +@@ -1192,7 +1193,8 @@ static int sh_mobile_open(struct fb_info *info, int user) + return 0; + } + +-static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *info) ++static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, ++ struct fb_info *info) + { + struct sh_mobile_lcdc_chan *ch = info->par; + struct sh_mobile_lcdc_priv *p = ch->lcdc; +@@ -1313,7 +1315,7 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in + return 0; + } + +-static int sh_mobile_set_par(struct fb_info *info) ++static int sh_mobile_lcdc_set_par(struct fb_info *info) + { + struct sh_mobile_lcdc_chan *ch = info->par; + int ret; +@@ -1383,8 +1385,8 @@ static int sh_mobile_lcdc_blank(int blank, struct fb_info *info) + * mode will reenable the clocks and update the screen in time, + * so it does not need this. */ + if (!info->fbdefio) { +- sh_mobile_wait_for_vsync(ch); +- sh_mobile_wait_for_vsync(ch); ++ sh_mobile_lcdc_wait_for_vsync(ch); ++ sh_mobile_lcdc_wait_for_vsync(ch); + } + sh_mobile_lcdc_clk_off(p); + } +@@ -1402,12 +1404,12 @@ static struct fb_ops sh_mobile_lcdc_ops = { + .fb_copyarea = sh_mobile_lcdc_copyarea, + .fb_imageblit = sh_mobile_lcdc_imageblit, + .fb_blank = sh_mobile_lcdc_blank, +- .fb_pan_display = sh_mobile_fb_pan_display, +- .fb_ioctl = sh_mobile_ioctl, +- .fb_open = sh_mobile_open, +- .fb_release = sh_mobile_release, +- .fb_check_var = sh_mobile_check_var, +- .fb_set_par = sh_mobile_set_par, ++ .fb_pan_display = sh_mobile_lcdc_pan, ++ .fb_ioctl = sh_mobile_lcdc_ioctl, ++ .fb_open = sh_mobile_lcdc_open, ++ .fb_release = sh_mobile_lcdc_release, ++ .fb_check_var = sh_mobile_lcdc_check_var, ++ .fb_set_par = sh_mobile_lcdc_set_par, + }; + + static void +@@ -1537,7 +1539,7 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch, + else + var->grayscale = ch->format->fourcc; + +- ret = sh_mobile_check_var(var, info); ++ ret = sh_mobile_lcdc_check_var(var, info); + if (ret) + return ret; + +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0041-fbdev-sh_mobile_lcdc-Implement-overlays-support.patch b/patches.armadillo800/0041-fbdev-sh_mobile_lcdc-Implement-overlays-support.patch new file mode 100644 index 0000000000000..85bd66b55ddff --- /dev/null +++ b/patches.armadillo800/0041-fbdev-sh_mobile_lcdc-Implement-overlays-support.patch @@ -0,0 +1,1137 @@ +From ae0b639299213d1d1361aa368c57ee8a3d94214b Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Mon, 12 Dec 2011 18:43:16 +0100 +Subject: fbdev: sh_mobile_lcdc: Implement overlays support + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +(cherry picked from commit c5deac3c9b2284a64326e8799dfe7416bc619c02) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + .../sysfs-devices-platform-sh_mobile_lcdc_fb | 44 + + drivers/video/sh_mobile_lcdcfb.c | 932 +++++++++++++++++++-- + include/video/sh_mobile_lcdc.h | 7 + + 3 files changed, 911 insertions(+), 72 deletions(-) + create mode 100644 Documentation/ABI/testing/sysfs-devices-platform-sh_mobile_lcdc_fb + +diff --git a/Documentation/ABI/testing/sysfs-devices-platform-sh_mobile_lcdc_fb b/Documentation/ABI/testing/sysfs-devices-platform-sh_mobile_lcdc_fb +new file mode 100644 +index 0000000..2107082 +--- /dev/null ++++ b/Documentation/ABI/testing/sysfs-devices-platform-sh_mobile_lcdc_fb +@@ -0,0 +1,44 @@ ++What: /sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_alpha ++Date: May 2012 ++Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com> ++Description: ++ This file is only available on fb[0-9] devices corresponding ++ to overlay planes. ++ ++ Stores the alpha blending value for the overlay. Values range ++ from 0 (transparent) to 255 (opaque). The value is ignored if ++ the mode is not set to Alpha Blending. ++ ++What: /sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_mode ++Date: May 2012 ++Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com> ++Description: ++ This file is only available on fb[0-9] devices corresponding ++ to overlay planes. ++ ++ Selects the composition mode for the overlay. Possible values ++ are ++ ++ 0 - Alpha Blending ++ 1 - ROP3 ++ ++What: /sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_position ++Date: May 2012 ++Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com> ++Description: ++ This file is only available on fb[0-9] devices corresponding ++ to overlay planes. ++ ++ Stores the x,y overlay position on the display in pixels. The ++ position format is `[0-9]+,[0-9]+'. ++ ++What: /sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_rop3 ++Date: May 2012 ++Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com> ++Description: ++ This file is only available on fb[0-9] devices corresponding ++ to overlay planes. ++ ++ Stores the raster operation (ROP3) for the overlay. Values ++ range from 0 to 255. The value is ignored if the mode is not ++ set to ROP3. +diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c +index 799f871..98e81b3 100644 +--- a/drivers/video/sh_mobile_lcdcfb.c ++++ b/drivers/video/sh_mobile_lcdcfb.c +@@ -12,6 +12,7 @@ + #include <linux/backlight.h> + #include <linux/clk.h> + #include <linux/console.h> ++#include <linux/ctype.h> + #include <linux/dma-mapping.h> + #include <linux/delay.h> + #include <linux/gpio.h> +@@ -32,12 +33,176 @@ + + #include "sh_mobile_lcdcfb.h" + ++/* ---------------------------------------------------------------------------- ++ * Overlay register definitions ++ */ ++ ++#define LDBCR 0xb00 ++#define LDBCR_UPC(n) (1 << ((n) + 16)) ++#define LDBCR_UPF(n) (1 << ((n) + 8)) ++#define LDBCR_UPD(n) (1 << ((n) + 0)) ++#define LDBnBSIFR(n) (0xb20 + (n) * 0x20 + 0x00) ++#define LDBBSIFR_EN (1 << 31) ++#define LDBBSIFR_VS (1 << 29) ++#define LDBBSIFR_BRSEL (1 << 28) ++#define LDBBSIFR_MX (1 << 27) ++#define LDBBSIFR_MY (1 << 26) ++#define LDBBSIFR_CV3 (3 << 24) ++#define LDBBSIFR_CV2 (2 << 24) ++#define LDBBSIFR_CV1 (1 << 24) ++#define LDBBSIFR_CV0 (0 << 24) ++#define LDBBSIFR_CV_MASK (3 << 24) ++#define LDBBSIFR_LAY_MASK (0xff << 16) ++#define LDBBSIFR_LAY_SHIFT 16 ++#define LDBBSIFR_ROP3_MASK (0xff << 16) ++#define LDBBSIFR_ROP3_SHIFT 16 ++#define LDBBSIFR_AL_PL8 (3 << 14) ++#define LDBBSIFR_AL_PL1 (2 << 14) ++#define LDBBSIFR_AL_PK (1 << 14) ++#define LDBBSIFR_AL_1 (0 << 14) ++#define LDBBSIFR_AL_MASK (3 << 14) ++#define LDBBSIFR_SWPL (1 << 10) ++#define LDBBSIFR_SWPW (1 << 9) ++#define LDBBSIFR_SWPB (1 << 8) ++#define LDBBSIFR_RY (1 << 7) ++#define LDBBSIFR_CHRR_420 (2 << 0) ++#define LDBBSIFR_CHRR_422 (1 << 0) ++#define LDBBSIFR_CHRR_444 (0 << 0) ++#define LDBBSIFR_RPKF_ARGB32 (0x00 << 0) ++#define LDBBSIFR_RPKF_RGB16 (0x03 << 0) ++#define LDBBSIFR_RPKF_RGB24 (0x0b << 0) ++#define LDBBSIFR_RPKF_MASK (0x1f << 0) ++#define LDBnBSSZR(n) (0xb20 + (n) * 0x20 + 0x04) ++#define LDBBSSZR_BVSS_MASK (0xfff << 16) ++#define LDBBSSZR_BVSS_SHIFT 16 ++#define LDBBSSZR_BHSS_MASK (0xfff << 0) ++#define LDBBSSZR_BHSS_SHIFT 0 ++#define LDBnBLOCR(n) (0xb20 + (n) * 0x20 + 0x08) ++#define LDBBLOCR_CVLC_MASK (0xfff << 16) ++#define LDBBLOCR_CVLC_SHIFT 16 ++#define LDBBLOCR_CHLC_MASK (0xfff << 0) ++#define LDBBLOCR_CHLC_SHIFT 0 ++#define LDBnBSMWR(n) (0xb20 + (n) * 0x20 + 0x0c) ++#define LDBBSMWR_BSMWA_MASK (0xffff << 16) ++#define LDBBSMWR_BSMWA_SHIFT 16 ++#define LDBBSMWR_BSMW_MASK (0xffff << 0) ++#define LDBBSMWR_BSMW_SHIFT 0 ++#define LDBnBSAYR(n) (0xb20 + (n) * 0x20 + 0x10) ++#define LDBBSAYR_FG1A_MASK (0xff << 24) ++#define LDBBSAYR_FG1A_SHIFT 24 ++#define LDBBSAYR_FG1R_MASK (0xff << 16) ++#define LDBBSAYR_FG1R_SHIFT 16 ++#define LDBBSAYR_FG1G_MASK (0xff << 8) ++#define LDBBSAYR_FG1G_SHIFT 8 ++#define LDBBSAYR_FG1B_MASK (0xff << 0) ++#define LDBBSAYR_FG1B_SHIFT 0 ++#define LDBnBSACR(n) (0xb20 + (n) * 0x20 + 0x14) ++#define LDBBSACR_FG2A_MASK (0xff << 24) ++#define LDBBSACR_FG2A_SHIFT 24 ++#define LDBBSACR_FG2R_MASK (0xff << 16) ++#define LDBBSACR_FG2R_SHIFT 16 ++#define LDBBSACR_FG2G_MASK (0xff << 8) ++#define LDBBSACR_FG2G_SHIFT 8 ++#define LDBBSACR_FG2B_MASK (0xff << 0) ++#define LDBBSACR_FG2B_SHIFT 0 ++#define LDBnBSAAR(n) (0xb20 + (n) * 0x20 + 0x18) ++#define LDBBSAAR_AP_MASK (0xff << 24) ++#define LDBBSAAR_AP_SHIFT 24 ++#define LDBBSAAR_R_MASK (0xff << 16) ++#define LDBBSAAR_R_SHIFT 16 ++#define LDBBSAAR_GY_MASK (0xff << 8) ++#define LDBBSAAR_GY_SHIFT 8 ++#define LDBBSAAR_B_MASK (0xff << 0) ++#define LDBBSAAR_B_SHIFT 0 ++#define LDBnBPPCR(n) (0xb20 + (n) * 0x20 + 0x1c) ++#define LDBBPPCR_AP_MASK (0xff << 24) ++#define LDBBPPCR_AP_SHIFT 24 ++#define LDBBPPCR_R_MASK (0xff << 16) ++#define LDBBPPCR_R_SHIFT 16 ++#define LDBBPPCR_GY_MASK (0xff << 8) ++#define LDBBPPCR_GY_SHIFT 8 ++#define LDBBPPCR_B_MASK (0xff << 0) ++#define LDBBPPCR_B_SHIFT 0 ++#define LDBnBBGCL(n) (0xb10 + (n) * 0x04) ++#define LDBBBGCL_BGA_MASK (0xff << 24) ++#define LDBBBGCL_BGA_SHIFT 24 ++#define LDBBBGCL_BGR_MASK (0xff << 16) ++#define LDBBBGCL_BGR_SHIFT 16 ++#define LDBBBGCL_BGG_MASK (0xff << 8) ++#define LDBBBGCL_BGG_SHIFT 8 ++#define LDBBBGCL_BGB_MASK (0xff << 0) ++#define LDBBBGCL_BGB_SHIFT 0 ++ + #define SIDE_B_OFFSET 0x1000 + #define MIRROR_OFFSET 0x2000 + + #define MAX_XRES 1920 + #define MAX_YRES 1080 + ++enum sh_mobile_lcdc_overlay_mode { ++ LCDC_OVERLAY_BLEND, ++ LCDC_OVERLAY_ROP3, ++}; ++ ++/* ++ * struct sh_mobile_lcdc_overlay - LCDC display overlay ++ * ++ * @channel: LCDC channel this overlay belongs to ++ * @cfg: Overlay configuration ++ * @info: Frame buffer device ++ * @index: Overlay index (0-3) ++ * @base: Overlay registers base address ++ * @enabled: True if the overlay is enabled ++ * @mode: Overlay blending mode (alpha blend or ROP3) ++ * @alpha: Global alpha blending value (0-255, for alpha blending mode) ++ * @rop3: Raster operation (for ROP3 mode) ++ * @fb_mem: Frame buffer virtual memory address ++ * @fb_size: Frame buffer size in bytes ++ * @dma_handle: Frame buffer DMA address ++ * @base_addr_y: Overlay base address (RGB or luma component) ++ * @base_addr_c: Overlay base address (chroma component) ++ * @pan_offset: Current pan offset in bytes ++ * @format: Current pixelf format ++ * @xres: Horizontal visible resolution ++ * @xres_virtual: Horizontal total resolution ++ * @yres: Vertical visible resolution ++ * @yres_virtual: Vertical total resolution ++ * @pitch: Overlay line pitch ++ * @pos_x: Horizontal overlay position ++ * @pos_y: Vertical overlay position ++ */ ++struct sh_mobile_lcdc_overlay { ++ struct sh_mobile_lcdc_chan *channel; ++ ++ const struct sh_mobile_lcdc_overlay_cfg *cfg; ++ struct fb_info *info; ++ ++ unsigned int index; ++ unsigned long base; ++ ++ bool enabled; ++ enum sh_mobile_lcdc_overlay_mode mode; ++ unsigned int alpha; ++ unsigned int rop3; ++ ++ void *fb_mem; ++ unsigned long fb_size; ++ ++ dma_addr_t dma_handle; ++ unsigned long base_addr_y; ++ unsigned long base_addr_c; ++ unsigned long pan_offset; ++ ++ const struct sh_mobile_lcdc_format_info *format; ++ unsigned int xres; ++ unsigned int xres_virtual; ++ unsigned int yres; ++ unsigned int yres_virtual; ++ unsigned int pitch; ++ int pos_x; ++ int pos_y; ++}; ++ + struct sh_mobile_lcdc_priv { + void __iomem *base; + int irq; +@@ -45,7 +210,10 @@ struct sh_mobile_lcdc_priv { + struct device *dev; + struct clk *dot_clk; + unsigned long lddckr; ++ + struct sh_mobile_lcdc_chan ch[2]; ++ struct sh_mobile_lcdc_overlay overlays[4]; ++ + struct notifier_block notifier; + int started; + int forced_fourcc; /* 2 channel LCDC must share fourcc setting */ +@@ -141,6 +309,13 @@ static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan, + return ioread32(chan->lcdc->base + chan->reg_offs[reg_nr]); + } + ++static void lcdc_write_overlay(struct sh_mobile_lcdc_overlay *ovl, ++ int reg, unsigned long data) ++{ ++ iowrite32(data, ovl->channel->lcdc->base + reg); ++ iowrite32(data, ovl->channel->lcdc->base + reg + SIDE_B_OFFSET); ++} ++ + static void lcdc_write(struct sh_mobile_lcdc_priv *priv, + unsigned long reg_offs, unsigned long data) + { +@@ -685,6 +860,96 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) + lcdc_write_chan(ch, LDHAJR, tmp); + } + ++static void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl) ++{ ++ u32 format = 0; ++ ++ if (!ovl->enabled) { ++ lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index)); ++ lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), 0); ++ lcdc_write(ovl->channel->lcdc, LDBCR, ++ LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index)); ++ return; ++ } ++ ++ ovl->base_addr_y = ovl->dma_handle; ++ ovl->base_addr_c = ovl->base_addr_y + ovl->xres ++ * ovl->yres_virtual; ++ ++ switch (ovl->mode) { ++ case LCDC_OVERLAY_BLEND: ++ format = LDBBSIFR_EN | (ovl->alpha << LDBBSIFR_LAY_SHIFT); ++ break; ++ ++ case LCDC_OVERLAY_ROP3: ++ format = LDBBSIFR_EN | LDBBSIFR_BRSEL ++ | (ovl->rop3 << LDBBSIFR_ROP3_SHIFT); ++ break; ++ } ++ ++ switch (ovl->format->fourcc) { ++ case V4L2_PIX_FMT_RGB565: ++ case V4L2_PIX_FMT_NV21: ++ case V4L2_PIX_FMT_NV61: ++ case V4L2_PIX_FMT_NV42: ++ format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW; ++ break; ++ case V4L2_PIX_FMT_BGR24: ++ case V4L2_PIX_FMT_NV12: ++ case V4L2_PIX_FMT_NV16: ++ case V4L2_PIX_FMT_NV24: ++ format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW | LDBBSIFR_SWPB; ++ break; ++ case V4L2_PIX_FMT_BGR32: ++ default: ++ format |= LDBBSIFR_SWPL; ++ break; ++ } ++ ++ switch (ovl->format->fourcc) { ++ case V4L2_PIX_FMT_RGB565: ++ format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16; ++ break; ++ case V4L2_PIX_FMT_BGR24: ++ format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24; ++ break; ++ case V4L2_PIX_FMT_BGR32: ++ format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDDFR_PKF_ARGB32; ++ break; ++ case V4L2_PIX_FMT_NV12: ++ case V4L2_PIX_FMT_NV21: ++ format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_420; ++ break; ++ case V4L2_PIX_FMT_NV16: ++ case V4L2_PIX_FMT_NV61: ++ format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_422; ++ break; ++ case V4L2_PIX_FMT_NV24: ++ case V4L2_PIX_FMT_NV42: ++ format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_444; ++ break; ++ } ++ ++ lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index)); ++ ++ lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), format); ++ ++ lcdc_write_overlay(ovl, LDBnBSSZR(ovl->index), ++ (ovl->yres << LDBBSSZR_BVSS_SHIFT) | ++ (ovl->xres << LDBBSSZR_BHSS_SHIFT)); ++ lcdc_write_overlay(ovl, LDBnBLOCR(ovl->index), ++ (ovl->pos_y << LDBBLOCR_CVLC_SHIFT) | ++ (ovl->pos_x << LDBBLOCR_CHLC_SHIFT)); ++ lcdc_write_overlay(ovl, LDBnBSMWR(ovl->index), ++ ovl->pitch << LDBBSMWR_BSMW_SHIFT); ++ ++ lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y); ++ lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c); ++ ++ lcdc_write(ovl->channel->lcdc, LDBCR, ++ LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index)); ++} ++ + /* + * __sh_mobile_lcdc_start - Configure and start the LCDC + * @priv: LCDC device +@@ -892,6 +1157,11 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) + } + } + ++ for (k = 0; k < ARRAY_SIZE(priv->overlays); ++k) { ++ struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[k]; ++ sh_mobile_lcdc_overlay_setup(ovl); ++ } ++ + /* Start the LCDC. */ + __sh_mobile_lcdc_start(priv); + +@@ -975,8 +1245,506 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) + sh_mobile_lcdc_clk_off(priv); + } + ++static int __sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, ++ struct fb_info *info) ++{ ++ if (var->xres > MAX_XRES || var->yres > MAX_YRES) ++ return -EINVAL; ++ ++ /* Make sure the virtual resolution is at least as big as the visible ++ * resolution. ++ */ ++ if (var->xres_virtual < var->xres) ++ var->xres_virtual = var->xres; ++ if (var->yres_virtual < var->yres) ++ var->yres_virtual = var->yres; ++ ++ if (sh_mobile_format_is_fourcc(var)) { ++ const struct sh_mobile_lcdc_format_info *format; ++ ++ format = sh_mobile_format_info(var->grayscale); ++ if (format == NULL) ++ return -EINVAL; ++ var->bits_per_pixel = format->bpp; ++ ++ /* Default to RGB and JPEG color-spaces for RGB and YUV formats ++ * respectively. ++ */ ++ if (!format->yuv) ++ var->colorspace = V4L2_COLORSPACE_SRGB; ++ else if (var->colorspace != V4L2_COLORSPACE_REC709) ++ var->colorspace = V4L2_COLORSPACE_JPEG; ++ } else { ++ if (var->bits_per_pixel <= 16) { /* RGB 565 */ ++ var->bits_per_pixel = 16; ++ var->red.offset = 11; ++ var->red.length = 5; ++ var->green.offset = 5; ++ var->green.length = 6; ++ var->blue.offset = 0; ++ var->blue.length = 5; ++ var->transp.offset = 0; ++ var->transp.length = 0; ++ } else if (var->bits_per_pixel <= 24) { /* RGB 888 */ ++ var->bits_per_pixel = 24; ++ var->red.offset = 16; ++ var->red.length = 8; ++ var->green.offset = 8; ++ var->green.length = 8; ++ var->blue.offset = 0; ++ var->blue.length = 8; ++ var->transp.offset = 0; ++ var->transp.length = 0; ++ } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */ ++ var->bits_per_pixel = 32; ++ var->red.offset = 16; ++ var->red.length = 8; ++ var->green.offset = 8; ++ var->green.length = 8; ++ var->blue.offset = 0; ++ var->blue.length = 8; ++ var->transp.offset = 24; ++ var->transp.length = 8; ++ } else ++ return -EINVAL; ++ ++ var->red.msb_right = 0; ++ var->green.msb_right = 0; ++ var->blue.msb_right = 0; ++ var->transp.msb_right = 0; ++ } ++ ++ /* Make sure we don't exceed our allocated memory. */ ++ if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 > ++ info->fix.smem_len) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++/* ----------------------------------------------------------------------------- ++ * Frame buffer operations - Overlays ++ */ ++ ++static ssize_t ++overlay_alpha_show(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct fb_info *info = dev_get_drvdata(dev); ++ struct sh_mobile_lcdc_overlay *ovl = info->par; ++ ++ return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->alpha); ++} ++ ++static ssize_t ++overlay_alpha_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct fb_info *info = dev_get_drvdata(dev); ++ struct sh_mobile_lcdc_overlay *ovl = info->par; ++ unsigned int alpha; ++ char *endp; ++ ++ alpha = simple_strtoul(buf, &endp, 10); ++ if (isspace(*endp)) ++ endp++; ++ ++ if (endp - buf != count) ++ return -EINVAL; ++ ++ if (alpha > 255) ++ return -EINVAL; ++ ++ if (ovl->alpha != alpha) { ++ ovl->alpha = alpha; ++ ++ if (ovl->mode == LCDC_OVERLAY_BLEND && ovl->enabled) ++ sh_mobile_lcdc_overlay_setup(ovl); ++ } ++ ++ return count; ++} ++ ++static ssize_t ++overlay_mode_show(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct fb_info *info = dev_get_drvdata(dev); ++ struct sh_mobile_lcdc_overlay *ovl = info->par; ++ ++ return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->mode); ++} ++ ++static ssize_t ++overlay_mode_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct fb_info *info = dev_get_drvdata(dev); ++ struct sh_mobile_lcdc_overlay *ovl = info->par; ++ unsigned int mode; ++ char *endp; ++ ++ mode = simple_strtoul(buf, &endp, 10); ++ if (isspace(*endp)) ++ endp++; ++ ++ if (endp - buf != count) ++ return -EINVAL; ++ ++ if (mode != LCDC_OVERLAY_BLEND && mode != LCDC_OVERLAY_ROP3) ++ return -EINVAL; ++ ++ if (ovl->mode != mode) { ++ ovl->mode = mode; ++ ++ if (ovl->enabled) ++ sh_mobile_lcdc_overlay_setup(ovl); ++ } ++ ++ return count; ++} ++ ++static ssize_t ++overlay_position_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct fb_info *info = dev_get_drvdata(dev); ++ struct sh_mobile_lcdc_overlay *ovl = info->par; ++ ++ return scnprintf(buf, PAGE_SIZE, "%d,%d\n", ovl->pos_x, ovl->pos_y); ++} ++ ++static ssize_t ++overlay_position_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct fb_info *info = dev_get_drvdata(dev); ++ struct sh_mobile_lcdc_overlay *ovl = info->par; ++ char *endp; ++ int pos_x; ++ int pos_y; ++ ++ pos_x = simple_strtol(buf, &endp, 10); ++ if (*endp != ',') ++ return -EINVAL; ++ ++ pos_y = simple_strtol(endp + 1, &endp, 10); ++ if (isspace(*endp)) ++ endp++; ++ ++ if (endp - buf != count) ++ return -EINVAL; ++ ++ if (ovl->pos_x != pos_x || ovl->pos_y != pos_y) { ++ ovl->pos_x = pos_x; ++ ovl->pos_y = pos_y; ++ ++ if (ovl->enabled) ++ sh_mobile_lcdc_overlay_setup(ovl); ++ } ++ ++ return count; ++} ++ ++static ssize_t ++overlay_rop3_show(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct fb_info *info = dev_get_drvdata(dev); ++ struct sh_mobile_lcdc_overlay *ovl = info->par; ++ ++ return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->rop3); ++} ++ ++static ssize_t ++overlay_rop3_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct fb_info *info = dev_get_drvdata(dev); ++ struct sh_mobile_lcdc_overlay *ovl = info->par; ++ unsigned int rop3; ++ char *endp; ++ ++ rop3 = !!simple_strtoul(buf, &endp, 10); ++ if (isspace(*endp)) ++ endp++; ++ ++ if (endp - buf != count) ++ return -EINVAL; ++ ++ if (rop3 > 255) ++ return -EINVAL; ++ ++ if (ovl->rop3 != rop3) { ++ ovl->rop3 = rop3; ++ ++ if (ovl->mode == LCDC_OVERLAY_ROP3 && ovl->enabled) ++ sh_mobile_lcdc_overlay_setup(ovl); ++ } ++ ++ return count; ++} ++ ++static const struct device_attribute overlay_sysfs_attrs[] = { ++ __ATTR(ovl_alpha, S_IRUGO|S_IWUSR, ++ overlay_alpha_show, overlay_alpha_store), ++ __ATTR(ovl_mode, S_IRUGO|S_IWUSR, ++ overlay_mode_show, overlay_mode_store), ++ __ATTR(ovl_position, S_IRUGO|S_IWUSR, ++ overlay_position_show, overlay_position_store), ++ __ATTR(ovl_rop3, S_IRUGO|S_IWUSR, ++ overlay_rop3_show, overlay_rop3_store), ++}; ++ ++static const struct fb_fix_screeninfo sh_mobile_lcdc_overlay_fix = { ++ .id = "SH Mobile LCDC", ++ .type = FB_TYPE_PACKED_PIXELS, ++ .visual = FB_VISUAL_TRUECOLOR, ++ .accel = FB_ACCEL_NONE, ++ .xpanstep = 0, ++ .ypanstep = 1, ++ .ywrapstep = 0, ++ .capabilities = FB_CAP_FOURCC, ++}; ++ ++static int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var, ++ struct fb_info *info) ++{ ++ struct sh_mobile_lcdc_overlay *ovl = info->par; ++ unsigned long base_addr_y; ++ unsigned long base_addr_c; ++ unsigned long pan_offset; ++ unsigned long c_offset; ++ ++ if (!ovl->format->yuv) ++ pan_offset = var->yoffset * ovl->pitch ++ + var->xoffset * (ovl->format->bpp / 8); ++ else ++ pan_offset = var->yoffset * ovl->pitch + var->xoffset; ++ ++ if (pan_offset == ovl->pan_offset) ++ return 0; /* No change, do nothing */ ++ ++ /* Set the source address for the next refresh */ ++ base_addr_y = ovl->dma_handle + pan_offset; ++ ++ ovl->base_addr_y = base_addr_y; ++ ovl->base_addr_c = base_addr_y; ++ ++ if (ovl->format->yuv) { ++ /* Set Y offset */ ++ c_offset = var->yoffset * ovl->pitch ++ * (ovl->format->bpp - 8) / 8; ++ base_addr_c = ovl->dma_handle ++ + ovl->xres * ovl->yres_virtual ++ + c_offset; ++ /* Set X offset */ ++ if (ovl->format->fourcc == V4L2_PIX_FMT_NV24) ++ base_addr_c += 2 * var->xoffset; ++ else ++ base_addr_c += var->xoffset; ++ ++ ovl->base_addr_c = base_addr_c; ++ } ++ ++ lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y); ++ lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c); ++ ++ ovl->pan_offset = pan_offset; ++ ++ return 0; ++} ++ ++static int sh_mobile_lcdc_overlay_ioctl(struct fb_info *info, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct sh_mobile_lcdc_overlay *ovl = info->par; ++ ++ switch (cmd) { ++ case FBIO_WAITFORVSYNC: ++ return sh_mobile_lcdc_wait_for_vsync(ovl->channel); ++ ++ default: ++ return -ENOIOCTLCMD; ++ } ++} ++ ++static int sh_mobile_lcdc_overlay_check_var(struct fb_var_screeninfo *var, ++ struct fb_info *info) ++{ ++ return __sh_mobile_lcdc_check_var(var, info); ++} ++ ++static int sh_mobile_lcdc_overlay_set_par(struct fb_info *info) ++{ ++ struct sh_mobile_lcdc_overlay *ovl = info->par; ++ ++ ovl->format = ++ sh_mobile_format_info(sh_mobile_format_fourcc(&info->var)); ++ ++ ovl->xres = info->var.xres; ++ ovl->xres_virtual = info->var.xres_virtual; ++ ovl->yres = info->var.yres; ++ ovl->yres_virtual = info->var.yres_virtual; ++ ++ if (ovl->format->yuv) ++ ovl->pitch = info->var.xres; ++ else ++ ovl->pitch = info->var.xres * ovl->format->bpp / 8; ++ ++ sh_mobile_lcdc_overlay_setup(ovl); ++ ++ info->fix.line_length = ovl->pitch; ++ ++ if (sh_mobile_format_is_fourcc(&info->var)) { ++ info->fix.type = FB_TYPE_FOURCC; ++ info->fix.visual = FB_VISUAL_FOURCC; ++ } else { ++ info->fix.type = FB_TYPE_PACKED_PIXELS; ++ info->fix.visual = FB_VISUAL_TRUECOLOR; ++ } ++ ++ return 0; ++} ++ ++/* Overlay blanking. Disable the overlay when blanked. */ ++static int sh_mobile_lcdc_overlay_blank(int blank, struct fb_info *info) ++{ ++ struct sh_mobile_lcdc_overlay *ovl = info->par; ++ ++ ovl->enabled = !blank; ++ sh_mobile_lcdc_overlay_setup(ovl); ++ ++ /* Prevent the backlight from receiving a blanking event by returning ++ * a non-zero value. ++ */ ++ return 1; ++} ++ ++static struct fb_ops sh_mobile_lcdc_overlay_ops = { ++ .owner = THIS_MODULE, ++ .fb_read = fb_sys_read, ++ .fb_write = fb_sys_write, ++ .fb_fillrect = sys_fillrect, ++ .fb_copyarea = sys_copyarea, ++ .fb_imageblit = sys_imageblit, ++ .fb_blank = sh_mobile_lcdc_overlay_blank, ++ .fb_pan_display = sh_mobile_lcdc_overlay_pan, ++ .fb_ioctl = sh_mobile_lcdc_overlay_ioctl, ++ .fb_check_var = sh_mobile_lcdc_overlay_check_var, ++ .fb_set_par = sh_mobile_lcdc_overlay_set_par, ++}; ++ ++static void ++sh_mobile_lcdc_overlay_fb_unregister(struct sh_mobile_lcdc_overlay *ovl) ++{ ++ struct fb_info *info = ovl->info; ++ ++ if (info == NULL || info->dev == NULL) ++ return; ++ ++ unregister_framebuffer(ovl->info); ++} ++ ++static int __devinit ++sh_mobile_lcdc_overlay_fb_register(struct sh_mobile_lcdc_overlay *ovl) ++{ ++ struct sh_mobile_lcdc_priv *lcdc = ovl->channel->lcdc; ++ struct fb_info *info = ovl->info; ++ unsigned int i; ++ int ret; ++ ++ if (info == NULL) ++ return 0; ++ ++ ret = register_framebuffer(info); ++ if (ret < 0) ++ return ret; ++ ++ dev_info(lcdc->dev, "registered %s/overlay %u as %dx%d %dbpp.\n", ++ dev_name(lcdc->dev), ovl->index, info->var.xres, ++ info->var.yres, info->var.bits_per_pixel); ++ ++ for (i = 0; i < ARRAY_SIZE(overlay_sysfs_attrs); ++i) { ++ ret = device_create_file(info->dev, &overlay_sysfs_attrs[i]); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void ++sh_mobile_lcdc_overlay_fb_cleanup(struct sh_mobile_lcdc_overlay *ovl) ++{ ++ struct fb_info *info = ovl->info; ++ ++ if (info == NULL || info->device == NULL) ++ return; ++ ++ framebuffer_release(info); ++} ++ ++static int __devinit ++sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl) ++{ ++ struct sh_mobile_lcdc_priv *priv = ovl->channel->lcdc; ++ struct fb_var_screeninfo *var; ++ struct fb_info *info; ++ ++ /* Allocate and initialize the frame buffer device. */ ++ info = framebuffer_alloc(0, priv->dev); ++ if (info == NULL) { ++ dev_err(priv->dev, "unable to allocate fb_info\n"); ++ return -ENOMEM; ++ } ++ ++ ovl->info = info; ++ ++ info->flags = FBINFO_FLAG_DEFAULT; ++ info->fbops = &sh_mobile_lcdc_overlay_ops; ++ info->device = priv->dev; ++ info->screen_base = ovl->fb_mem; ++ info->par = ovl; ++ ++ /* Initialize fixed screen information. Restrict pan to 2 lines steps ++ * for NV12 and NV21. ++ */ ++ info->fix = sh_mobile_lcdc_overlay_fix; ++ snprintf(info->fix.id, sizeof(info->fix.id), ++ "SH Mobile LCDC Overlay %u", ovl->index); ++ info->fix.smem_start = ovl->dma_handle; ++ info->fix.smem_len = ovl->fb_size; ++ info->fix.line_length = ovl->pitch; ++ ++ if (ovl->format->yuv) ++ info->fix.visual = FB_VISUAL_FOURCC; ++ else ++ info->fix.visual = FB_VISUAL_TRUECOLOR; ++ ++ if (ovl->format->fourcc == V4L2_PIX_FMT_NV12 || ++ ovl->format->fourcc == V4L2_PIX_FMT_NV21) ++ info->fix.ypanstep = 2; ++ ++ /* Initialize variable screen information. */ ++ var = &info->var; ++ memset(var, 0, sizeof(*var)); ++ var->xres = ovl->xres; ++ var->yres = ovl->yres; ++ var->xres_virtual = ovl->xres_virtual; ++ var->yres_virtual = ovl->yres_virtual; ++ var->activate = FB_ACTIVATE_NOW; ++ ++ /* Use the legacy API by default for RGB formats, and the FOURCC API ++ * for YUV formats. ++ */ ++ if (!ovl->format->yuv) ++ var->bits_per_pixel = ovl->format->bpp; ++ else ++ var->grayscale = ovl->format->fourcc; ++ ++ return sh_mobile_lcdc_overlay_check_var(var, info); ++} ++ + /* ----------------------------------------------------------------------------- +- * Frame buffer operations ++ * Frame buffer operations - main frame buffer + */ + + static int sh_mobile_lcdc_setcolreg(u_int regno, +@@ -1202,9 +1970,7 @@ static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, + unsigned int best_xres = 0; + unsigned int best_yres = 0; + unsigned int i; +- +- if (var->xres > MAX_XRES || var->yres > MAX_YRES) +- return -EINVAL; ++ int ret; + + /* If board code provides us with a list of available modes, make sure + * we use one of them. Find the mode closest to the requested one. The +@@ -1239,73 +2005,9 @@ static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, + var->yres = best_yres; + } + +- /* Make sure the virtual resolution is at least as big as the visible +- * resolution. +- */ +- if (var->xres_virtual < var->xres) +- var->xres_virtual = var->xres; +- if (var->yres_virtual < var->yres) +- var->yres_virtual = var->yres; +- +- if (sh_mobile_format_is_fourcc(var)) { +- const struct sh_mobile_lcdc_format_info *format; +- +- format = sh_mobile_format_info(var->grayscale); +- if (format == NULL) +- return -EINVAL; +- var->bits_per_pixel = format->bpp; +- +- /* Default to RGB and JPEG color-spaces for RGB and YUV formats +- * respectively. +- */ +- if (!format->yuv) +- var->colorspace = V4L2_COLORSPACE_SRGB; +- else if (var->colorspace != V4L2_COLORSPACE_REC709) +- var->colorspace = V4L2_COLORSPACE_JPEG; +- } else { +- if (var->bits_per_pixel <= 16) { /* RGB 565 */ +- var->bits_per_pixel = 16; +- var->red.offset = 11; +- var->red.length = 5; +- var->green.offset = 5; +- var->green.length = 6; +- var->blue.offset = 0; +- var->blue.length = 5; +- var->transp.offset = 0; +- var->transp.length = 0; +- } else if (var->bits_per_pixel <= 24) { /* RGB 888 */ +- var->bits_per_pixel = 24; +- var->red.offset = 16; +- var->red.length = 8; +- var->green.offset = 8; +- var->green.length = 8; +- var->blue.offset = 0; +- var->blue.length = 8; +- var->transp.offset = 0; +- var->transp.length = 0; +- } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */ +- var->bits_per_pixel = 32; +- var->red.offset = 16; +- var->red.length = 8; +- var->green.offset = 8; +- var->green.length = 8; +- var->blue.offset = 0; +- var->blue.length = 8; +- var->transp.offset = 24; +- var->transp.length = 8; +- } else +- return -EINVAL; +- +- var->red.msb_right = 0; +- var->green.msb_right = 0; +- var->blue.msb_right = 0; +- var->transp.msb_right = 0; +- } +- +- /* Make sure we don't exceed our allocated memory. */ +- if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 > +- info->fix.smem_len) +- return -EINVAL; ++ ret = __sh_mobile_lcdc_check_var(var, info); ++ if (ret < 0) ++ return ret; + + /* only accept the forced_fourcc for dual channel configurations */ + if (p->forced_fourcc && +@@ -1714,15 +2416,27 @@ static const struct fb_videomode default_720p __devinitconst = { + static int sh_mobile_lcdc_remove(struct platform_device *pdev) + { + struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); +- int i; ++ unsigned int i; + + fb_unregister_client(&priv->notifier); + ++ for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) ++ sh_mobile_lcdc_overlay_fb_unregister(&priv->overlays[i]); + for (i = 0; i < ARRAY_SIZE(priv->ch); i++) + sh_mobile_lcdc_channel_fb_unregister(&priv->ch[i]); + + sh_mobile_lcdc_stop(priv); + ++ for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) { ++ struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i]; ++ ++ sh_mobile_lcdc_overlay_fb_cleanup(ovl); ++ ++ if (ovl->fb_mem) ++ dma_free_coherent(&pdev->dev, ovl->fb_size, ++ ovl->fb_mem, ovl->dma_handle); ++ } ++ + for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { + struct sh_mobile_lcdc_chan *ch = &priv->ch[i]; + +@@ -1798,6 +2512,61 @@ static int __devinit sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan * + } + + static int __devinit ++sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv, ++ struct sh_mobile_lcdc_overlay *ovl) ++{ ++ const struct sh_mobile_lcdc_format_info *format; ++ int ret; ++ ++ if (ovl->cfg->fourcc == 0) ++ return 0; ++ ++ /* Validate the format. */ ++ format = sh_mobile_format_info(ovl->cfg->fourcc); ++ if (format == NULL) { ++ dev_err(priv->dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc); ++ return -EINVAL; ++ } ++ ++ ovl->enabled = false; ++ ovl->mode = LCDC_OVERLAY_BLEND; ++ ovl->alpha = 255; ++ ovl->rop3 = 0; ++ ovl->pos_x = 0; ++ ovl->pos_y = 0; ++ ++ /* The default Y virtual resolution is twice the panel size to allow for ++ * double-buffering. ++ */ ++ ovl->format = format; ++ ovl->xres = ovl->cfg->max_xres; ++ ovl->xres_virtual = ovl->xres; ++ ovl->yres = ovl->cfg->max_yres; ++ ovl->yres_virtual = ovl->yres * 2; ++ ++ if (!format->yuv) ++ ovl->pitch = ovl->xres * format->bpp / 8; ++ else ++ ovl->pitch = ovl->xres; ++ ++ /* Allocate frame buffer memory. */ ++ ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres ++ * format->bpp / 8 * 2; ++ ovl->fb_mem = dma_alloc_coherent(priv->dev, ovl->fb_size, ++ &ovl->dma_handle, GFP_KERNEL); ++ if (!ovl->fb_mem) { ++ dev_err(priv->dev, "unable to allocate buffer\n"); ++ return -ENOMEM; ++ } ++ ++ ret = sh_mobile_lcdc_overlay_fb_init(ovl); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int __devinit + sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv, + struct sh_mobile_lcdc_chan *ch) + { +@@ -2005,6 +2774,17 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) + goto err1; + } + ++ for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) { ++ struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i]; ++ ++ ovl->cfg = &pdata->overlays[i]; ++ ovl->channel = &priv->ch[0]; ++ ++ error = sh_mobile_lcdc_overlay_init(priv, ovl); ++ if (error) ++ goto err1; ++ } ++ + error = sh_mobile_lcdc_start(priv); + if (error) { + dev_err(&pdev->dev, "unable to start hardware\n"); +@@ -2019,6 +2799,14 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) + goto err1; + } + ++ for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) { ++ struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i]; ++ ++ error = sh_mobile_lcdc_overlay_fb_register(ovl); ++ if (error) ++ goto err1; ++ } ++ + /* Failure ignored */ + priv->notifier.notifier_call = sh_mobile_lcdc_notify; + fb_register_client(&priv->notifier); +diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h +index 7571b27..ff43ffc 100644 +--- a/include/video/sh_mobile_lcdc.h ++++ b/include/video/sh_mobile_lcdc.h +@@ -166,6 +166,12 @@ struct sh_mobile_lcdc_bl_info { + int (*get_brightness)(void); + }; + ++struct sh_mobile_lcdc_overlay_cfg { ++ int fourcc; ++ unsigned int max_xres; ++ unsigned int max_yres; ++}; ++ + struct sh_mobile_lcdc_chan_cfg { + int chan; + int fourcc; +@@ -186,6 +192,7 @@ struct sh_mobile_lcdc_chan_cfg { + struct sh_mobile_lcdc_info { + int clock_source; + struct sh_mobile_lcdc_chan_cfg ch[2]; ++ struct sh_mobile_lcdc_overlay_cfg overlays[4]; + struct sh_mobile_meram_info *meram_dev; + }; + +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0042-sh_mobile_meram-Rename-operations-to-cache_-alloc-fr.patch b/patches.armadillo800/0042-sh_mobile_meram-Rename-operations-to-cache_-alloc-fr.patch new file mode 100644 index 0000000000000..84b5cc703c4c6 --- /dev/null +++ b/patches.armadillo800/0042-sh_mobile_meram-Rename-operations-to-cache_-alloc-fr.patch @@ -0,0 +1,425 @@ +From 5175271a2ba2d97d73adadcaca3ba6b6616b6f23 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Thu, 15 Mar 2012 12:40:47 +0100 +Subject: sh_mobile_meram: Rename operations to cache_[alloc|free|update] + +The MERAM operations meram_register, meram_unregister and meram_update +handle LCDC cache. In preparation for "raw" MERAM allocation, rename +them to more appropriate names. + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +(cherry picked from commit 4a2371772146b30113c9c837eb32b64f18376c0d) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/video/sh_mobile_lcdcfb.c | 32 ++++--- + drivers/video/sh_mobile_lcdcfb.h | 2 +- + drivers/video/sh_mobile_meram.c | 176 +++++++++++++++++++-------------------- + include/video/sh_mobile_meram.h | 21 ++--- + 4 files changed, 110 insertions(+), 121 deletions(-) + +diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c +index 98e81b3..e593e81 100644 +--- a/drivers/video/sh_mobile_lcdcfb.c ++++ b/drivers/video/sh_mobile_lcdcfb.c +@@ -1104,7 +1104,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) + /* Compute frame buffer base address and pitch for each channel. */ + for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { + int pixelformat; +- void *meram; ++ void *cache; + + ch = &priv->ch[k]; + if (!ch->enabled) +@@ -1119,12 +1119,10 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) + ch->cfg->meram_cfg == NULL) + continue; + +- /* we need to de-init configured ICBs before we can +- * re-initialize them. +- */ +- if (ch->meram) { +- mdev->ops->meram_unregister(mdev, ch->meram); +- ch->meram = NULL; ++ /* Free the allocated MERAM cache. */ ++ if (ch->cache) { ++ mdev->ops->cache_free(mdev, ch->cache); ++ ch->cache = NULL; + } + + switch (ch->format->fourcc) { +@@ -1146,14 +1144,14 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) + break; + } + +- meram = mdev->ops->meram_register(mdev, ch->cfg->meram_cfg, ++ cache = mdev->ops->cache_alloc(mdev, ch->cfg->meram_cfg, + ch->pitch, ch->yres, pixelformat, + &ch->line_size); +- if (!IS_ERR(meram)) { +- mdev->ops->meram_update(mdev, meram, ++ if (!IS_ERR(cache)) { ++ mdev->ops->cache_update(mdev, cache, + ch->base_addr_y, ch->base_addr_c, + &ch->base_addr_y, &ch->base_addr_c); +- ch->meram = meram; ++ ch->cache = cache; + } + } + +@@ -1223,12 +1221,12 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) + + sh_mobile_lcdc_display_off(ch); + +- /* disable the meram */ +- if (ch->meram) { ++ /* Free the MERAM cache. */ ++ if (ch->cache) { + struct sh_mobile_meram_info *mdev; + mdev = priv->meram_dev; +- mdev->ops->meram_unregister(mdev, ch->meram); +- ch->meram = 0; ++ mdev->ops->cache_free(mdev, ch->cache); ++ ch->cache = 0; + } + + } +@@ -1839,11 +1837,11 @@ static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var, + base_addr_c += var->xoffset; + } + +- if (ch->meram) { ++ if (ch->cache) { + struct sh_mobile_meram_info *mdev; + + mdev = priv->meram_dev; +- mdev->ops->meram_update(mdev, ch->meram, ++ mdev->ops->cache_update(mdev, ch->cache, + base_addr_y, base_addr_c, + &base_addr_y, &base_addr_c); + } +diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h +index 5c3bddd..e53cd11 100644 +--- a/drivers/video/sh_mobile_lcdcfb.h ++++ b/drivers/video/sh_mobile_lcdcfb.h +@@ -59,7 +59,7 @@ struct sh_mobile_lcdc_chan { + unsigned long *reg_offs; + unsigned long ldmt1r_value; + unsigned long enabled; /* ME and SE in LDCNT2R */ +- void *meram; ++ void *cache; + + struct mutex open_lock; /* protects the use counter */ + int use_count; +diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c +index 82ba830..4aa3fcb 100644 +--- a/drivers/video/sh_mobile_meram.c ++++ b/drivers/video/sh_mobile_meram.c +@@ -194,13 +194,13 @@ static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off) + } + + /* ----------------------------------------------------------------------------- +- * Allocation ++ * LCDC cache planes allocation, init, cleanup and free + */ + + /* Allocate ICBs and MERAM for a plane. */ +-static int __meram_alloc(struct sh_mobile_meram_priv *priv, +- struct sh_mobile_meram_fb_plane *plane, +- size_t size) ++static int meram_plane_alloc(struct sh_mobile_meram_priv *priv, ++ struct sh_mobile_meram_fb_plane *plane, ++ size_t size) + { + unsigned long mem; + unsigned long idx; +@@ -229,8 +229,8 @@ static int __meram_alloc(struct sh_mobile_meram_priv *priv, + } + + /* Free ICBs and MERAM for a plane. */ +-static void __meram_free(struct sh_mobile_meram_priv *priv, +- struct sh_mobile_meram_fb_plane *plane) ++static void meram_plane_free(struct sh_mobile_meram_priv *priv, ++ struct sh_mobile_meram_fb_plane *plane) + { + gen_pool_free(priv->pool, priv->meram + plane->marker->offset, + plane->marker->size * 1024); +@@ -248,62 +248,6 @@ static int is_nvcolor(int cspace) + return 0; + } + +-/* Allocate memory for the ICBs and mark them as used. */ +-static struct sh_mobile_meram_fb_cache * +-meram_alloc(struct sh_mobile_meram_priv *priv, +- const struct sh_mobile_meram_cfg *cfg, +- int pixelformat) +-{ +- struct sh_mobile_meram_fb_cache *cache; +- unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1; +- int ret; +- +- if (cfg->icb[0].meram_size == 0) +- return ERR_PTR(-EINVAL); +- +- if (nplanes == 2 && cfg->icb[1].meram_size == 0) +- return ERR_PTR(-EINVAL); +- +- cache = kzalloc(sizeof(*cache), GFP_KERNEL); +- if (cache == NULL) +- return ERR_PTR(-ENOMEM); +- +- cache->nplanes = nplanes; +- +- ret = __meram_alloc(priv, &cache->planes[0], cfg->icb[0].meram_size); +- if (ret < 0) +- goto error; +- +- cache->planes[0].marker->current_reg = 1; +- cache->planes[0].marker->pixelformat = pixelformat; +- +- if (cache->nplanes == 1) +- return cache; +- +- ret = __meram_alloc(priv, &cache->planes[1], cfg->icb[1].meram_size); +- if (ret < 0) { +- __meram_free(priv, &cache->planes[0]); +- goto error; +- } +- +- return cache; +- +-error: +- kfree(cache); +- return ERR_PTR(-ENOMEM); +-} +- +-/* Unmark the specified ICB as used. */ +-static void meram_free(struct sh_mobile_meram_priv *priv, +- struct sh_mobile_meram_fb_cache *cache) +-{ +- __meram_free(priv, &cache->planes[0]); +- if (cache->nplanes == 2) +- __meram_free(priv, &cache->planes[1]); +- +- kfree(cache); +-} +- + /* Set the next address to fetch. */ + static void meram_set_next_addr(struct sh_mobile_meram_priv *priv, + struct sh_mobile_meram_fb_cache *cache, +@@ -355,10 +299,10 @@ meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata, + (((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1)) + + /* Initialize MERAM. */ +-static int meram_init(struct sh_mobile_meram_priv *priv, +- struct sh_mobile_meram_fb_plane *plane, +- unsigned int xres, unsigned int yres, +- unsigned int *out_pitch) ++static int meram_plane_init(struct sh_mobile_meram_priv *priv, ++ struct sh_mobile_meram_fb_plane *plane, ++ unsigned int xres, unsigned int yres, ++ unsigned int *out_pitch) + { + struct sh_mobile_meram_icb *marker = plane->marker; + unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres); +@@ -427,8 +371,8 @@ static int meram_init(struct sh_mobile_meram_priv *priv, + return 0; + } + +-static void meram_deinit(struct sh_mobile_meram_priv *priv, +- struct sh_mobile_meram_fb_plane *plane) ++static void meram_plane_cleanup(struct sh_mobile_meram_priv *priv, ++ struct sh_mobile_meram_fb_plane *plane) + { + /* disable ICB */ + meram_write_icb(priv->base, plane->cache->index, MExxCTL, +@@ -441,18 +385,60 @@ static void meram_deinit(struct sh_mobile_meram_priv *priv, + } + + /* ----------------------------------------------------------------------------- +- * Registration/unregistration ++ * LCDC cache operations + */ + +-static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata, +- const struct sh_mobile_meram_cfg *cfg, +- unsigned int xres, unsigned int yres, +- unsigned int pixelformat, +- unsigned int *pitch) ++/* Allocate memory for the ICBs and mark them as used. */ ++static struct sh_mobile_meram_fb_cache * ++meram_cache_alloc(struct sh_mobile_meram_priv *priv, ++ const struct sh_mobile_meram_cfg *cfg, ++ int pixelformat) ++{ ++ unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1; ++ struct sh_mobile_meram_fb_cache *cache; ++ int ret; ++ ++ cache = kzalloc(sizeof(*cache), GFP_KERNEL); ++ if (cache == NULL) ++ return ERR_PTR(-ENOMEM); ++ ++ cache->nplanes = nplanes; ++ ++ ret = meram_plane_alloc(priv, &cache->planes[0], ++ cfg->icb[0].meram_size); ++ if (ret < 0) ++ goto error; ++ ++ cache->planes[0].marker->current_reg = 1; ++ cache->planes[0].marker->pixelformat = pixelformat; ++ ++ if (cache->nplanes == 1) ++ return cache; ++ ++ ret = meram_plane_alloc(priv, &cache->planes[1], ++ cfg->icb[1].meram_size); ++ if (ret < 0) { ++ meram_plane_free(priv, &cache->planes[0]); ++ goto error; ++ } ++ ++ return cache; ++ ++error: ++ kfree(cache); ++ return ERR_PTR(-ENOMEM); ++} ++ ++static void *sh_mobile_cache_alloc(struct sh_mobile_meram_info *pdata, ++ const struct sh_mobile_meram_cfg *cfg, ++ unsigned int xres, unsigned int yres, ++ unsigned int pixelformat, ++ unsigned int *pitch) + { + struct sh_mobile_meram_fb_cache *cache; + struct sh_mobile_meram_priv *priv = pdata->priv; + struct platform_device *pdev = pdata->pdev; ++ unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1; + unsigned int out_pitch; + + if (pixelformat != SH_MOBILE_MERAM_PF_NV && +@@ -469,10 +455,16 @@ static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata, + return ERR_PTR(-EINVAL); + } + ++ if (cfg->icb[0].meram_size == 0) ++ return ERR_PTR(-EINVAL); ++ ++ if (nplanes == 2 && cfg->icb[1].meram_size == 0) ++ return ERR_PTR(-EINVAL); ++ + mutex_lock(&priv->lock); + + /* We now register the ICBs and allocate the MERAM regions. */ +- cache = meram_alloc(priv, cfg, pixelformat); ++ cache = meram_cache_alloc(priv, cfg, pixelformat); + if (IS_ERR(cache)) { + dev_err(&pdev->dev, "MERAM allocation failed (%ld).", + PTR_ERR(cache)); +@@ -480,14 +472,14 @@ static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata, + } + + /* initialize MERAM */ +- meram_init(priv, &cache->planes[0], xres, yres, &out_pitch); ++ meram_plane_init(priv, &cache->planes[0], xres, yres, &out_pitch); + *pitch = out_pitch; + if (pixelformat == SH_MOBILE_MERAM_PF_NV) +- meram_init(priv, &cache->planes[1], xres, (yres + 1) / 2, +- &out_pitch); ++ meram_plane_init(priv, &cache->planes[1], ++ xres, (yres + 1) / 2, &out_pitch); + else if (pixelformat == SH_MOBILE_MERAM_PF_NV24) +- meram_init(priv, &cache->planes[1], 2 * xres, (yres + 1) / 2, +- &out_pitch); ++ meram_plane_init(priv, &cache->planes[1], ++ 2 * xres, (yres + 1) / 2, &out_pitch); + + err: + mutex_unlock(&priv->lock); +@@ -495,25 +487,29 @@ err: + } + + static void +-sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata, void *data) ++sh_mobile_cache_free(struct sh_mobile_meram_info *pdata, void *data) + { + struct sh_mobile_meram_fb_cache *cache = data; + struct sh_mobile_meram_priv *priv = pdata->priv; + + mutex_lock(&priv->lock); + +- /* deinit & free */ +- meram_deinit(priv, &cache->planes[0]); +- if (cache->nplanes == 2) +- meram_deinit(priv, &cache->planes[1]); ++ /* Cleanup and free. */ ++ meram_plane_cleanup(priv, &cache->planes[0]); ++ meram_plane_free(priv, &cache->planes[0]); + +- meram_free(priv, cache); ++ if (cache->nplanes == 2) { ++ meram_plane_cleanup(priv, &cache->planes[1]); ++ meram_plane_free(priv, &cache->planes[1]); ++ } ++ ++ kfree(cache); + + mutex_unlock(&priv->lock); + } + + static void +-sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, void *data, ++sh_mobile_cache_update(struct sh_mobile_meram_info *pdata, void *data, + unsigned long base_addr_y, unsigned long base_addr_c, + unsigned long *icb_addr_y, unsigned long *icb_addr_c) + { +@@ -530,9 +526,9 @@ sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, void *data, + + static struct sh_mobile_meram_ops sh_mobile_meram_ops = { + .module = THIS_MODULE, +- .meram_register = sh_mobile_meram_register, +- .meram_unregister = sh_mobile_meram_unregister, +- .meram_update = sh_mobile_meram_update, ++ .cache_alloc = sh_mobile_cache_alloc, ++ .cache_free = sh_mobile_cache_free, ++ .cache_update = sh_mobile_cache_update, + }; + + /* ----------------------------------------------------------------------------- +diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h +index 29b2fd3..8a5afaf 100644 +--- a/include/video/sh_mobile_meram.h ++++ b/include/video/sh_mobile_meram.h +@@ -41,19 +41,14 @@ struct sh_mobile_meram_cfg { + struct module; + struct sh_mobile_meram_ops { + struct module *module; +- /* register usage of meram */ +- void *(*meram_register)(struct sh_mobile_meram_info *meram_dev, +- const struct sh_mobile_meram_cfg *cfg, +- unsigned int xres, unsigned int yres, +- unsigned int pixelformat, +- unsigned int *pitch); +- +- /* unregister usage of meram */ +- void (*meram_unregister)(struct sh_mobile_meram_info *meram_dev, +- void *data); +- +- /* update meram settings */ +- void (*meram_update)(struct sh_mobile_meram_info *meram_dev, void *data, ++ ++ /* LCDC cache management */ ++ void *(*cache_alloc)(struct sh_mobile_meram_info *meram_dev, ++ const struct sh_mobile_meram_cfg *cfg, ++ unsigned int xres, unsigned int yres, ++ unsigned int pixelformat, unsigned int *pitch); ++ void (*cache_free)(struct sh_mobile_meram_info *meram_dev, void *data); ++ void (*cache_update)(struct sh_mobile_meram_info *meram_dev, void *data, + unsigned long base_addr_y, + unsigned long base_addr_c, + unsigned long *icb_addr_y, +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0043-sh_mobile_meram-Use-direct-function-calls-for-the-pu.patch b/patches.armadillo800/0043-sh_mobile_meram-Use-direct-function-calls-for-the-pu.patch new file mode 100644 index 0000000000000..64653c1fbaa3a --- /dev/null +++ b/patches.armadillo800/0043-sh_mobile_meram-Use-direct-function-calls-for-the-pu.patch @@ -0,0 +1,265 @@ +From b8fe39bce6f2c38cfa04299077173aff50600687 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Thu, 15 Mar 2012 12:40:47 +0100 +Subject: sh_mobile_meram: Use direct function calls for the public API + +There's no reason to use abstract operation pointers to implement the +MERAM API. Replace them by direct function calls. + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +(cherry picked from commit 6e729b416b44296f5ed503b40ac58c2bffb43caf) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/video/sh_mobile_lcdcfb.c | 27 ++++++++-------------- + drivers/video/sh_mobile_meram.c | 40 ++++++++++++++++---------------- + include/video/sh_mobile_meram.h | 50 ++++++++++++++++++++++++++++------------ + 3 files changed, 65 insertions(+), 52 deletions(-) + +diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c +index e593e81..9da4b1b6 100644 +--- a/drivers/video/sh_mobile_lcdcfb.c ++++ b/drivers/video/sh_mobile_lcdcfb.c +@@ -1115,13 +1115,12 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) + ch->line_size = ch->pitch; + + /* Enable MERAM if possible. */ +- if (mdev == NULL || mdev->ops == NULL || +- ch->cfg->meram_cfg == NULL) ++ if (mdev == NULL || ch->cfg->meram_cfg == NULL) + continue; + + /* Free the allocated MERAM cache. */ + if (ch->cache) { +- mdev->ops->cache_free(mdev, ch->cache); ++ sh_mobile_meram_cache_free(mdev, ch->cache); + ch->cache = NULL; + } + +@@ -1144,11 +1143,11 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) + break; + } + +- cache = mdev->ops->cache_alloc(mdev, ch->cfg->meram_cfg, ++ cache = sh_mobile_meram_cache_alloc(mdev, ch->cfg->meram_cfg, + ch->pitch, ch->yres, pixelformat, + &ch->line_size); + if (!IS_ERR(cache)) { +- mdev->ops->cache_update(mdev, cache, ++ sh_mobile_meram_cache_update(mdev, cache, + ch->base_addr_y, ch->base_addr_c, + &ch->base_addr_y, &ch->base_addr_c); + ch->cache = cache; +@@ -1223,9 +1222,7 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) + + /* Free the MERAM cache. */ + if (ch->cache) { +- struct sh_mobile_meram_info *mdev; +- mdev = priv->meram_dev; +- mdev->ops->cache_free(mdev, ch->cache); ++ sh_mobile_meram_cache_free(priv->meram_dev, ch->cache); + ch->cache = 0; + } + +@@ -1808,7 +1805,7 @@ static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var, + struct sh_mobile_lcdc_priv *priv = ch->lcdc; + unsigned long ldrcntr; + unsigned long new_pan_offset; +- unsigned long base_addr_y, base_addr_c; ++ unsigned long base_addr_y, base_addr_c = 0; + unsigned long c_offset; + + if (!ch->format->yuv) +@@ -1837,14 +1834,10 @@ static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var, + base_addr_c += var->xoffset; + } + +- if (ch->cache) { +- struct sh_mobile_meram_info *mdev; +- +- mdev = priv->meram_dev; +- mdev->ops->cache_update(mdev, ch->cache, +- base_addr_y, base_addr_c, +- &base_addr_y, &base_addr_c); +- } ++ if (ch->cache) ++ sh_mobile_meram_cache_update(priv->meram_dev, ch->cache, ++ base_addr_y, base_addr_c, ++ &base_addr_y, &base_addr_c); + + ch->base_addr_y = base_addr_y; + ch->base_addr_c = base_addr_c; +diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c +index 4aa3fcb..fdb6fc1 100644 +--- a/drivers/video/sh_mobile_meram.c ++++ b/drivers/video/sh_mobile_meram.c +@@ -11,6 +11,7 @@ + + #include <linux/device.h> + #include <linux/err.h> ++#include <linux/export.h> + #include <linux/genalloc.h> + #include <linux/io.h> + #include <linux/kernel.h> +@@ -429,11 +430,10 @@ error: + return ERR_PTR(-ENOMEM); + } + +-static void *sh_mobile_cache_alloc(struct sh_mobile_meram_info *pdata, +- const struct sh_mobile_meram_cfg *cfg, +- unsigned int xres, unsigned int yres, +- unsigned int pixelformat, +- unsigned int *pitch) ++void *sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *pdata, ++ const struct sh_mobile_meram_cfg *cfg, ++ unsigned int xres, unsigned int yres, ++ unsigned int pixelformat, unsigned int *pitch) + { + struct sh_mobile_meram_fb_cache *cache; + struct sh_mobile_meram_priv *priv = pdata->priv; +@@ -441,6 +441,9 @@ static void *sh_mobile_cache_alloc(struct sh_mobile_meram_info *pdata, + unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1; + unsigned int out_pitch; + ++ if (priv == NULL) ++ return ERR_PTR(-ENODEV); ++ + if (pixelformat != SH_MOBILE_MERAM_PF_NV && + pixelformat != SH_MOBILE_MERAM_PF_NV24 && + pixelformat != SH_MOBILE_MERAM_PF_RGB) +@@ -485,9 +488,10 @@ err: + mutex_unlock(&priv->lock); + return cache; + } ++EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_alloc); + +-static void +-sh_mobile_cache_free(struct sh_mobile_meram_info *pdata, void *data) ++void ++sh_mobile_meram_cache_free(struct sh_mobile_meram_info *pdata, void *data) + { + struct sh_mobile_meram_fb_cache *cache = data; + struct sh_mobile_meram_priv *priv = pdata->priv; +@@ -507,11 +511,14 @@ sh_mobile_cache_free(struct sh_mobile_meram_info *pdata, void *data) + + mutex_unlock(&priv->lock); + } +- +-static void +-sh_mobile_cache_update(struct sh_mobile_meram_info *pdata, void *data, +- unsigned long base_addr_y, unsigned long base_addr_c, +- unsigned long *icb_addr_y, unsigned long *icb_addr_c) ++EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_free); ++ ++void ++sh_mobile_meram_cache_update(struct sh_mobile_meram_info *pdata, void *data, ++ unsigned long base_addr_y, ++ unsigned long base_addr_c, ++ unsigned long *icb_addr_y, ++ unsigned long *icb_addr_c) + { + struct sh_mobile_meram_fb_cache *cache = data; + struct sh_mobile_meram_priv *priv = pdata->priv; +@@ -523,13 +530,7 @@ sh_mobile_cache_update(struct sh_mobile_meram_info *pdata, void *data, + + mutex_unlock(&priv->lock); + } +- +-static struct sh_mobile_meram_ops sh_mobile_meram_ops = { +- .module = THIS_MODULE, +- .cache_alloc = sh_mobile_cache_alloc, +- .cache_free = sh_mobile_cache_free, +- .cache_update = sh_mobile_cache_update, +-}; ++EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_update); + + /* ----------------------------------------------------------------------------- + * Power management +@@ -620,7 +621,6 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev) + for (i = 0; i < MERAM_ICB_NUM; ++i) + priv->icbs[i].index = i; + +- pdata->ops = &sh_mobile_meram_ops; + pdata->priv = priv; + pdata->pdev = pdev; + +diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h +index 8a5afaf..1134837 100644 +--- a/include/video/sh_mobile_meram.h ++++ b/include/video/sh_mobile_meram.h +@@ -15,7 +15,6 @@ enum { + + + struct sh_mobile_meram_priv; +-struct sh_mobile_meram_ops; + + /* + * struct sh_mobile_meram_info - MERAM platform data +@@ -24,7 +23,6 @@ struct sh_mobile_meram_ops; + struct sh_mobile_meram_info { + int addr_mode; + u32 reserved_icbs; +- struct sh_mobile_meram_ops *ops; + struct sh_mobile_meram_priv *priv; + struct platform_device *pdev; + }; +@@ -38,21 +36,43 @@ struct sh_mobile_meram_cfg { + struct sh_mobile_meram_icb_cfg icb[2]; + }; + +-struct module; +-struct sh_mobile_meram_ops { +- struct module *module; +- +- /* LCDC cache management */ +- void *(*cache_alloc)(struct sh_mobile_meram_info *meram_dev, +- const struct sh_mobile_meram_cfg *cfg, +- unsigned int xres, unsigned int yres, +- unsigned int pixelformat, unsigned int *pitch); +- void (*cache_free)(struct sh_mobile_meram_info *meram_dev, void *data); +- void (*cache_update)(struct sh_mobile_meram_info *meram_dev, void *data, ++#if defined(CONFIG_FB_SH_MOBILE_MERAM) || \ ++ defined(CONFIG_FB_SH_MOBILE_MERAM_MODULE) ++void *sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *dev, ++ const struct sh_mobile_meram_cfg *cfg, ++ unsigned int xres, unsigned int yres, ++ unsigned int pixelformat, ++ unsigned int *pitch); ++void sh_mobile_meram_cache_free(struct sh_mobile_meram_info *dev, void *data); ++void sh_mobile_meram_cache_update(struct sh_mobile_meram_info *dev, void *data, ++ unsigned long base_addr_y, ++ unsigned long base_addr_c, ++ unsigned long *icb_addr_y, ++ unsigned long *icb_addr_c); ++#else ++static inline void * ++sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *dev, ++ const struct sh_mobile_meram_cfg *cfg, ++ unsigned int xres, unsigned int yres, ++ unsigned int pixelformat, ++ unsigned int *pitch) ++{ ++ return ERR_PTR(-ENODEV); ++} ++ ++static inline void ++sh_mobile_meram_cache_free(struct sh_mobile_meram_info *dev, void *data) ++{ ++} ++ ++static inline void ++sh_mobile_meram_cache_update(struct sh_mobile_meram_info *dev, void *data, + unsigned long base_addr_y, + unsigned long base_addr_c, + unsigned long *icb_addr_y, +- unsigned long *icb_addr_c); +-}; ++ unsigned long *icb_addr_c) ++{ ++} ++#endif + + #endif /* __VIDEO_SH_MOBILE_MERAM_H__ */ +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0044-sh_mobile_meram-Add-direct-MERAM-allocation-API.patch b/patches.armadillo800/0044-sh_mobile_meram-Add-direct-MERAM-allocation-API.patch new file mode 100644 index 0000000000000..0602f7715b36c --- /dev/null +++ b/patches.armadillo800/0044-sh_mobile_meram-Add-direct-MERAM-allocation-API.patch @@ -0,0 +1,129 @@ +From 81c446ad9189a068ef555c436c96d651dc86c4da Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Thu, 15 Mar 2012 13:18:17 +0100 +Subject: sh_mobile_meram: Add direct MERAM allocation API + +The API can be used to allocate and free MERAM blocks directly, without +going through ICBs. + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +(cherry picked from commit 239921ec1d969e904676f444a92e6d68a928d98c) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/video/sh_mobile_meram.c | 41 +++++++++++++++++++++++++++++++++++++---- + include/video/sh_mobile_meram.h | 16 ++++++++++++++++ + 2 files changed, 53 insertions(+), 4 deletions(-) + +diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c +index fdb6fc1..7a0ba8b 100644 +--- a/drivers/video/sh_mobile_meram.c ++++ b/drivers/video/sh_mobile_meram.c +@@ -195,6 +195,21 @@ static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off) + } + + /* ----------------------------------------------------------------------------- ++ * MERAM allocation and free ++ */ ++ ++static unsigned long meram_alloc(struct sh_mobile_meram_priv *priv, size_t size) ++{ ++ return gen_pool_alloc(priv->pool, size); ++} ++ ++static void meram_free(struct sh_mobile_meram_priv *priv, unsigned long mem, ++ size_t size) ++{ ++ gen_pool_free(priv->pool, mem, size); ++} ++ ++/* ----------------------------------------------------------------------------- + * LCDC cache planes allocation, init, cleanup and free + */ + +@@ -216,7 +231,7 @@ static int meram_plane_alloc(struct sh_mobile_meram_priv *priv, + return -ENOMEM; + plane->marker = &priv->icbs[idx]; + +- mem = gen_pool_alloc(priv->pool, size * 1024); ++ mem = meram_alloc(priv, size * 1024); + if (mem == 0) + return -ENOMEM; + +@@ -233,8 +248,8 @@ static int meram_plane_alloc(struct sh_mobile_meram_priv *priv, + static void meram_plane_free(struct sh_mobile_meram_priv *priv, + struct sh_mobile_meram_fb_plane *plane) + { +- gen_pool_free(priv->pool, priv->meram + plane->marker->offset, +- plane->marker->size * 1024); ++ meram_free(priv, priv->meram + plane->marker->offset, ++ plane->marker->size * 1024); + + __clear_bit(plane->marker->index, &priv->used_icb); + __clear_bit(plane->cache->index, &priv->used_icb); +@@ -386,9 +401,27 @@ static void meram_plane_cleanup(struct sh_mobile_meram_priv *priv, + } + + /* ----------------------------------------------------------------------------- +- * LCDC cache operations ++ * MERAM operations + */ + ++unsigned long sh_mobile_meram_alloc(struct sh_mobile_meram_info *pdata, ++ size_t size) ++{ ++ struct sh_mobile_meram_priv *priv = pdata->priv; ++ ++ return meram_alloc(priv, size); ++} ++EXPORT_SYMBOL_GPL(sh_mobile_meram_alloc); ++ ++void sh_mobile_meram_free(struct sh_mobile_meram_info *pdata, unsigned long mem, ++ size_t size) ++{ ++ struct sh_mobile_meram_priv *priv = pdata->priv; ++ ++ meram_free(priv, mem, size); ++} ++EXPORT_SYMBOL_GPL(sh_mobile_meram_free); ++ + /* Allocate memory for the ICBs and mark them as used. */ + static struct sh_mobile_meram_fb_cache * + meram_cache_alloc(struct sh_mobile_meram_priv *priv, +diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h +index 1134837..062e6e7 100644 +--- a/include/video/sh_mobile_meram.h ++++ b/include/video/sh_mobile_meram.h +@@ -38,6 +38,10 @@ struct sh_mobile_meram_cfg { + + #if defined(CONFIG_FB_SH_MOBILE_MERAM) || \ + defined(CONFIG_FB_SH_MOBILE_MERAM_MODULE) ++unsigned long sh_mobile_meram_alloc(struct sh_mobile_meram_info *meram_dev, ++ size_t size); ++void sh_mobile_meram_free(struct sh_mobile_meram_info *meram_dev, ++ unsigned long mem, size_t size); + void *sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *dev, + const struct sh_mobile_meram_cfg *cfg, + unsigned int xres, unsigned int yres, +@@ -50,6 +54,18 @@ void sh_mobile_meram_cache_update(struct sh_mobile_meram_info *dev, void *data, + unsigned long *icb_addr_y, + unsigned long *icb_addr_c); + #else ++static inline unsigned long ++sh_mobile_meram_alloc(struct sh_mobile_meram_info *meram_dev, size_t size) ++{ ++ return 0; ++} ++ ++static inline void ++sh_mobile_meram_free(struct sh_mobile_meram_info *meram_dev, ++ unsigned long mem, size_t size) ++{ ++} ++ + static inline void * + sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *dev, + const struct sh_mobile_meram_cfg *cfg, +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0045-fbdev-sh_mobile_lcdc-Destroy-mutex-at-remove-time.patch b/patches.armadillo800/0045-fbdev-sh_mobile_lcdc-Destroy-mutex-at-remove-time.patch new file mode 100644 index 0000000000000..3df2f9ab9ecef --- /dev/null +++ b/patches.armadillo800/0045-fbdev-sh_mobile_lcdc-Destroy-mutex-at-remove-time.patch @@ -0,0 +1,37 @@ +From fbcfe8a409c3a0177d599e2b6a73a70fd4dffc8a Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Thu, 15 Mar 2012 18:34:05 +0100 +Subject: fbdev: sh_mobile_lcdc: Destroy mutex at remove time + +Add a missing mutex_destroy() call when the driver is unbound from the +device. + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +(cherry picked from commit 0c75c4e073a8ec35bfd6c8adcceb2b896f2063e2) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/video/sh_mobile_lcdcfb.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c +index 9da4b1b6..644c230 100644 +--- a/drivers/video/sh_mobile_lcdcfb.c ++++ b/drivers/video/sh_mobile_lcdcfb.c +@@ -2444,8 +2444,11 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev) + } + + for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { +- if (priv->ch[i].bl) +- sh_mobile_lcdc_bl_remove(priv->ch[i].bl); ++ struct sh_mobile_lcdc_chan *ch = &priv->ch[i]; ++ ++ if (ch->bl) ++ sh_mobile_lcdc_bl_remove(ch->bl); ++ mutex_destroy(&ch->open_lock); + } + + if (priv->dot_clk) { +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0046-fbdev-sh_mobile_lcdc-Fix-line-pitch-computation.patch b/patches.armadillo800/0046-fbdev-sh_mobile_lcdc-Fix-line-pitch-computation.patch new file mode 100644 index 0000000000000..378217b52603d --- /dev/null +++ b/patches.armadillo800/0046-fbdev-sh_mobile_lcdc-Fix-line-pitch-computation.patch @@ -0,0 +1,72 @@ +From 8a18c739cb6639c5b8e43cc19929f98c532afae7 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Wed, 18 Jul 2012 16:29:20 +0200 +Subject: fbdev: sh_mobile_lcdc: Fix line pitch computation + +Line pitch depends on the virtual horizontal resolution, compute it +accordingly. + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +(cherry picked from commit 16ca21c9a9f64577221c47d8d2f00d13b880aefa) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/video/sh_mobile_lcdcfb.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c +index 644c230..67877cc 100644 +--- a/drivers/video/sh_mobile_lcdcfb.c ++++ b/drivers/video/sh_mobile_lcdcfb.c +@@ -1580,9 +1580,9 @@ static int sh_mobile_lcdc_overlay_set_par(struct fb_info *info) + ovl->yres_virtual = info->var.yres_virtual; + + if (ovl->format->yuv) +- ovl->pitch = info->var.xres; ++ ovl->pitch = info->var.xres_virtual; + else +- ovl->pitch = info->var.xres * ovl->format->bpp / 8; ++ ovl->pitch = info->var.xres_virtual * ovl->format->bpp / 8; + + sh_mobile_lcdc_overlay_setup(ovl); + +@@ -2024,9 +2024,9 @@ static int sh_mobile_lcdc_set_par(struct fb_info *info) + ch->yres_virtual = info->var.yres_virtual; + + if (ch->format->yuv) +- ch->pitch = info->var.xres; ++ ch->pitch = info->var.xres_virtual; + else +- ch->pitch = info->var.xres * ch->format->bpp / 8; ++ ch->pitch = info->var.xres_virtual * ch->format->bpp / 8; + + ret = sh_mobile_lcdc_start(ch->lcdc); + if (ret < 0) +@@ -2539,9 +2539,9 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv, + ovl->yres_virtual = ovl->yres * 2; + + if (!format->yuv) +- ovl->pitch = ovl->xres * format->bpp / 8; ++ ovl->pitch = ovl->xres_virtual * format->bpp / 8; + else +- ovl->pitch = ovl->xres; ++ ovl->pitch = ovl->xres_virtual; + + /* Allocate frame buffer memory. */ + ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres +@@ -2628,10 +2628,10 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv, + + if (!format->yuv) { + ch->colorspace = V4L2_COLORSPACE_SRGB; +- ch->pitch = ch->xres * format->bpp / 8; ++ ch->pitch = ch->xres_virtual * format->bpp / 8; + } else { + ch->colorspace = V4L2_COLORSPACE_REC709; +- ch->pitch = ch->xres; ++ ch->pitch = ch->xres_virtual; + } + + ch->display.width = cfg->panel_cfg.width; +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0047-fbdev-sh_mobile_lcdc-Use-channel-configuration-to-in.patch b/patches.armadillo800/0047-fbdev-sh_mobile_lcdc-Use-channel-configuration-to-in.patch new file mode 100644 index 0000000000000..b14dd22a45d7c --- /dev/null +++ b/patches.armadillo800/0047-fbdev-sh_mobile_lcdc-Use-channel-configuration-to-in.patch @@ -0,0 +1,53 @@ +From 1cd17c833c8811e06b3dddbe9a9c71e6735a58f9 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Wed, 18 Jul 2012 16:59:16 +0200 +Subject: fbdev: sh_mobile_lcdc: Use channel configuration to initialize fb + device + +Copy the x and y virtual resolutions from the channel information +instead of recomputing them. + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +(cherry picked from commit bd5f2c6911c210af52fa4dc4cf504043ff8a4971) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/video/sh_mobile_lcdcfb.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c +index 67877cc..68011b5 100644 +--- a/drivers/video/sh_mobile_lcdcfb.c ++++ b/drivers/video/sh_mobile_lcdcfb.c +@@ -2214,14 +2214,14 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch, + info->fix.ypanstep = 2; + + /* Initialize variable screen information using the first mode as +- * default. The default Y virtual resolution is twice the panel size to +- * allow for double-buffering. ++ * default. + */ + var = &info->var; + fb_videomode_to_var(var, mode); + var->width = ch->cfg->panel_cfg.width; + var->height = ch->cfg->panel_cfg.height; +- var->yres_virtual = var->yres * 2; ++ var->xres_virtual = ch->xres_virtual; ++ var->yres_virtual = ch->yres_virtual; + var->activate = FB_ACTIVATE_NOW; + + /* Use the legacy API by default for RGB formats, and the FOURCC API +@@ -2619,7 +2619,9 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv, + num_modes = cfg->num_modes; + } + +- /* Use the first mode as default. */ ++ /* Use the first mode as default. The default Y virtual resolution is ++ * twice the panel size to allow for double-buffering. ++ */ + ch->format = format; + ch->xres = mode->xres; + ch->xres_virtual = mode->xres; +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0048-fbdev-sh_mobile_lcdc-Support-horizontal-panning.patch b/patches.armadillo800/0048-fbdev-sh_mobile_lcdc-Support-horizontal-panning.patch new file mode 100644 index 0000000000000..80ab27b4bd142 --- /dev/null +++ b/patches.armadillo800/0048-fbdev-sh_mobile_lcdc-Support-horizontal-panning.patch @@ -0,0 +1,72 @@ +From 194360fff0a2a4255630477db84bf7af704109ca Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Wed, 18 Jul 2012 17:09:04 +0200 +Subject: fbdev: sh_mobile_lcdc: Support horizontal panning + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +(cherry picked from commit 15dede882e564601947f2ce4b647742c0351be6d) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/video/sh_mobile_lcdcfb.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c +index 68011b5..d82c1de 100644 +--- a/drivers/video/sh_mobile_lcdcfb.c ++++ b/drivers/video/sh_mobile_lcdcfb.c +@@ -1493,7 +1493,7 @@ static const struct fb_fix_screeninfo sh_mobile_lcdc_overlay_fix = { + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .accel = FB_ACCEL_NONE, +- .xpanstep = 0, ++ .xpanstep = 1, + .ypanstep = 1, + .ywrapstep = 0, + .capabilities = FB_CAP_FOURCC, +@@ -1714,9 +1714,14 @@ sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl) + else + info->fix.visual = FB_VISUAL_TRUECOLOR; + +- if (ovl->format->fourcc == V4L2_PIX_FMT_NV12 || +- ovl->format->fourcc == V4L2_PIX_FMT_NV21) ++ switch (ovl->format->fourcc) { ++ case V4L2_PIX_FMT_NV16: ++ case V4L2_PIX_FMT_NV61: + info->fix.ypanstep = 2; ++ case V4L2_PIX_FMT_NV12: ++ case V4L2_PIX_FMT_NV21: ++ info->fix.xpanstep = 2; ++ } + + /* Initialize variable screen information. */ + var = &info->var; +@@ -1771,7 +1776,7 @@ static const struct fb_fix_screeninfo sh_mobile_lcdc_fix = { + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .accel = FB_ACCEL_NONE, +- .xpanstep = 0, ++ .xpanstep = 1, + .ypanstep = 1, + .ywrapstep = 0, + .capabilities = FB_CAP_FOURCC, +@@ -2209,9 +2214,14 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch, + else + info->fix.visual = FB_VISUAL_TRUECOLOR; + +- if (ch->format->fourcc == V4L2_PIX_FMT_NV12 || +- ch->format->fourcc == V4L2_PIX_FMT_NV21) ++ switch (ch->format->fourcc) { ++ case V4L2_PIX_FMT_NV16: ++ case V4L2_PIX_FMT_NV61: + info->fix.ypanstep = 2; ++ case V4L2_PIX_FMT_NV12: ++ case V4L2_PIX_FMT_NV21: ++ info->fix.xpanstep = 2; ++ } + + /* Initialize variable screen information using the first mode as + * default. +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0049-fbdev-sh_mobile_lcdc-Fix-overlay-registers-update-du.patch b/patches.armadillo800/0049-fbdev-sh_mobile_lcdc-Fix-overlay-registers-update-du.patch new file mode 100644 index 0000000000000..ee64fdba9c7f0 --- /dev/null +++ b/patches.armadillo800/0049-fbdev-sh_mobile_lcdc-Fix-overlay-registers-update-du.patch @@ -0,0 +1,41 @@ +From 07f80feb4f79273ade0b493d4f173d4721709d74 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Thu, 19 Jul 2012 02:29:52 +0200 +Subject: fbdev: sh_mobile_lcdc: Fix overlay registers update during pan + operation + +Updating overlay registers require switching to overlay update mode. +This was correctly done when configuring the overlay format and size, +but not when updating the base address registers during pan operation. +Fix it. + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +(cherry picked from commit 8be7c66995bf06769dc4c5f7a62f3cd62a627e7e) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/video/sh_mobile_lcdcfb.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c +index d82c1de..a502709 100644 +--- a/drivers/video/sh_mobile_lcdcfb.c ++++ b/drivers/video/sh_mobile_lcdcfb.c +@@ -1539,9 +1539,14 @@ static int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var, + ovl->base_addr_c = base_addr_c; + } + ++ lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index)); ++ + lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y); + lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c); + ++ lcdc_write(ovl->channel->lcdc, LDBCR, ++ LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index)); ++ + ovl->pan_offset = pan_offset; + + return 0; +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0050-fbdev-sh_mobile_lcdc-Fix-pan-offset-computation-in-Y.patch b/patches.armadillo800/0050-fbdev-sh_mobile_lcdc-Fix-pan-offset-computation-in-Y.patch new file mode 100644 index 0000000000000..d72596f9b1593 --- /dev/null +++ b/patches.armadillo800/0050-fbdev-sh_mobile_lcdc-Fix-pan-offset-computation-in-Y.patch @@ -0,0 +1,241 @@ +From 896e926e26d250d1b5397c5a39d12fb25c6928b5 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Thu, 15 Mar 2012 18:15:37 +0100 +Subject: fbdev: sh_mobile_lcdc: Fix pan offset computation in YUV mode + +The chroma plane offset in memory is equal to the luma plane maximum +size. Fix offset computations. + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +(cherry picked from commit a4aa25f6e7885a42c90fe5f0a965403df6cbc943) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/video/sh_mobile_lcdcfb.c | 110 ++++++++++++++++++--------------------- + drivers/video/sh_mobile_lcdcfb.h | 3 +- + 2 files changed, 54 insertions(+), 59 deletions(-) + +diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c +index a502709..8cb653b 100644 +--- a/drivers/video/sh_mobile_lcdcfb.c ++++ b/drivers/video/sh_mobile_lcdcfb.c +@@ -161,7 +161,7 @@ enum sh_mobile_lcdc_overlay_mode { + * @dma_handle: Frame buffer DMA address + * @base_addr_y: Overlay base address (RGB or luma component) + * @base_addr_c: Overlay base address (chroma component) +- * @pan_offset: Current pan offset in bytes ++ * @pan_y_offset: Panning linear offset in bytes (luma component) + * @format: Current pixelf format + * @xres: Horizontal visible resolution + * @xres_virtual: Horizontal total resolution +@@ -191,7 +191,7 @@ struct sh_mobile_lcdc_overlay { + dma_addr_t dma_handle; + unsigned long base_addr_y; + unsigned long base_addr_c; +- unsigned long pan_offset; ++ unsigned long pan_y_offset; + + const struct sh_mobile_lcdc_format_info *format; + unsigned int xres; +@@ -873,8 +873,8 @@ static void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl) + } + + ovl->base_addr_y = ovl->dma_handle; +- ovl->base_addr_c = ovl->base_addr_y + ovl->xres +- * ovl->yres_virtual; ++ ovl->base_addr_c = ovl->dma_handle ++ + ovl->xres_virtual * ovl->yres_virtual; + + switch (ovl->mode) { + case LCDC_OVERLAY_BLEND: +@@ -1111,7 +1111,8 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) + continue; + + ch->base_addr_y = ch->dma_handle; +- ch->base_addr_c = ch->base_addr_y + ch->xres * ch->yres_virtual; ++ ch->base_addr_c = ch->dma_handle ++ + ch->xres_virtual * ch->yres_virtual; + ch->line_size = ch->pitch; + + /* Enable MERAM if possible. */ +@@ -1505,39 +1506,36 @@ static int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var, + struct sh_mobile_lcdc_overlay *ovl = info->par; + unsigned long base_addr_y; + unsigned long base_addr_c; +- unsigned long pan_offset; ++ unsigned long y_offset; + unsigned long c_offset; + +- if (!ovl->format->yuv) +- pan_offset = var->yoffset * ovl->pitch +- + var->xoffset * (ovl->format->bpp / 8); +- else +- pan_offset = var->yoffset * ovl->pitch + var->xoffset; ++ if (!ovl->format->yuv) { ++ y_offset = (var->yoffset * ovl->xres_virtual + var->xoffset) ++ * ovl->format->bpp / 8; ++ c_offset = 0; ++ } else { ++ unsigned int xsub = ovl->format->bpp < 24 ? 2 : 1; ++ unsigned int ysub = ovl->format->bpp < 16 ? 2 : 1; ++ ++ y_offset = var->yoffset * ovl->xres_virtual + var->xoffset; ++ c_offset = var->yoffset / ysub * ovl->xres_virtual * 2 / xsub ++ + var->xoffset * 2 / xsub; ++ } + +- if (pan_offset == ovl->pan_offset) +- return 0; /* No change, do nothing */ ++ /* If the Y offset hasn't changed, the C offset hasn't either. There's ++ * nothing to do in that case. ++ */ ++ if (y_offset == ovl->pan_y_offset) ++ return 0; + + /* Set the source address for the next refresh */ +- base_addr_y = ovl->dma_handle + pan_offset; ++ base_addr_y = ovl->dma_handle + y_offset; ++ base_addr_c = ovl->dma_handle + ovl->xres_virtual * ovl->yres_virtual ++ + c_offset; + + ovl->base_addr_y = base_addr_y; +- ovl->base_addr_c = base_addr_y; +- +- if (ovl->format->yuv) { +- /* Set Y offset */ +- c_offset = var->yoffset * ovl->pitch +- * (ovl->format->bpp - 8) / 8; +- base_addr_c = ovl->dma_handle +- + ovl->xres * ovl->yres_virtual +- + c_offset; +- /* Set X offset */ +- if (ovl->format->fourcc == V4L2_PIX_FMT_NV24) +- base_addr_c += 2 * var->xoffset; +- else +- base_addr_c += var->xoffset; +- +- ovl->base_addr_c = base_addr_c; +- } ++ ovl->base_addr_c = base_addr_c; ++ ovl->pan_y_offset = y_offset; + + lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index)); + +@@ -1547,8 +1545,6 @@ static int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var, + lcdc_write(ovl->channel->lcdc, LDBCR, + LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index)); + +- ovl->pan_offset = pan_offset; +- + return 0; + } + +@@ -1814,35 +1810,33 @@ static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var, + struct sh_mobile_lcdc_chan *ch = info->par; + struct sh_mobile_lcdc_priv *priv = ch->lcdc; + unsigned long ldrcntr; +- unsigned long new_pan_offset; +- unsigned long base_addr_y, base_addr_c = 0; ++ unsigned long base_addr_y, base_addr_c; ++ unsigned long y_offset; + unsigned long c_offset; + +- if (!ch->format->yuv) +- new_pan_offset = var->yoffset * ch->pitch +- + var->xoffset * (ch->format->bpp / 8); +- else +- new_pan_offset = var->yoffset * ch->pitch + var->xoffset; ++ if (!ch->format->yuv) { ++ y_offset = (var->yoffset * ch->xres_virtual + var->xoffset) ++ * ch->format->bpp / 8; ++ c_offset = 0; ++ } else { ++ unsigned int xsub = ch->format->bpp < 24 ? 2 : 1; ++ unsigned int ysub = ch->format->bpp < 16 ? 2 : 1; + +- if (new_pan_offset == ch->pan_offset) +- return 0; /* No change, do nothing */ ++ y_offset = var->yoffset * ch->xres_virtual + var->xoffset; ++ c_offset = var->yoffset / ysub * ch->xres_virtual * 2 / xsub ++ + var->xoffset * 2 / xsub; ++ } + +- ldrcntr = lcdc_read(priv, _LDRCNTR); ++ /* If the Y offset hasn't changed, the C offset hasn't either. There's ++ * nothing to do in that case. ++ */ ++ if (y_offset == ch->pan_y_offset) ++ return 0; + + /* Set the source address for the next refresh */ +- base_addr_y = ch->dma_handle + new_pan_offset; +- if (ch->format->yuv) { +- /* Set y offset */ +- c_offset = var->yoffset * ch->pitch +- * (ch->format->bpp - 8) / 8; +- base_addr_c = ch->dma_handle + ch->xres * ch->yres_virtual +- + c_offset; +- /* Set x offset */ +- if (ch->format->fourcc == V4L2_PIX_FMT_NV24) +- base_addr_c += 2 * var->xoffset; +- else +- base_addr_c += var->xoffset; +- } ++ base_addr_y = ch->dma_handle + y_offset; ++ base_addr_c = ch->dma_handle + ch->xres_virtual * ch->yres_virtual ++ + c_offset; + + if (ch->cache) + sh_mobile_meram_cache_update(priv->meram_dev, ch->cache, +@@ -1851,17 +1845,18 @@ static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var, + + ch->base_addr_y = base_addr_y; + ch->base_addr_c = base_addr_c; ++ ch->pan_y_offset = y_offset; + + lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); + if (ch->format->yuv) + lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); + ++ ldrcntr = lcdc_read(priv, _LDRCNTR); + if (lcdc_chan_is_sublcd(ch)) + lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS); + else + lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS); + +- ch->pan_offset = new_pan_offset; + + sh_mobile_lcdc_deferred_io_touch(info); + +@@ -2734,7 +2729,6 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) + } + init_waitqueue_head(&ch->frame_end_wait); + init_completion(&ch->vsync_completion); +- ch->pan_offset = 0; + + /* probe the backlight is there is one defined */ + if (ch->cfg->bl_info.max_brightness) +diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h +index e53cd11..0f92f65 100644 +--- a/drivers/video/sh_mobile_lcdcfb.h ++++ b/drivers/video/sh_mobile_lcdcfb.h +@@ -47,6 +47,7 @@ struct sh_mobile_lcdc_entity { + /* + * struct sh_mobile_lcdc_chan - LCDC display channel + * ++ * @pan_y_offset: Panning linear offset in bytes (luma component) + * @base_addr_y: Frame buffer viewport base address (luma component) + * @base_addr_c: Frame buffer viewport base address (chroma component) + * @pitch: Frame buffer line pitch +@@ -68,7 +69,7 @@ struct sh_mobile_lcdc_chan { + unsigned long fb_size; + + dma_addr_t dma_handle; +- unsigned long pan_offset; ++ unsigned long pan_y_offset; + + unsigned long frame_end; + wait_queue_head_t frame_end_wait; +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0051-fbdev-sh_mobile_lcdc-Fix-vertical-panning-step.patch b/patches.armadillo800/0051-fbdev-sh_mobile_lcdc-Fix-vertical-panning-step.patch new file mode 100644 index 0000000000000..2662cba50a404 --- /dev/null +++ b/patches.armadillo800/0051-fbdev-sh_mobile_lcdc-Fix-vertical-panning-step.patch @@ -0,0 +1,55 @@ +From 633f3cd2b85466e5744a86cbe888d78f30302083 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Thu, 26 Jul 2012 14:36:55 +0200 +Subject: fbdev: sh_mobile_lcdc: Fix vertical panning step + +Commit 15dede882e564601947f2ce4b647742c0351be6d added support for +horizontal panning but accidentally computes the Y pan step value +incorrectly for NV12/21 and NV16/61 formats. Fix this. + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de> +(cherry picked from commit ac33a207b13a70bbca6e58094e28bd92b9fc1ff3) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/video/sh_mobile_lcdcfb.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c +index 8cb653b..699487c 100644 +--- a/drivers/video/sh_mobile_lcdcfb.c ++++ b/drivers/video/sh_mobile_lcdcfb.c +@@ -1716,11 +1716,11 @@ sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl) + info->fix.visual = FB_VISUAL_TRUECOLOR; + + switch (ovl->format->fourcc) { +- case V4L2_PIX_FMT_NV16: +- case V4L2_PIX_FMT_NV61: +- info->fix.ypanstep = 2; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: ++ info->fix.ypanstep = 2; ++ case V4L2_PIX_FMT_NV16: ++ case V4L2_PIX_FMT_NV61: + info->fix.xpanstep = 2; + } + +@@ -2215,11 +2215,11 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch, + info->fix.visual = FB_VISUAL_TRUECOLOR; + + switch (ch->format->fourcc) { +- case V4L2_PIX_FMT_NV16: +- case V4L2_PIX_FMT_NV61: +- info->fix.ypanstep = 2; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: ++ info->fix.ypanstep = 2; ++ case V4L2_PIX_FMT_NV16: ++ case V4L2_PIX_FMT_NV61: + info->fix.xpanstep = 2; + } + +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0052-ARM-mach-shmobile-r8a7740-add-gpio_irq-support.patch b/patches.armadillo800/0052-ARM-mach-shmobile-r8a7740-add-gpio_irq-support.patch new file mode 100644 index 0000000000000..e33085a762801 --- /dev/null +++ b/patches.armadillo800/0052-ARM-mach-shmobile-r8a7740-add-gpio_irq-support.patch @@ -0,0 +1,83 @@ +From 18ed06783eaf892967a3260bd9056a4aba81bfa0 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 6 Apr 2012 01:28:14 -0700 +Subject: ARM: mach-shmobile: r8a7740: add gpio_irq support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 9f6b78223b7b49bc06d2e84b15d48f02206ec3c3) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/pfc-r8a7740.c | 39 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 39 insertions(+) + +diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c +index a4fff69..670fe18 100644 +--- a/arch/arm/mach-shmobile/pfc-r8a7740.c ++++ b/arch/arm/mach-shmobile/pfc-r8a7740.c +@@ -22,6 +22,7 @@ + #include <linux/kernel.h> + #include <linux/gpio.h> + #include <mach/r8a7740.h> ++#include <mach/irqs.h> + + #define CPU_ALL_PORT(fn, pfx, sfx) \ + PORT_10(fn, pfx, sfx), PORT_90(fn, pfx, sfx), \ +@@ -2527,6 +2528,41 @@ static struct pinmux_data_reg pinmux_data_regs[] = { + { }, + }; + ++static struct pinmux_irq pinmux_irqs[] = { ++ PINMUX_IRQ(evt2irq(0x0200), PORT2_FN0, PORT13_FN0), /* IRQ0A */ ++ PINMUX_IRQ(evt2irq(0x0220), PORT20_FN0), /* IRQ1A */ ++ PINMUX_IRQ(evt2irq(0x0240), PORT11_FN0, PORT12_FN0), /* IRQ2A */ ++ PINMUX_IRQ(evt2irq(0x0260), PORT10_FN0, PORT14_FN0), /* IRQ3A */ ++ PINMUX_IRQ(evt2irq(0x0280), PORT15_FN0, PORT172_FN0), /* IRQ4A */ ++ PINMUX_IRQ(evt2irq(0x02A0), PORT0_FN0, PORT1_FN0), /* IRQ5A */ ++ PINMUX_IRQ(evt2irq(0x02C0), PORT121_FN0, PORT173_FN0), /* IRQ6A */ ++ PINMUX_IRQ(evt2irq(0x02E0), PORT120_FN0, PORT209_FN0), /* IRQ7A */ ++ PINMUX_IRQ(evt2irq(0x0300), PORT119_FN0), /* IRQ8A */ ++ PINMUX_IRQ(evt2irq(0x0320), PORT118_FN0, PORT210_FN0), /* IRQ9A */ ++ PINMUX_IRQ(evt2irq(0x0340), PORT19_FN0), /* IRQ10A */ ++ PINMUX_IRQ(evt2irq(0x0360), PORT104_FN0), /* IRQ11A */ ++ PINMUX_IRQ(evt2irq(0x0380), PORT42_FN0, PORT97_FN0), /* IRQ12A */ ++ PINMUX_IRQ(evt2irq(0x03A0), PORT64_FN0, PORT98_FN0), /* IRQ13A */ ++ PINMUX_IRQ(evt2irq(0x03C0), PORT63_FN0, PORT99_FN0), /* IRQ14A */ ++ PINMUX_IRQ(evt2irq(0x03E0), PORT62_FN0, PORT100_FN0), /* IRQ15A */ ++ PINMUX_IRQ(evt2irq(0x3200), PORT68_FN0, PORT211_FN0), /* IRQ16A */ ++ PINMUX_IRQ(evt2irq(0x3220), PORT69_FN0), /* IRQ17A */ ++ PINMUX_IRQ(evt2irq(0x3240), PORT70_FN0), /* IRQ18A */ ++ PINMUX_IRQ(evt2irq(0x3260), PORT71_FN0), /* IRQ19A */ ++ PINMUX_IRQ(evt2irq(0x3280), PORT67_FN0), /* IRQ20A */ ++ PINMUX_IRQ(evt2irq(0x32A0), PORT202_FN0), /* IRQ21A */ ++ PINMUX_IRQ(evt2irq(0x32C0), PORT95_FN0), /* IRQ22A */ ++ PINMUX_IRQ(evt2irq(0x32E0), PORT96_FN0), /* IRQ23A */ ++ PINMUX_IRQ(evt2irq(0x3300), PORT180_FN0), /* IRQ24A */ ++ PINMUX_IRQ(evt2irq(0x3320), PORT38_FN0), /* IRQ25A */ ++ PINMUX_IRQ(evt2irq(0x3340), PORT58_FN0, PORT81_FN0), /* IRQ26A */ ++ PINMUX_IRQ(evt2irq(0x3360), PORT57_FN0, PORT168_FN0), /* IRQ27A */ ++ PINMUX_IRQ(evt2irq(0x3380), PORT56_FN0, PORT169_FN0), /* IRQ28A */ ++ PINMUX_IRQ(evt2irq(0x33A0), PORT50_FN0, PORT170_FN0), /* IRQ29A */ ++ PINMUX_IRQ(evt2irq(0x33C0), PORT49_FN0, PORT171_FN0), /* IRQ30A */ ++ PINMUX_IRQ(evt2irq(0x33E0), PORT41_FN0, PORT167_FN0), /* IRQ31A */ ++}; ++ + static struct pinmux_info r8a7740_pinmux_info = { + .name = "r8a7740_pfc", + .reserved_id = PINMUX_RESERVED, +@@ -2554,6 +2590,9 @@ static struct pinmux_info r8a7740_pinmux_info = { + + .gpio_data = pinmux_data, + .gpio_data_size = ARRAY_SIZE(pinmux_data), ++ ++ .gpio_irq = pinmux_irqs, ++ .gpio_irq_size = ARRAY_SIZE(pinmux_irqs), + }; + + void r8a7740_pinmux_init(void) +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0053-ARM-mach-shmobile-r8a7740-cleanup-I2C-workaround-met.patch b/patches.armadillo800/0053-ARM-mach-shmobile-r8a7740-cleanup-I2C-workaround-met.patch new file mode 100644 index 0000000000000..b750ea78f1a8e --- /dev/null +++ b/patches.armadillo800/0053-ARM-mach-shmobile-r8a7740-cleanup-I2C-workaround-met.patch @@ -0,0 +1,48 @@ +From 46dccabaa06e08bb7b9b2ac4b46f784b8afba7f0 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 13 Apr 2012 02:41:06 -0700 +Subject: ARM: mach-shmobile: r8a7740: cleanup I2C workaround method + +Current workaround of I2C on r8a7740 used mdelay(), +but it was an overkill. +This patch cleans up the workaround delay. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 4228716c87f7915410721952bad3e568fb5f2431) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/setup-r8a7740.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/arch/arm/mach-shmobile/setup-r8a7740.c ++++ b/arch/arm/mach-shmobile/setup-r8a7740.c +@@ -368,19 +368,19 @@ static void r8a7740_i2c_workaround(struc + i2c_write(reg, ICSTART, i2c_read(reg, ICSTART) | 0x10); + i2c_read(reg, ICSTART); /* dummy read */ + +- mdelay(100); ++ udelay(10); + + i2c_write(reg, ICCR, 0x01); +- i2c_read(reg, ICCR); + i2c_write(reg, ICSTART, 0x00); +- i2c_read(reg, ICSTART); ++ ++ udelay(10); + + i2c_write(reg, ICCR, 0x10); +- mdelay(100); ++ udelay(10); + i2c_write(reg, ICCR, 0x00); +- mdelay(100); ++ udelay(10); + i2c_write(reg, ICCR, 0x10); +- mdelay(100); ++ udelay(10); + + iounmap(reg); + } diff --git a/patches.armadillo800/0054-ARM-mach-shmobile-clock-r8a7740-add-FSI-clock.patch b/patches.armadillo800/0054-ARM-mach-shmobile-clock-r8a7740-add-FSI-clock.patch new file mode 100644 index 0000000000000..474b8fcdbc926 --- /dev/null +++ b/patches.armadillo800/0054-ARM-mach-shmobile-clock-r8a7740-add-FSI-clock.patch @@ -0,0 +1,47 @@ +From 9b696a8092bedbd771c4b8e6a8c12edbd6881444 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 1 Apr 2012 18:46:09 -0700 +Subject: ARM: mach-shmobile: clock-r8a7740: add FSI clock + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 7ee8948d158946e52ea21562f2ceef268439f36e) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-r8a7740.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c +index 99c4d74..b6fa1b7 100644 +--- a/arch/arm/mach-shmobile/clock-r8a7740.c ++++ b/arch/arm/mach-shmobile/clock-r8a7740.c +@@ -257,7 +257,7 @@ enum { + MSTP222, + MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, + +- MSTP329, MSTP323, ++ MSTP329, MSTP328, MSTP323, + + MSTP_NR + }; +@@ -280,6 +280,7 @@ static struct clk mstp_clks[MSTP_NR] = { + [MSTP200] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */ + + [MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ ++ [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /* FSI */ + [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ + }; + +@@ -334,6 +335,7 @@ static struct clk_lookup lookups[] = { + CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP230]), + + CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), ++ CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), + CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), + }; + +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0055-ARM-mach-shmobile-clock-r8a7740-add-USB-clock.patch b/patches.armadillo800/0055-ARM-mach-shmobile-clock-r8a7740-add-USB-clock.patch new file mode 100644 index 0000000000000..3e72e0bca4d55 --- /dev/null +++ b/patches.armadillo800/0055-ARM-mach-shmobile-clock-r8a7740-add-USB-clock.patch @@ -0,0 +1,208 @@ +From a747b7aa896100a6b9dd0dc0828c27ef344f381c Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 24 Apr 2012 02:07:47 -0700 +Subject: ARM: mach-shmobile: clock-r8a7740: add USB clock + +R8A7740 USB needs many clocks for workaround, +and it has confusing name "usb24s" and "usb24". +This "usb24s" will be used by other clocks. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit fcca3f0f007d97f095a3ebe8f209021b517309d2) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-r8a7740.c | 118 ++++++++++++++++++++++++++++++++- + 1 file changed, 116 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c +index b6fa1b7..b9b1d73 100644 +--- a/arch/arm/mach-shmobile/clock-r8a7740.c ++++ b/arch/arm/mach-shmobile/clock-r8a7740.c +@@ -47,6 +47,7 @@ + #define PLLC01CR 0xe6150028 + + #define SUBCKCR 0xe6150080 ++#define USBCKCR 0xe615008c + + #define MSTPSR0 0xe6150030 + #define MSTPSR1 0xe6150038 +@@ -181,6 +182,100 @@ static struct clk pllc1_div2_clk = { + .parent = &pllc1_clk, + }; + ++/* USB clock */ ++static struct clk *usb24s_parents[] = { ++ [0] = &system_clk, ++ [1] = &extal2_clk ++}; ++ ++static unsigned long usb24s_recalc(struct clk *clk) ++{ ++ return clk->parent->rate; ++}; ++ ++static int usb24s_enable(struct clk *clk) ++{ ++ __raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR); ++ ++ return 0; ++} ++ ++static void usb24s_disable(struct clk *clk) ++{ ++ __raw_writel(__raw_readl(USBCKCR) | (1 << 8), USBCKCR); ++} ++ ++static int usb24s_set_parent(struct clk *clk, struct clk *parent) ++{ ++ int i, ret; ++ u32 val; ++ ++ if (!clk->parent_table || !clk->parent_num) ++ return -EINVAL; ++ ++ /* Search the parent */ ++ for (i = 0; i < clk->parent_num; i++) ++ if (clk->parent_table[i] == parent) ++ break; ++ ++ if (i == clk->parent_num) ++ return -ENODEV; ++ ++ ret = clk_reparent(clk, parent); ++ if (ret < 0) ++ return ret; ++ ++ val = __raw_readl(USBCKCR); ++ val &= ~(1 << 7); ++ val |= i << 7; ++ __raw_writel(val, USBCKCR); ++ ++ return 0; ++} ++ ++static struct sh_clk_ops usb24s_clk_ops = { ++ .recalc = usb24s_recalc, ++ .enable = usb24s_enable, ++ .disable = usb24s_disable, ++ .set_parent = usb24s_set_parent, ++}; ++ ++static struct clk usb24s_clk = { ++ .ops = &usb24s_clk_ops, ++ .parent_table = usb24s_parents, ++ .parent_num = ARRAY_SIZE(usb24s_parents), ++ .parent = &system_clk, ++}; ++ ++static unsigned long usb24_recalc(struct clk *clk) ++{ ++ return clk->parent->rate / ++ ((__raw_readl(USBCKCR) & (1 << 6)) ? 1 : 2); ++}; ++ ++static int usb24_set_rate(struct clk *clk, unsigned long rate) ++{ ++ u32 val; ++ ++ /* closer to which ? parent->rate or parent->rate/2 */ ++ val = __raw_readl(USBCKCR); ++ val &= ~(1 << 6); ++ val |= (rate > (clk->parent->rate / 4) * 3) << 6; ++ __raw_writel(val, USBCKCR); ++ ++ return 0; ++} ++ ++static struct sh_clk_ops usb24_clk_ops = { ++ .recalc = usb24_recalc, ++ .set_rate = usb24_set_rate, ++}; ++ ++static struct clk usb24_clk = { ++ .ops = &usb24_clk_ops, ++ .parent = &usb24s_clk, ++}; ++ + struct clk *main_clks[] = { + &extalr_clk, + &extal1_clk, +@@ -196,6 +291,8 @@ struct clk *main_clks[] = { + &pllc0_clk, + &pllc1_clk, + &pllc1_div2_clk, ++ &usb24s_clk, ++ &usb24_clk, + }; + + static void div4_kick(struct clk *clk) +@@ -223,7 +320,7 @@ static struct clk_div4_table div4_table = { + + enum { + DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP, +- DIV4_HPP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP, ++ DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP, + DIV4_NR + }; + +@@ -234,6 +331,7 @@ struct clk div4_clks[DIV4_NR] = { + [DIV4_M1] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT), + [DIV4_HP] = SH_CLK_DIV4(&pllc1_clk, FRQCRB, 4, 0x6fff, 0), + [DIV4_HPP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0), ++ [DIV4_USBP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 16, 0x6fff, 0), + [DIV4_S] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0), + [DIV4_ZB] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 8, 0x6fff, 0), + [DIV4_M3] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 4, 0x6fff, 0), +@@ -257,7 +355,9 @@ enum { + MSTP222, + MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, + +- MSTP329, MSTP328, MSTP323, ++ MSTP329, MSTP328, MSTP323, MSTP320, ++ ++ MSTP416, MSTP407, MSTP406, + + MSTP_NR + }; +@@ -282,6 +382,11 @@ static struct clk mstp_clks[MSTP_NR] = { + [MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ + [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /* FSI */ + [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ ++ [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */ ++ ++ [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */ ++ [MSTP407] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 7, 0), /* USB-Func */ ++ [MSTP406] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 6, 0), /* USB Phy */ + }; + + static struct clk_lookup lookups[] = { +@@ -300,6 +405,7 @@ static struct clk_lookup lookups[] = { + CLKDEV_CON_ID("pllc0_clk", &pllc0_clk), + CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), + CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), ++ CLKDEV_CON_ID("usb24s", &usb24s_clk), + + /* DIV4 clocks */ + CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), +@@ -337,6 +443,14 @@ static struct clk_lookup lookups[] = { + CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), + CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), + CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), ++ CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]), ++ ++ /* ICK */ ++ CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]), ++ CLKDEV_ICK_ID("func", "renesas_usbhs", &mstp_clks[MSTP407]), ++ CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]), ++ CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]), ++ CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk), + }; + + void __init r8a7740_clock_init(u8 md_ck) +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0056-ARM-mach-shmobile-clock-r8a7740-add-SDHI-clock.patch b/patches.armadillo800/0056-ARM-mach-shmobile-clock-r8a7740-add-SDHI-clock.patch new file mode 100644 index 0000000000000..86c437981cf93 --- /dev/null +++ b/patches.armadillo800/0056-ARM-mach-shmobile-clock-r8a7740-add-SDHI-clock.patch @@ -0,0 +1,57 @@ +From df046bb39c81fb474109a85f21b35345df0b9441 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 24 Apr 2012 02:08:11 -0700 +Subject: ARM: mach-shmobile: clock-r8a7740: add SDHI clock + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 19ad322de262c810463aeb8769c66474d8b68210) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-r8a7740.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c +index b9b1d73..86f7147 100644 +--- a/arch/arm/mach-shmobile/clock-r8a7740.c ++++ b/arch/arm/mach-shmobile/clock-r8a7740.c +@@ -356,8 +356,9 @@ enum { + MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, + + MSTP329, MSTP328, MSTP323, MSTP320, ++ MSTP314, MSTP313, + +- MSTP416, MSTP407, MSTP406, ++ MSTP416, MSTP415, MSTP407, MSTP406, + + MSTP_NR + }; +@@ -383,8 +384,11 @@ static struct clk mstp_clks[MSTP_NR] = { + [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /* FSI */ + [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ + [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */ ++ [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */ ++ [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */ + + [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */ ++ [MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 15, 0), /* SDHI2 */ + [MSTP407] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 7, 0), /* USB-Func */ + [MSTP406] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 6, 0), /* USB Phy */ + }; +@@ -444,6 +448,10 @@ static struct clk_lookup lookups[] = { + CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), + CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), + CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]), ++ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), ++ CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), ++ ++ CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]), + + /* ICK */ + CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]), +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0057-ARM-mach-shmobile-clock-r8a7740-add-MMCIF-clock.patch b/patches.armadillo800/0057-ARM-mach-shmobile-clock-r8a7740-add-MMCIF-clock.patch new file mode 100644 index 0000000000000..e0c1a387c076b --- /dev/null +++ b/patches.armadillo800/0057-ARM-mach-shmobile-clock-r8a7740-add-MMCIF-clock.patch @@ -0,0 +1,48 @@ +From 3b4d84a8de5adaa8ec1b4db8b3409fc75340bd7f Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 24 Apr 2012 02:08:29 -0700 +Subject: ARM: mach-shmobile: clock-r8a7740: add MMCIF clock + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit f2c2d7e9210c4a82336b208adc88630cd0e77f57) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-r8a7740.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c +index 86f7147..89a2f9d 100644 +--- a/arch/arm/mach-shmobile/clock-r8a7740.c ++++ b/arch/arm/mach-shmobile/clock-r8a7740.c +@@ -356,7 +356,7 @@ enum { + MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, + + MSTP329, MSTP328, MSTP323, MSTP320, +- MSTP314, MSTP313, ++ MSTP314, MSTP313, MSTP312, + + MSTP416, MSTP415, MSTP407, MSTP406, + +@@ -386,6 +386,7 @@ static struct clk mstp_clks[MSTP_NR] = { + [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */ + [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */ + [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */ ++ [MSTP312] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMC */ + + [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */ + [MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 15, 0), /* SDHI2 */ +@@ -450,6 +451,7 @@ static struct clk_lookup lookups[] = { + CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]), + CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), + CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), ++ CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP312]), + + CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]), + +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0058-ARM-mach-shmobile-clock-r8a7740-use-followparent_rec.patch b/patches.armadillo800/0058-ARM-mach-shmobile-clock-r8a7740-use-followparent_rec.patch new file mode 100644 index 0000000000000..db699188a7dde --- /dev/null +++ b/patches.armadillo800/0058-ARM-mach-shmobile-clock-r8a7740-use-followparent_rec.patch @@ -0,0 +1,48 @@ +From 02b6fac5cb1a97bb8851976abdd8a229a852907f Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 6 May 2012 18:12:41 -0700 +Subject: ARM: mach-shmobile: clock-r8a7740: use followparent_recalc on usb24s + +If the clocks is always same value as the parent clock, +we can use followparent_recalc() for .recalc + +Reported-by: Paul Mundt <lethal@linux-sh.org> +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Reviewed-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit c8241085e8606a14ef48e6d99556133c48aaddaf) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-r8a7740.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c +index 89a2f9d..81b54a6 100644 +--- a/arch/arm/mach-shmobile/clock-r8a7740.c ++++ b/arch/arm/mach-shmobile/clock-r8a7740.c +@@ -188,11 +188,6 @@ static struct clk *usb24s_parents[] = { + [1] = &extal2_clk + }; + +-static unsigned long usb24s_recalc(struct clk *clk) +-{ +- return clk->parent->rate; +-}; +- + static int usb24s_enable(struct clk *clk) + { + __raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR); +@@ -234,7 +229,7 @@ static int usb24s_set_parent(struct clk *clk, struct clk *parent) + } + + static struct sh_clk_ops usb24s_clk_ops = { +- .recalc = usb24s_recalc, ++ .recalc = followparent_recalc, + .enable = usb24s_enable, + .disable = usb24s_disable, + .set_parent = usb24s_set_parent, +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0059-ARM-mach-shmobile-add-armadillo800eva-board-support.patch b/patches.armadillo800/0059-ARM-mach-shmobile-add-armadillo800eva-board-support.patch new file mode 100644 index 0000000000000..f40a99937f618 --- /dev/null +++ b/patches.armadillo800/0059-ARM-mach-shmobile-add-armadillo800eva-board-support.patch @@ -0,0 +1,232 @@ +From 6dbc9d7efd3ddd2dbc0a1b95b3a237173df5e1d8 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 6 Apr 2012 01:28:59 -0700 +Subject: ARM: mach-shmobile: add armadillo800eva board support. + +This adds very basic armadillo800eva board (R-Mobile A1) support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 4d22e564ca7bb5c7340c782aedd93bed99f3fb41) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/Kconfig | 11 +- + arch/arm/mach-shmobile/Makefile | 1 + + arch/arm/mach-shmobile/board-armadillo800eva.c | 154 +++++++++++++++++++++++++ + 3 files changed, 164 insertions(+), 2 deletions(-) + create mode 100644 arch/arm/mach-shmobile/board-armadillo800eva.c + +diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig +index 2cda0c2..799e996 100644 +--- a/arch/arm/mach-shmobile/Kconfig ++++ b/arch/arm/mach-shmobile/Kconfig +@@ -95,6 +95,11 @@ config MACH_BONITO + select ARCH_REQUIRE_GPIOLIB + depends on ARCH_R8A7740 + ++config MACH_ARMADILLO800EVA ++ bool "Armadillo-800 EVA board" ++ depends on ARCH_R8A7740 ++ select ARCH_REQUIRE_GPIOLIB ++ + config MACH_MARZEN + bool "MARZEN board" + depends on ARCH_R8A7779 +@@ -112,7 +117,8 @@ config MEMORY_START + hex "Physical memory start address" + default "0x50000000" if MACH_G3EVM + default "0x40000000" if MACH_G4EVM || MACH_AP4EVB || MACH_AG5EVM || \ +- MACH_MACKEREL || MACH_BONITO ++ MACH_MACKEREL || MACH_BONITO || \ ++ MACH_ARMADILLO800EVA + default "0x41000000" if MACH_KOTA2 + default "0x00000000" + ---help--- +@@ -124,7 +130,8 @@ config MEMORY_SIZE + hex "Physical memory size" + default "0x08000000" if MACH_G3EVM + default "0x08000000" if MACH_G4EVM +- default "0x20000000" if MACH_AG5EVM || MACH_BONITO ++ default "0x20000000" if MACH_AG5EVM || MACH_BONITO || \ ++ MACH_ARMADILLO800EVA + default "0x1e000000" if MACH_KOTA2 + default "0x10000000" if MACH_AP4EVB || MACH_MACKEREL + default "0x04000000" +diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile +index 53846a1e..b39033b 100644 +--- a/arch/arm/mach-shmobile/Makefile ++++ b/arch/arm/mach-shmobile/Makefile +@@ -50,6 +50,7 @@ obj-$(CONFIG_MACH_MACKEREL) += board-mackerel.o + obj-$(CONFIG_MACH_KOTA2) += board-kota2.o + obj-$(CONFIG_MACH_BONITO) += board-bonito.o + obj-$(CONFIG_MACH_MARZEN) += board-marzen.o ++obj-$(CONFIG_MACH_ARMADILLO800EVA) += board-armadillo800eva.o + + # Framework support + obj-$(CONFIG_SMP) += $(smp-y) +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +new file mode 100644 +index 0000000..28bc259 +--- /dev/null ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -0,0 +1,154 @@ ++/* ++ * armadillo 800 eva board support ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++#include <linux/clk.h> ++#include <linux/err.h> ++#include <linux/kernel.h> ++#include <linux/platform_device.h> ++#include <linux/gpio.h> ++#include <mach/common.h> ++#include <mach/irqs.h> ++#include <asm/page.h> ++#include <asm/mach-types.h> ++#include <asm/mach/arch.h> ++#include <asm/mach/map.h> ++#include <asm/mach/time.h> ++#include <asm/hardware/cache-l2x0.h> ++#include <mach/r8a7740.h> ++ ++/* ++ * CON1 Camera Module ++ * CON2 Extension Bus ++ * CON3 HDMI Output ++ * CON4 Composite Video Output ++ * CON5 H-UDI JTAG ++ * CON6 ARM JTAG ++ * CON7 SD1 ++ * CON8 SD2 ++ * CON9 RTC BackUp ++ * CON10 Monaural Mic Input ++ * CON11 Stereo Headphone Output ++ * CON12 Audio Line Output(L) ++ * CON13 Audio Line Output(R) ++ * CON14 AWL13 Module ++ * CON15 Extension ++ * CON16 LCD1 ++ * CON17 LCD2 ++ * CON19 Power Input ++ * CON20 USB1 ++ * CON21 USB2 ++ * CON22 Serial ++ * CON23 LAN ++ * CON24 USB3 ++ * LED1 Camera LED(Yellow) ++ * LED2 Power LED (Green) ++ * ED3-LED6 User LED(Yellow) ++ * LED7 LAN link LED(Green) ++ * LED8 LAN activity LED(Yellow) ++ */ ++ ++/* ++ * DipSwitch ++ * ++ * SW1 ++ * ++ * -12345678-+---------------+---------------------------- ++ * 1 | boot | hermit ++ * 0 | boot | OS auto boot ++ * -12345678-+---------------+---------------------------- ++ * 00 | boot device | eMMC ++ * 10 | boot device | SDHI0 (CON7) ++ * 01 | boot device | - ++ * 11 | boot device | Extension Buss (CS0) ++ * -12345678-+---------------+---------------------------- ++ * 0 | Extension Bus | D8-D15 disable, eMMC enable ++ * 1 | Extension Bus | D8-D15 enable, eMMC disable ++ * -12345678-+---------------+---------------------------- ++ * 0 | SDHI1 | COM8 enable, COM14 disable ++ * 1 | SDHI1 | COM8 enable, COM14 disable ++ * -12345678-+---------------+---------------------------- ++ * 00 | JTAG | SH-X2 ++ * 10 | JTAG | ARM ++ * 01 | JTAG | - ++ * 11 | JTAG | Boundary Scan ++ *-----------+---------------+---------------------------- ++ */ ++ ++/* ++ * board devices ++ */ ++static struct platform_device *eva_devices[] __initdata = { ++}; ++ ++/* ++ * board init ++ */ ++static void __init eva_init(void) ++{ ++ r8a7740_pinmux_init(); ++ ++ /* SCIFA1 */ ++ gpio_request(GPIO_FN_SCIFA1_RXD, NULL); ++ gpio_request(GPIO_FN_SCIFA1_TXD, NULL); ++ ++#ifdef CONFIG_CACHE_L2X0 ++ /* Early BRESP enable, Shared attribute override enable, 32K*8way */ ++ l2x0_init(__io(0xf0002000), 0x40440000, 0x82000fff); ++#endif ++ ++ r8a7740_add_standard_devices(); ++ ++ platform_add_devices(eva_devices, ++ ARRAY_SIZE(eva_devices)); ++} ++ ++static void __init eva_earlytimer_init(void) ++{ ++ struct clk *xtal1; ++ ++ r8a7740_clock_init(MD_CK0 | MD_CK2); ++ ++ xtal1 = clk_get(NULL, "extal1"); ++ if (!IS_ERR(xtal1)) { ++ /* armadillo 800 eva extal1 is 24MHz */ ++ clk_set_rate(xtal1, 24000000); ++ clk_put(xtal1); ++ } ++ ++ shmobile_earlytimer_init(); ++} ++ ++static void __init eva_add_early_devices(void) ++{ ++ r8a7740_add_early_devices(); ++ ++ /* override timer setup with board-specific code */ ++ shmobile_timer.init = eva_earlytimer_init; ++} ++ ++MACHINE_START(ARMADILLO800EVA, "armadillo800eva") ++ .map_io = r8a7740_map_io, ++ .init_early = eva_add_early_devices, ++ .init_irq = r8a7740_init_irq, ++ .handle_irq = shmobile_handle_irq_intc, ++ .init_machine = eva_init, ++ .timer = &shmobile_timer, ++MACHINE_END +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0060-ARM-mach-shmobile-armadillo800eva-add-defconfig.patch b/patches.armadillo800/0060-ARM-mach-shmobile-armadillo800eva-add-defconfig.patch new file mode 100644 index 0000000000000..2ee612615feab --- /dev/null +++ b/patches.armadillo800/0060-ARM-mach-shmobile-armadillo800eva-add-defconfig.patch @@ -0,0 +1,169 @@ +From 90660861a7540365f6c7c4412f30a74e4a7d9dd3 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 6 Apr 2012 01:29:36 -0700 +Subject: ARM: mach-shmobile: armadillo800eva: add defconfig + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit edc4910171f332466fa8f164de3d2395d80163db) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/configs/armadillo800eva_defconfig | 143 +++++++++++++++++++++++++++++ + 1 file changed, 143 insertions(+) + create mode 100644 arch/arm/configs/armadillo800eva_defconfig + +diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig +new file mode 100644 +index 0000000..0d20749 +--- /dev/null ++++ b/arch/arm/configs/armadillo800eva_defconfig +@@ -0,0 +1,143 @@ ++CONFIG_EXPERIMENTAL=y ++CONFIG_SYSVIPC=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=16 ++# CONFIG_UTS_NS is not set ++# CONFIG_IPC_NS is not set ++# CONFIG_USER_NS is not set ++# CONFIG_PID_NS is not set ++CONFIG_SYSFS_DEPRECATED=y ++CONFIG_SYSFS_DEPRECATED_V2=y ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_KALLSYMS_ALL=y ++CONFIG_SLAB=y ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODULE_FORCE_UNLOAD=y ++# CONFIG_BLK_DEV_BSG is not set ++# CONFIG_IOSCHED_DEADLINE is not set ++# CONFIG_IOSCHED_CFQ is not set ++CONFIG_ARCH_SHMOBILE=y ++CONFIG_ARCH_R8A7740=y ++CONFIG_MACH_ARMADILLO800EVA=y ++# CONFIG_SH_TIMER_TMU is not set ++# CONFIG_ARM_THUMB is not set ++CONFIG_CPU_BPREDICT_DISABLE=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_ERRATA_430973=y ++CONFIG_ARM_ERRATA_458693=y ++CONFIG_ARM_ERRATA_460075=y ++CONFIG_ARM_ERRATA_720789=y ++CONFIG_ARM_ERRATA_743622=y ++CONFIG_ARM_ERRATA_751472=y ++CONFIG_ARM_ERRATA_754322=y ++CONFIG_AEABI=y ++# CONFIG_OABI_COMPAT is not set ++CONFIG_FORCE_MAX_ZONEORDER=13 ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096" ++CONFIG_CMDLINE_FORCE=y ++CONFIG_KEXEC=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++# CONFIG_SUSPEND is not set ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_INET=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++# CONFIG_INET_LRO is not set ++# CONFIG_INET_DIAG is not set ++# CONFIG_IPV6 is not set ++# CONFIG_WIRELESS is not set ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++CONFIG_MD=y ++CONFIG_BLK_DEV_DM=y ++CONFIG_NETDEVICES=y ++# CONFIG_NET_VENDOR_BROADCOM is not set ++# CONFIG_NET_VENDOR_CHELSIO is not set ++# CONFIG_NET_VENDOR_FARADAY is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++CONFIG_SH_ETH=y ++# CONFIG_NET_VENDOR_SEEQ is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++# CONFIG_WLAN is not set ++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO=y ++# CONFIG_INPUT_MOUSE is not set ++CONFIG_INPUT_TOUCHSCREEN=y ++CONFIG_TOUCHSCREEN_ST1232=y ++# CONFIG_SERIO is not set ++# CONFIG_LEGACY_PTYS is not set ++CONFIG_SERIAL_SH_SCI=y ++CONFIG_SERIAL_SH_SCI_NR_UARTS=8 ++CONFIG_SERIAL_SH_SCI_CONSOLE=y ++# CONFIG_HW_RANDOM is not set ++CONFIG_I2C=y ++CONFIG_I2C_SH_MOBILE=y ++# CONFIG_HWMON is not set ++CONFIG_FB=y ++CONFIG_FB_MODE_HELPERS=y ++CONFIG_FB_SH_MOBILE_LCDC=y ++CONFIG_LCD_CLASS_DEVICE=y ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y ++CONFIG_LOGO=y ++# CONFIG_LOGO_LINUX_MONO is not set ++# CONFIG_LOGO_LINUX_VGA16 is not set ++CONFIG_SOUND=y ++CONFIG_SND=y ++# CONFIG_SND_SUPPORT_OLD_API is not set ++# CONFIG_SND_VERBOSE_PROCFS is not set ++# CONFIG_SND_DRIVERS is not set ++# CONFIG_SND_ARM is not set ++CONFIG_SND_SOC=y ++CONFIG_SND_SOC_SH4_FSI=y ++# CONFIG_HID_SUPPORT is not set ++# CONFIG_USB_SUPPORT is not set ++CONFIG_UIO=y ++CONFIG_UIO_PDRV_GENIRQ=y ++# CONFIG_DNOTIFY is not set ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_TMPFS=y ++# CONFIG_MISC_FILESYSTEMS is not set ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_V4_1=y ++CONFIG_ROOT_NFS=y ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_ISO8859_1=y ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_DEBUG_SECTION_MISMATCH=y ++CONFIG_DEBUG_KERNEL=y ++CONFIG_LOCKUP_DETECTOR=y ++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_SCHED_DEBUG is not set ++CONFIG_DEBUG_KMEMLEAK=y ++CONFIG_DEBUG_SPINLOCK=y ++CONFIG_DEBUG_INFO=y ++# CONFIG_FTRACE is not set ++CONFIG_CRYPTO=y ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_MD5=y ++CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_ANSI_CPRNG=y ++CONFIG_XZ_DEC=y +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0061-ARM-mach-shmobile-armadillo800eva-add-support-LCDC0.patch b/patches.armadillo800/0061-ARM-mach-shmobile-armadillo800eva-add-support-LCDC0.patch new file mode 100644 index 0000000000000..7aab5bd8bc305 --- /dev/null +++ b/patches.armadillo800/0061-ARM-mach-shmobile-armadillo800eva-add-support-LCDC0.patch @@ -0,0 +1,160 @@ +From 4dac8081711cdd9f55ee3191344bff84f7b573ff Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 6 Apr 2012 01:30:09 -0700 +Subject: ARM: mach-shmobile: armadillo800eva: add support LCDC0 + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit dad29d1c29b7a8699403e45822065d979309f756) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 105 +++++++++++++++++++++++++ + 1 file changed, 105 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index 28bc259..5cc17a8 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -24,6 +24,7 @@ + #include <linux/kernel.h> + #include <linux/platform_device.h> + #include <linux/gpio.h> ++#include <linux/videodev2.h> + #include <mach/common.h> + #include <mach/irqs.h> + #include <asm/page.h> +@@ -33,6 +34,7 @@ + #include <asm/mach/time.h> + #include <asm/hardware/cache-l2x0.h> + #include <mach/r8a7740.h> ++#include <video/sh_mobile_lcdc.h> + + /* + * CON1 Camera Module +@@ -92,10 +94,66 @@ + *-----------+---------------+---------------------------- + */ + ++/* LCDC */ ++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 = intcs_evt2irq(0x580), ++ .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 = ~0, ++ }, ++}; ++ + /* + * board devices + */ + static struct platform_device *eva_devices[] __initdata = { ++ &lcdc0_device, + }; + + /* +@@ -109,6 +167,53 @@ static void __init eva_init(void) + gpio_request(GPIO_FN_SCIFA1_RXD, NULL); + gpio_request(GPIO_FN_SCIFA1_TXD, NULL); + ++ /* LCDC0 */ ++ gpio_request(GPIO_FN_LCDC0_SELECT, NULL); ++ gpio_request(GPIO_FN_LCD0_D0, NULL); ++ gpio_request(GPIO_FN_LCD0_D1, NULL); ++ gpio_request(GPIO_FN_LCD0_D2, NULL); ++ gpio_request(GPIO_FN_LCD0_D3, NULL); ++ gpio_request(GPIO_FN_LCD0_D4, NULL); ++ gpio_request(GPIO_FN_LCD0_D5, NULL); ++ gpio_request(GPIO_FN_LCD0_D6, NULL); ++ gpio_request(GPIO_FN_LCD0_D7, NULL); ++ gpio_request(GPIO_FN_LCD0_D8, NULL); ++ gpio_request(GPIO_FN_LCD0_D9, NULL); ++ gpio_request(GPIO_FN_LCD0_D10, NULL); ++ gpio_request(GPIO_FN_LCD0_D11, NULL); ++ gpio_request(GPIO_FN_LCD0_D12, NULL); ++ gpio_request(GPIO_FN_LCD0_D13, NULL); ++ gpio_request(GPIO_FN_LCD0_D14, NULL); ++ gpio_request(GPIO_FN_LCD0_D15, NULL); ++ gpio_request(GPIO_FN_LCD0_D16, NULL); ++ gpio_request(GPIO_FN_LCD0_D17, NULL); ++ gpio_request(GPIO_FN_LCD0_D18_PORT40, NULL); ++ gpio_request(GPIO_FN_LCD0_D19_PORT4, NULL); ++ gpio_request(GPIO_FN_LCD0_D20_PORT3, NULL); ++ gpio_request(GPIO_FN_LCD0_D21_PORT2, NULL); ++ gpio_request(GPIO_FN_LCD0_D22_PORT0, NULL); ++ gpio_request(GPIO_FN_LCD0_D23_PORT1, NULL); ++ gpio_request(GPIO_FN_LCD0_DCK, NULL); ++ gpio_request(GPIO_FN_LCD0_VSYN, NULL); ++ gpio_request(GPIO_FN_LCD0_HSYN, NULL); ++ gpio_request(GPIO_FN_LCD0_DISP, NULL); ++ gpio_request(GPIO_FN_LCD0_LCLK_PORT165, NULL); ++ ++ gpio_request(GPIO_PORT61, NULL); /* LCDDON */ ++ gpio_direction_output(GPIO_PORT61, 1); ++ ++ gpio_request(GPIO_PORT202, NULL); /* LCD0_LED_CONT */ ++ gpio_direction_output(GPIO_PORT202, 0); ++ ++ /* ++ * CAUTION ++ * ++ * DBGMD/LCDC0/FSIA MUX ++ * DBGMD_SELECT_B should be set after setting PFC Function. ++ */ ++ gpio_request(GPIO_PORT176, NULL); ++ gpio_direction_output(GPIO_PORT176, 1); ++ + #ifdef CONFIG_CACHE_L2X0 + /* Early BRESP enable, Shared attribute override enable, 32K*8way */ + l2x0_init(__io(0xf0002000), 0x40440000, 0x82000fff); +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0062-ARM-mach-shmobile-armadillo800eva-add-support-gpio_k.patch b/patches.armadillo800/0062-ARM-mach-shmobile-armadillo800eva-add-support-gpio_k.patch new file mode 100644 index 0000000000000..813c5ef4c4829 --- /dev/null +++ b/patches.armadillo800/0062-ARM-mach-shmobile-armadillo800eva-add-support-gpio_k.patch @@ -0,0 +1,70 @@ +From 683089b4115c60b9b9f35ec3f5d91122a8a416e1 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 6 Apr 2012 01:31:33 -0700 +Subject: ARM: mach-shmobile: armadillo800eva: add support gpio_key + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit f7e7d31a1299e11be780f8e2d235570792849e31) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index 5cc17a8..0bce9b8 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -22,8 +22,10 @@ + #include <linux/clk.h> + #include <linux/err.h> + #include <linux/kernel.h> ++#include <linux/input.h> + #include <linux/platform_device.h> + #include <linux/gpio.h> ++#include <linux/gpio_keys.h> + #include <linux/videodev2.h> + #include <mach/common.h> + #include <mach/irqs.h> +@@ -149,11 +151,35 @@ static struct platform_device lcdc0_device = { + }, + }; + ++/* GPIO KEY */ ++#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 } ++ ++static struct gpio_keys_button gpio_buttons[] = { ++ GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW1"), ++ GPIO_KEY(KEY_BACK, GPIO_PORT100, "SW2"), ++ GPIO_KEY(KEY_MENU, GPIO_PORT97, "SW3"), ++ GPIO_KEY(KEY_HOME, GPIO_PORT98, "SW4"), ++}; ++ ++static struct gpio_keys_platform_data gpio_key_info = { ++ .buttons = gpio_buttons, ++ .nbuttons = ARRAY_SIZE(gpio_buttons), ++}; ++ ++static struct platform_device gpio_keys_device = { ++ .name = "gpio-keys", ++ .id = -1, ++ .dev = { ++ .platform_data = &gpio_key_info, ++ }, ++}; ++ + /* + * board devices + */ + static struct platform_device *eva_devices[] __initdata = { + &lcdc0_device, ++ &gpio_keys_device, + }; + + /* +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0063-ARM-mach-shmobile-armadillo800eva-add-support-sh_eth.patch b/patches.armadillo800/0063-ARM-mach-shmobile-armadillo800eva-add-support-sh_eth.patch new file mode 100644 index 0000000000000..a66c2450f1462 --- /dev/null +++ b/patches.armadillo800/0063-ARM-mach-shmobile-armadillo800eva-add-support-sh_eth.patch @@ -0,0 +1,109 @@ +From ab1150c0be9d95c57f6f03a56917c77b2af01bce Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 6 Apr 2012 01:32:02 -0700 +Subject: ARM: mach-shmobile: armadillo800eva: add support sh_eth + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit d8fed1e254ba1ed38fd2977fdac4c2e35ed5dbc1) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 58 ++++++++++++++++++++++++++ + 1 file changed, 58 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index 0bce9b8..d439e7f 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -26,6 +26,7 @@ + #include <linux/platform_device.h> + #include <linux/gpio.h> + #include <linux/gpio_keys.h> ++#include <linux/sh_eth.h> + #include <linux/videodev2.h> + #include <mach/common.h> + #include <mach/irqs.h> +@@ -96,6 +97,38 @@ + *-----------+---------------+---------------------------- + */ + ++/* Ether */ ++static struct sh_eth_plat_data sh_eth_platdata = { ++ .phy = 0x00, /* LAN8710A */ ++ .edmac_endian = EDMAC_LITTLE_ENDIAN, ++ .register_type = SH_ETH_REG_GIGABIT, ++ .phy_interface = PHY_INTERFACE_MODE_MII, ++}; ++ ++static struct resource sh_eth_resources[] = { ++ { ++ .start = 0xe9a00000, ++ .end = 0xe9a00800 - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = 0xe9a01800, ++ .end = 0xe9a02000 - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = evt2irq(0x0500), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device sh_eth_device = { ++ .name = "sh-eth", ++ .dev = { ++ .platform_data = &sh_eth_platdata, ++ }, ++ .resource = sh_eth_resources, ++ .num_resources = ARRAY_SIZE(sh_eth_resources), ++}; ++ + /* LCDC */ + static struct fb_videomode lcdc0_mode = { + .name = "AMPIER/AM-800480", +@@ -180,6 +213,7 @@ static struct platform_device gpio_keys_device = { + static struct platform_device *eva_devices[] __initdata = { + &lcdc0_device, + &gpio_keys_device, ++ &sh_eth_device, + }; + + /* +@@ -231,6 +265,30 @@ static void __init eva_init(void) + gpio_request(GPIO_PORT202, NULL); /* LCD0_LED_CONT */ + gpio_direction_output(GPIO_PORT202, 0); + ++ /* GETHER */ ++ gpio_request(GPIO_FN_ET_CRS, NULL); ++ gpio_request(GPIO_FN_ET_MDC, NULL); ++ gpio_request(GPIO_FN_ET_MDIO, NULL); ++ gpio_request(GPIO_FN_ET_TX_ER, NULL); ++ gpio_request(GPIO_FN_ET_RX_ER, NULL); ++ gpio_request(GPIO_FN_ET_ERXD0, NULL); ++ gpio_request(GPIO_FN_ET_ERXD1, NULL); ++ gpio_request(GPIO_FN_ET_ERXD2, NULL); ++ gpio_request(GPIO_FN_ET_ERXD3, NULL); ++ gpio_request(GPIO_FN_ET_TX_CLK, NULL); ++ gpio_request(GPIO_FN_ET_TX_EN, NULL); ++ gpio_request(GPIO_FN_ET_ETXD0, NULL); ++ gpio_request(GPIO_FN_ET_ETXD1, NULL); ++ gpio_request(GPIO_FN_ET_ETXD2, NULL); ++ gpio_request(GPIO_FN_ET_ETXD3, NULL); ++ gpio_request(GPIO_FN_ET_PHY_INT, NULL); ++ gpio_request(GPIO_FN_ET_COL, NULL); ++ gpio_request(GPIO_FN_ET_RX_DV, NULL); ++ gpio_request(GPIO_FN_ET_RX_CLK, NULL); ++ ++ gpio_request(GPIO_PORT18, NULL); /* PHY_RST */ ++ gpio_direction_output(GPIO_PORT18, 1); ++ + /* + * CAUTION + * +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0064-ARM-mach-shmobile-armadillo800eva-add-support-ST1232.patch b/patches.armadillo800/0064-ARM-mach-shmobile-armadillo800eva-add-support-ST1232.patch new file mode 100644 index 0000000000000..3dc4e30a947a7 --- /dev/null +++ b/patches.armadillo800/0064-ARM-mach-shmobile-armadillo800eva-add-support-ST1232.patch @@ -0,0 +1,59 @@ +From 6c075ffc555411ed9a75c338058837c617323f16 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 6 Apr 2012 01:30:42 -0700 +Subject: ARM: mach-shmobile: armadillo800eva: add support ST1232 + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Reviewed-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 46cf668748070e54879d528fa58107abc835dff3) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index d439e7f..4d066f9 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -207,6 +207,14 @@ static struct platform_device gpio_keys_device = { + }, + }; + ++/* I2C */ ++static struct i2c_board_info i2c0_devices[] = { ++ { ++ I2C_BOARD_INFO("st1232-ts", 0x55), ++ .irq = evt2irq(0x0340), ++ }, ++}; ++ + /* + * board devices + */ +@@ -265,6 +273,11 @@ static void __init eva_init(void) + gpio_request(GPIO_PORT202, NULL); /* LCD0_LED_CONT */ + gpio_direction_output(GPIO_PORT202, 0); + ++ /* Touchscreen */ ++ gpio_request(GPIO_FN_IRQ10, NULL); /* TP_INT */ ++ gpio_request(GPIO_PORT166, NULL); /* TP_RST_B */ ++ gpio_direction_output(GPIO_PORT166, 1); ++ + /* GETHER */ + gpio_request(GPIO_FN_ET_CRS, NULL); + gpio_request(GPIO_FN_ET_MDC, NULL); +@@ -303,6 +316,8 @@ static void __init eva_init(void) + l2x0_init(__io(0xf0002000), 0x40440000, 0x82000fff); + #endif + ++ i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices)); ++ + r8a7740_add_standard_devices(); + + platform_add_devices(eva_devices, +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0065-ARM-mach-shmobile-armadillo800eva-add-USB-function-s.patch b/patches.armadillo800/0065-ARM-mach-shmobile-armadillo800eva-add-USB-function-s.patch new file mode 100644 index 0000000000000..f153b6ecad422 --- /dev/null +++ b/patches.armadillo800/0065-ARM-mach-shmobile-armadillo800eva-add-USB-function-s.patch @@ -0,0 +1,326 @@ +From 1dae1324b5c1a1b5c27de07729b9b52a61037b3e Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 24 Apr 2012 02:09:08 -0700 +Subject: ARM: mach-shmobile: armadillo800eva: add USB function support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 1c96293e9f8b8ec9620201bcf7f776f0e0f89edb) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 247 ++++++++++++++++++++++++- + 1 file changed, 237 insertions(+), 10 deletions(-) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index 4d066f9..1d25d5f 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -20,14 +20,17 @@ + */ + + #include <linux/clk.h> ++#include <linux/delay.h> + #include <linux/err.h> + #include <linux/kernel.h> + #include <linux/input.h> ++#include <linux/irq.h> + #include <linux/platform_device.h> + #include <linux/gpio.h> + #include <linux/gpio_keys.h> + #include <linux/sh_eth.h> + #include <linux/videodev2.h> ++#include <linux/usb/renesas_usbhs.h> + #include <mach/common.h> + #include <mach/irqs.h> + #include <asm/page.h> +@@ -90,6 +93,9 @@ + * 0 | SDHI1 | COM8 enable, COM14 disable + * 1 | SDHI1 | COM8 enable, COM14 disable + * -12345678-+---------------+---------------------------- ++ * 0 | USB0 | COM20 enable, COM24 disable ++ * 1 | USB0 | COM20 disable, COM24 enable ++ * -12345678-+---------------+---------------------------- + * 00 | JTAG | SH-X2 + * 10 | JTAG | ARM + * 01 | JTAG | - +@@ -97,6 +103,195 @@ + *-----------+---------------+---------------------------- + */ + ++/* ++ * USB function ++ * ++ * When you use USB Function, ++ * set SW1.6 ON, and connect cable to CN24. ++ * ++ * USBF needs workaround on R8A7740 chip. ++ * These are a little bit complex. ++ * see ++ * usbhsf_power_ctrl() ++ * ++ * CAUTION ++ * ++ * It uses autonomy mode for USB hotplug at this point ++ * (= usbhs_private.platform_callback.get_vbus is NULL), ++ * since we don't know what's happen on PM control ++ * on this workaround. ++ */ ++#define USBCR1 0xe605810a ++#define USBH 0xC6700000 ++#define USBH_USBCTR 0x10834 ++ ++struct usbhsf_private { ++ struct clk *phy; ++ struct clk *usb24; ++ struct clk *pci; ++ struct clk *func; ++ struct clk *host; ++ void __iomem *usbh_base; ++ struct renesas_usbhs_platform_info info; ++}; ++ ++#define usbhsf_get_priv(pdev) \ ++ container_of(renesas_usbhs_get_info(pdev), \ ++ struct usbhsf_private, info) ++ ++static int usbhsf_get_id(struct platform_device *pdev) ++{ ++ return USBHS_GADGET; ++} ++ ++static void usbhsf_power_ctrl(struct platform_device *pdev, ++ void __iomem *base, int enable) ++{ ++ struct usbhsf_private *priv = usbhsf_get_priv(pdev); ++ ++ /* ++ * Work around for USB Function. ++ * It needs USB host clock, and settings ++ */ ++ if (enable) { ++ /* ++ * enable all the related usb clocks ++ * for usb workaround ++ */ ++ clk_enable(priv->usb24); ++ clk_enable(priv->pci); ++ clk_enable(priv->host); ++ clk_enable(priv->func); ++ clk_enable(priv->phy); ++ ++ /* ++ * set USBCR1 ++ * ++ * Port1 is driven by USB function, ++ * Port2 is driven by USB HOST ++ * One HOST (Port1 or Port2 is HOST) ++ * USB PLL input clock = 24MHz ++ */ ++ __raw_writew(0xd750, USBCR1); ++ mdelay(1); ++ ++ /* ++ * start USB Host ++ */ ++ __raw_writel(0x0000000c, priv->usbh_base + USBH_USBCTR); ++ __raw_writel(0x00000008, priv->usbh_base + USBH_USBCTR); ++ mdelay(10); ++ ++ /* ++ * USB PHY Power ON ++ */ ++ __raw_writew(0xd770, USBCR1); ++ __raw_writew(0x4000, base + 0x102); /* USBF :: SUSPMODE */ ++ ++ } else { ++ __raw_writel(0x0000010f, priv->usbh_base + USBH_USBCTR); ++ __raw_writew(0xd7c0, USBCR1); /* GPIO */ ++ ++ clk_disable(priv->phy); ++ clk_disable(priv->func); /* usb work around */ ++ clk_disable(priv->host); /* usb work around */ ++ clk_disable(priv->pci); /* usb work around */ ++ clk_disable(priv->usb24); /* usb work around */ ++ } ++} ++ ++static void usbhsf_hardware_exit(struct platform_device *pdev) ++{ ++ struct usbhsf_private *priv = usbhsf_get_priv(pdev); ++ ++ if (!IS_ERR(priv->phy)) ++ clk_put(priv->phy); ++ if (!IS_ERR(priv->usb24)) ++ clk_put(priv->usb24); ++ if (!IS_ERR(priv->pci)) ++ clk_put(priv->pci); ++ if (!IS_ERR(priv->host)) ++ clk_put(priv->host); ++ if (!IS_ERR(priv->func)) ++ clk_put(priv->func); ++ if (priv->usbh_base) ++ iounmap(priv->usbh_base); ++ ++ priv->phy = NULL; ++ priv->usb24 = NULL; ++ priv->pci = NULL; ++ priv->host = NULL; ++ priv->func = NULL; ++ priv->usbh_base = NULL; ++} ++ ++static int usbhsf_hardware_init(struct platform_device *pdev) ++{ ++ struct usbhsf_private *priv = usbhsf_get_priv(pdev); ++ ++ priv->phy = clk_get(&pdev->dev, "phy"); ++ priv->usb24 = clk_get(&pdev->dev, "usb24"); ++ priv->pci = clk_get(&pdev->dev, "pci"); ++ priv->func = clk_get(&pdev->dev, "func"); ++ priv->host = clk_get(&pdev->dev, "host"); ++ priv->usbh_base = ioremap_nocache(USBH, 0x20000); ++ ++ if (IS_ERR(priv->phy) || ++ IS_ERR(priv->usb24) || ++ IS_ERR(priv->pci) || ++ IS_ERR(priv->host) || ++ IS_ERR(priv->func) || ++ !priv->usbh_base) { ++ dev_err(&pdev->dev, "USB clock setting failed\n"); ++ usbhsf_hardware_exit(pdev); ++ return -EIO; ++ } ++ ++ /* usb24 use 1/1 of parent clock (= usb24s = 24MHz) */ ++ clk_set_rate(priv->usb24, ++ clk_get_rate(clk_get_parent(priv->usb24))); ++ ++ return 0; ++} ++ ++static struct usbhsf_private usbhsf_private = { ++ .info = { ++ .platform_callback = { ++ .get_id = usbhsf_get_id, ++ .hardware_init = usbhsf_hardware_init, ++ .hardware_exit = usbhsf_hardware_exit, ++ .power_ctrl = usbhsf_power_ctrl, ++ }, ++ .driver_param = { ++ .buswait_bwait = 5, ++ .detection_delay = 5, ++ }, ++ } ++}; ++ ++static struct resource usbhsf_resources[] = { ++ { ++ .name = "USBHS", ++ .start = 0xe6890000, ++ .end = 0xe6890104 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = evt2irq(0x0A20), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device usbhsf_device = { ++ .name = "renesas_usbhs", ++ .dev = { ++ .platform_data = &usbhsf_private.info, ++ }, ++ .id = -1, ++ .num_resources = ARRAY_SIZE(usbhsf_resources), ++ .resource = usbhsf_resources, ++}; ++ + /* Ether */ + static struct sh_eth_plat_data sh_eth_platdata = { + .phy = 0x00, /* LAN8710A */ +@@ -224,11 +419,41 @@ static struct platform_device *eva_devices[] __initdata = { + &sh_eth_device, + }; + ++static void __init eva_clock_init(void) ++{ ++ struct clk *system = clk_get(NULL, "system_clk"); ++ struct clk *xtal1 = clk_get(NULL, "extal1"); ++ struct clk *usb24s = clk_get(NULL, "usb24s"); ++ ++ if (IS_ERR(system) || ++ IS_ERR(xtal1) || ++ IS_ERR(usb24s)) { ++ pr_err("armadillo800eva board clock init failed\n"); ++ goto clock_error; ++ } ++ ++ /* armadillo 800 eva extal1 is 24MHz */ ++ clk_set_rate(xtal1, 24000000); ++ ++ /* usb24s use extal1 (= system) clock (= 24MHz) */ ++ clk_set_parent(usb24s, system); ++ ++clock_error: ++ if (!IS_ERR(system)) ++ clk_put(system); ++ if (!IS_ERR(xtal1)) ++ clk_put(xtal1); ++ if (!IS_ERR(usb24s)) ++ clk_put(usb24s); ++} ++ + /* + * board init + */ + static void __init eva_init(void) + { ++ eva_clock_init(); ++ + r8a7740_pinmux_init(); + + /* SCIFA1 */ +@@ -302,6 +527,18 @@ static void __init eva_init(void) + gpio_request(GPIO_PORT18, NULL); /* PHY_RST */ + gpio_direction_output(GPIO_PORT18, 1); + ++ /* USB */ ++ gpio_request(GPIO_PORT159, NULL); /* USB_DEVICE_MODE */ ++ gpio_direction_input(GPIO_PORT159); ++ ++ if (gpio_get_value(GPIO_PORT159)) { ++ /* USB Host */ ++ } else { ++ /* USB Func */ ++ gpio_request(GPIO_FN_VBUS, NULL); ++ platform_device_register(&usbhsf_device); ++ } ++ + /* + * CAUTION + * +@@ -326,17 +563,7 @@ static void __init eva_init(void) + + static void __init eva_earlytimer_init(void) + { +- struct clk *xtal1; +- + r8a7740_clock_init(MD_CK0 | MD_CK2); +- +- xtal1 = clk_get(NULL, "extal1"); +- if (!IS_ERR(xtal1)) { +- /* armadillo 800 eva extal1 is 24MHz */ +- clk_set_rate(xtal1, 24000000); +- clk_put(xtal1); +- } +- + shmobile_earlytimer_init(); + } + +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0066-ARM-mach-shmobile-armadillo800eva-add-SDHI0-support.patch b/patches.armadillo800/0066-ARM-mach-shmobile-armadillo800eva-add-SDHI0-support.patch new file mode 100644 index 0000000000000..d98a57088be6c --- /dev/null +++ b/patches.armadillo800/0066-ARM-mach-shmobile-armadillo800eva-add-SDHI0-support.patch @@ -0,0 +1,129 @@ +From 4cc08f83ce664539a9c3dab8a1b486002346ee83 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 24 Apr 2012 02:09:19 -0700 +Subject: ARM: mach-shmobile: armadillo800eva: add SDHI0 support + +On armadillo800eva board, +CD (= Card Detect) pin is not connected to SDHI0_CD. +Then, we can use IRQ31 as card detect irq, +but it needs chattering removal operation. +We should use IRQ card detect in the future, +but this patch use polling mode at this point. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 49c01112d6afdb679276c172ffcd4f1205c1ff97) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 71 ++++++++++++++++++++++++++ + 1 file changed, 71 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index 1d25d5f..ed85686 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -31,6 +31,9 @@ + #include <linux/sh_eth.h> + #include <linux/videodev2.h> + #include <linux/usb/renesas_usbhs.h> ++#include <linux/mfd/tmio.h> ++#include <linux/mmc/host.h> ++#include <linux/mmc/sh_mobile_sdhi.h> + #include <mach/common.h> + #include <mach/irqs.h> + #include <asm/page.h> +@@ -402,6 +405,55 @@ static struct platform_device gpio_keys_device = { + }, + }; + ++/* SDHI0 */ ++/* ++ * FIXME ++ * ++ * It use polling mode here, since ++ * CD (= Card Detect) pin is not connected to SDHI0_CD. ++ * We can use IRQ31 as card detect irq, ++ * but it needs chattering removal operation ++ */ ++#define IRQ31 evt2irq(0x33E0) ++static struct sh_mobile_sdhi_info sdhi0_info = { ++ .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |\ ++ MMC_CAP_NEEDS_POLL, ++ .tmio_ocr_mask = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34, ++ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT, ++}; ++ ++static struct resource sdhi0_resources[] = { ++ { ++ .name = "SDHI0", ++ .start = 0xe6850000, ++ .end = 0xe6850100 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ /* ++ * no SH_MOBILE_SDHI_IRQ_CARD_DETECT here ++ */ ++ { ++ .name = SH_MOBILE_SDHI_IRQ_SDCARD, ++ .start = evt2irq(0x0E20), ++ .flags = IORESOURCE_IRQ, ++ }, ++ { ++ .name = SH_MOBILE_SDHI_IRQ_SDIO, ++ .start = evt2irq(0x0E40), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device sdhi0_device = { ++ .name = "sh_mobile_sdhi", ++ .id = 0, ++ .dev = { ++ .platform_data = &sdhi0_info, ++ }, ++ .num_resources = ARRAY_SIZE(sdhi0_resources), ++ .resource = sdhi0_resources, ++}; ++ + /* I2C */ + static struct i2c_board_info i2c0_devices[] = { + { +@@ -417,6 +469,7 @@ static struct platform_device *eva_devices[] __initdata = { + &lcdc0_device, + &gpio_keys_device, + &sh_eth_device, ++ &sdhi0_device, + }; + + static void __init eva_clock_init(void) +@@ -539,6 +592,24 @@ static void __init eva_init(void) + platform_device_register(&usbhsf_device); + } + ++ /* SDHI0 */ ++ gpio_request(GPIO_FN_SDHI0_CMD, NULL); ++ gpio_request(GPIO_FN_SDHI0_CLK, NULL); ++ gpio_request(GPIO_FN_SDHI0_D0, NULL); ++ gpio_request(GPIO_FN_SDHI0_D1, NULL); ++ gpio_request(GPIO_FN_SDHI0_D2, NULL); ++ gpio_request(GPIO_FN_SDHI0_D3, NULL); ++ gpio_request(GPIO_FN_SDHI0_WP, NULL); ++ ++ gpio_request(GPIO_PORT17, NULL); /* SDHI0_18/33_B */ ++ gpio_request(GPIO_PORT74, NULL); /* SDHI0_PON */ ++ gpio_request(GPIO_PORT75, NULL); /* SDSLOT1_PON */ ++ gpio_direction_output(GPIO_PORT17, 0); ++ gpio_direction_output(GPIO_PORT74, 1); ++ gpio_direction_output(GPIO_PORT75, 1); ++ ++ /* we can use GPIO_FN_IRQ31_PORT167 here for SDHI0 CD irq */ ++ + /* + * CAUTION + * +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0067-ARM-mach-shmobile-armadillo800eva-add-SDHI1-support.patch b/patches.armadillo800/0067-ARM-mach-shmobile-armadillo800eva-add-SDHI1-support.patch new file mode 100644 index 0000000000000..ff2fe866e3f91 --- /dev/null +++ b/patches.armadillo800/0067-ARM-mach-shmobile-armadillo800eva-add-SDHI1-support.patch @@ -0,0 +1,113 @@ +From 78c21b71d7b4c9b2a5b2a785aca79aee0b9ffba2 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 24 Apr 2012 02:09:31 -0700 +Subject: ARM: mach-shmobile: armadillo800eva: add SDHI1 support + +We can switch CON8/CON14 by SW1.5 +SDHI1 is CON8 (SW1.5 = ON) + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 2e3a5ef28f8182c439a5a276ff4c0883c02787f4) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 66 +++++++++++++++++++++++++- + 1 file changed, 65 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index ed85686..5f62428 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -93,7 +93,7 @@ + * 0 | Extension Bus | D8-D15 disable, eMMC enable + * 1 | Extension Bus | D8-D15 enable, eMMC disable + * -12345678-+---------------+---------------------------- +- * 0 | SDHI1 | COM8 enable, COM14 disable ++ * 0 | SDHI1 | COM8 disable, COM14 enable + * 1 | SDHI1 | COM8 enable, COM14 disable + * -12345678-+---------------+---------------------------- + * 0 | USB0 | COM20 enable, COM24 disable +@@ -454,6 +454,44 @@ static struct platform_device sdhi0_device = { + .resource = sdhi0_resources, + }; + ++/* SDHI1 */ ++static struct sh_mobile_sdhi_info sdhi1_info = { ++ .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, ++ .tmio_ocr_mask = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34, ++ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT, ++}; ++ ++static struct resource sdhi1_resources[] = { ++ [0] = { ++ .name = "SDHI1", ++ .start = 0xe6860000, ++ .end = 0xe6860100 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = evt2irq(0x0E80), ++ .flags = IORESOURCE_IRQ, ++ }, ++ [2] = { ++ .start = evt2irq(0x0EA0), ++ .flags = IORESOURCE_IRQ, ++ }, ++ [3] = { ++ .start = evt2irq(0x0EC0), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device sdhi1_device = { ++ .name = "sh_mobile_sdhi", ++ .id = 1, ++ .dev = { ++ .platform_data = &sdhi1_info, ++ }, ++ .num_resources = ARRAY_SIZE(sdhi1_resources), ++ .resource = sdhi1_resources, ++}; ++ + /* I2C */ + static struct i2c_board_info i2c0_devices[] = { + { +@@ -619,6 +657,32 @@ static void __init eva_init(void) + gpio_request(GPIO_PORT176, NULL); + gpio_direction_output(GPIO_PORT176, 1); + ++ /* ++ * We can switch CON8/CON14 by SW1.5, ++ * but it needs after DBGMD_SELECT_B ++ */ ++ gpio_request(GPIO_PORT6, NULL); ++ gpio_direction_input(GPIO_PORT6); ++ if (gpio_get_value(GPIO_PORT6)) { ++ /* CON14 enable */ ++ } else { ++ /* CON8 (SDHI1) enable */ ++ gpio_request(GPIO_FN_SDHI1_CLK, NULL); ++ gpio_request(GPIO_FN_SDHI1_CMD, NULL); ++ gpio_request(GPIO_FN_SDHI1_D0, NULL); ++ gpio_request(GPIO_FN_SDHI1_D1, NULL); ++ gpio_request(GPIO_FN_SDHI1_D2, NULL); ++ gpio_request(GPIO_FN_SDHI1_D3, NULL); ++ gpio_request(GPIO_FN_SDHI1_CD, NULL); ++ gpio_request(GPIO_FN_SDHI1_WP, NULL); ++ ++ gpio_request(GPIO_PORT16, NULL); /* SDSLOT2_PON */ ++ gpio_direction_output(GPIO_PORT16, 1); ++ ++ platform_device_register(&sdhi1_device); ++ } ++ ++ + #ifdef CONFIG_CACHE_L2X0 + /* Early BRESP enable, Shared attribute override enable, 32K*8way */ + l2x0_init(__io(0xf0002000), 0x40440000, 0x82000fff); +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0068-ARM-mach-shmobile-armadillo800eva-add-MMCIF-support.patch b/patches.armadillo800/0068-ARM-mach-shmobile-armadillo800eva-add-MMCIF-support.patch new file mode 100644 index 0000000000000..fe15b6ab9e5f1 --- /dev/null +++ b/patches.armadillo800/0068-ARM-mach-shmobile-armadillo800eva-add-MMCIF-support.patch @@ -0,0 +1,108 @@ +From 0d4e5e39563404cb97b24a37388535b6c54ac90d Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 24 Apr 2012 02:09:42 -0700 +Subject: ARM: mach-shmobile: armadillo800eva: add MMCIF support + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 0a4266bb22774bb0b6390d2633a151d996a14e77) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 57 ++++++++++++++++++++++++++ + 1 file changed, 57 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index 5f62428..0cfaec5 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -33,6 +33,7 @@ + #include <linux/usb/renesas_usbhs.h> + #include <linux/mfd/tmio.h> + #include <linux/mmc/host.h> ++#include <linux/mmc/sh_mmcif.h> + #include <linux/mmc/sh_mobile_sdhi.h> + #include <mach/common.h> + #include <mach/irqs.h> +@@ -492,6 +493,44 @@ static struct platform_device sdhi1_device = { + .resource = sdhi1_resources, + }; + ++/* MMCIF */ ++static struct sh_mmcif_plat_data sh_mmcif_plat = { ++ .sup_pclk = 0, ++ .ocr = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34, ++ .caps = MMC_CAP_4_BIT_DATA | ++ MMC_CAP_8_BIT_DATA | ++ MMC_CAP_NONREMOVABLE, ++}; ++ ++static struct resource sh_mmcif_resources[] = { ++ [0] = { ++ .name = "MMCIF", ++ .start = 0xe6bd0000, ++ .end = 0xe6bd0100 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ /* MMC ERR */ ++ .start = evt2irq(0x1AC0), ++ .flags = IORESOURCE_IRQ, ++ }, ++ [2] = { ++ /* MMC NOR */ ++ .start = evt2irq(0x1AE0), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device sh_mmcif_device = { ++ .name = "sh_mmcif", ++ .id = -1, ++ .dev = { ++ .platform_data = &sh_mmcif_plat, ++ }, ++ .num_resources = ARRAY_SIZE(sh_mmcif_resources), ++ .resource = sh_mmcif_resources, ++}; ++ + /* I2C */ + static struct i2c_board_info i2c0_devices[] = { + { +@@ -508,6 +547,7 @@ static struct platform_device *eva_devices[] __initdata = { + &gpio_keys_device, + &sh_eth_device, + &sdhi0_device, ++ &sh_mmcif_device, + }; + + static void __init eva_clock_init(void) +@@ -649,6 +689,23 @@ static void __init eva_init(void) + /* we can use GPIO_FN_IRQ31_PORT167 here for SDHI0 CD irq */ + + /* ++ * MMCIF ++ * ++ * Here doesn't care SW1.4 status, ++ * since CON2 is not mounted. ++ */ ++ gpio_request(GPIO_FN_MMC1_CLK_PORT103, NULL); ++ gpio_request(GPIO_FN_MMC1_CMD_PORT104, NULL); ++ gpio_request(GPIO_FN_MMC1_D0_PORT149, NULL); ++ gpio_request(GPIO_FN_MMC1_D1_PORT148, NULL); ++ gpio_request(GPIO_FN_MMC1_D2_PORT147, NULL); ++ gpio_request(GPIO_FN_MMC1_D3_PORT146, NULL); ++ gpio_request(GPIO_FN_MMC1_D4_PORT145, NULL); ++ gpio_request(GPIO_FN_MMC1_D5_PORT144, NULL); ++ gpio_request(GPIO_FN_MMC1_D6_PORT143, NULL); ++ gpio_request(GPIO_FN_MMC1_D7_PORT142, NULL); ++ ++ /* + * CAUTION + * + * DBGMD/LCDC0/FSIA MUX +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0069-ARM-mach-shmobile-r8a7740-reserve-DMA-memory-for-the.patch b/patches.armadillo800/0069-ARM-mach-shmobile-r8a7740-reserve-DMA-memory-for-the.patch new file mode 100644 index 0000000000000..90555bdbcc333 --- /dev/null +++ b/patches.armadillo800/0069-ARM-mach-shmobile-r8a7740-reserve-DMA-memory-for-the.patch @@ -0,0 +1,47 @@ +From 3d1f581e9dbb224b5f0543883cc3e86876c8e5fe Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 24 Apr 2012 02:10:05 -0700 +Subject: ARM: mach-shmobile: r8a7740: reserve DMA memory for the frame buffer + +The default 2MB size of DMA coherent memory isn't enough for allocate +frame buffer memory. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 3841e6f561af717478b253ce1dcba7bff9e9f890) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/setup-r8a7740.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c +index 34a1548..ec4eb49 100644 +--- a/arch/arm/mach-shmobile/setup-r8a7740.c ++++ b/arch/arm/mach-shmobile/setup-r8a7740.c +@@ -18,6 +18,7 @@ + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + #include <linux/delay.h> ++#include <linux/dma-mapping.h> + #include <linux/kernel.h> + #include <linux/init.h> + #include <linux/io.h> +@@ -60,6 +61,12 @@ static struct map_desc r8a7740_io_desc[] __initdata = { + void __init r8a7740_map_io(void) + { + iotable_init(r8a7740_io_desc, ARRAY_SIZE(r8a7740_io_desc)); ++ ++ /* ++ * DMA memory at 0xff200000 - 0xffdfffff. The default 2MB size isn't ++ * enough to allocate the frame buffer memory. ++ */ ++ init_consistent_dma_size(12 << 20); + } + + /* SCIFA0 */ +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0070-ARM-mach-shmobile-clock-r8a7740-add-sh-eth-clock.patch b/patches.armadillo800/0070-ARM-mach-shmobile-clock-r8a7740-add-sh-eth-clock.patch new file mode 100644 index 0000000000000..1205439ce95a5 --- /dev/null +++ b/patches.armadillo800/0070-ARM-mach-shmobile-clock-r8a7740-add-sh-eth-clock.patch @@ -0,0 +1,64 @@ +From c1d7a1d9c12959dea7cc4f0552e6b7985afeb186 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 6 May 2012 22:58:41 -0700 +Subject: ARM: mach-shmobile: clock-r8a7740: add sh-eth clock + +armadillo800eva board is using sh-eth, but clock-r8a7740 didn't care it. +This clock was enabled by boot-loader. +This patch fix it up. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Reviewed-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 9c18f238c1ec36b9912b5b36ae24e0c221179044) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 1 + + arch/arm/mach-shmobile/clock-r8a7740.c | 3 +++ + 2 files changed, 4 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index 0cfaec5..e750ea6 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -321,6 +321,7 @@ static struct resource sh_eth_resources[] = { + + static struct platform_device sh_eth_device = { + .name = "sh-eth", ++ .id = -1, + .dev = { + .platform_data = &sh_eth_platdata, + }, +diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c +index 81b54a6..26eea5f 100644 +--- a/arch/arm/mach-shmobile/clock-r8a7740.c ++++ b/arch/arm/mach-shmobile/clock-r8a7740.c +@@ -352,6 +352,7 @@ enum { + + MSTP329, MSTP328, MSTP323, MSTP320, + MSTP314, MSTP313, MSTP312, ++ MSTP309, + + MSTP416, MSTP415, MSTP407, MSTP406, + +@@ -382,6 +383,7 @@ static struct clk mstp_clks[MSTP_NR] = { + [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */ + [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */ + [MSTP312] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMC */ ++ [MSTP309] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 9, 0), /* GEther */ + + [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */ + [MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 15, 0), /* SDHI2 */ +@@ -447,6 +449,7 @@ static struct clk_lookup lookups[] = { + CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), + CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), + CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP312]), ++ CLKDEV_DEV_ID("sh-eth", &mstp_clks[MSTP309]), + + CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]), + +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0071-ARM-mach-shmobile-armadillo800eva-defconfig-update.patch b/patches.armadillo800/0071-ARM-mach-shmobile-armadillo800eva-defconfig-update.patch new file mode 100644 index 0000000000000..0fdb8e8588a0c --- /dev/null +++ b/patches.armadillo800/0071-ARM-mach-shmobile-armadillo800eva-defconfig-update.patch @@ -0,0 +1,87 @@ +From b578e0342552c51f1d81de4d730bf5325f52b48a Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Wed, 25 Apr 2012 20:57:13 -0700 +Subject: ARM: mach-shmobile: armadillo800eva: defconfig update + +This patch enable USBFunc/SHDI/MMCIF, +remove debug settings, +and cleanuped by c2330e286f68f1c408b4aa6515ba49d57f05beae script + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 9183857d503f915ee05abb6e03cea7253dcbace6) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/configs/armadillo800eva_defconfig | 25 ++++++++++++------------- + 1 file changed, 12 insertions(+), 13 deletions(-) + +diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig +index 0d20749..ddc9fe6 100644 +--- a/arch/arm/configs/armadillo800eva_defconfig ++++ b/arch/arm/configs/armadillo800eva_defconfig +@@ -10,7 +10,6 @@ CONFIG_LOG_BUF_SHIFT=16 + CONFIG_SYSFS_DEPRECATED=y + CONFIG_SYSFS_DEPRECATED_V2=y + CONFIG_CC_OPTIMIZE_FOR_SIZE=y +-CONFIG_KALLSYMS_ALL=y + CONFIG_SLAB=y + CONFIG_MODULES=y + CONFIG_MODULE_UNLOAD=y +@@ -63,6 +62,7 @@ CONFIG_BLK_DEV_DM=y + CONFIG_NETDEVICES=y + # CONFIG_NET_VENDOR_BROADCOM is not set + # CONFIG_NET_VENDOR_CHELSIO is not set ++# CONFIG_NET_VENDOR_CIRRUS is not set + # CONFIG_NET_VENDOR_FARADAY is not set + # CONFIG_NET_VENDOR_INTEL is not set + # CONFIG_NET_VENDOR_MARVELL is not set +@@ -70,6 +70,7 @@ CONFIG_NETDEVICES=y + # CONFIG_NET_VENDOR_NATSEMI is not set + CONFIG_SH_ETH=y + # CONFIG_NET_VENDOR_SEEQ is not set ++# CONFIG_NET_VENDOR_SMSC is not set + # CONFIG_NET_VENDOR_STMICRO is not set + # CONFIG_WLAN is not set + # CONFIG_INPUT_MOUSEDEV_PSAUX is not set +@@ -106,7 +107,15 @@ CONFIG_SND=y + CONFIG_SND_SOC=y + CONFIG_SND_SOC_SH4_FSI=y + # CONFIG_HID_SUPPORT is not set +-# CONFIG_USB_SUPPORT is not set ++CONFIG_USB=y ++# CONFIG_USB_DEVICE_CLASS is not set ++CONFIG_USB_RENESAS_USBHS=y ++CONFIG_USB_GADGET=y ++CONFIG_USB_RENESAS_USBHS_UDC=y ++CONFIG_USB_ETH=m ++CONFIG_MMC=y ++CONFIG_MMC_SDHI=y ++CONFIG_MMC_SH_MMCIF=y + CONFIG_UIO=y + CONFIG_UIO_PDRV_GENIRQ=y + # CONFIG_DNOTIFY is not set +@@ -124,17 +133,7 @@ CONFIG_NLS_CODEPAGE_437=y + CONFIG_NLS_ISO8859_1=y + # CONFIG_ENABLE_WARN_DEPRECATED is not set + # CONFIG_ENABLE_MUST_CHECK is not set +-CONFIG_MAGIC_SYSRQ=y +-CONFIG_DEBUG_SECTION_MISMATCH=y +-CONFIG_DEBUG_KERNEL=y +-CONFIG_LOCKUP_DETECTOR=y +-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y +-# CONFIG_DETECT_HUNG_TASK is not set +-# CONFIG_SCHED_DEBUG is not set +-CONFIG_DEBUG_KMEMLEAK=y +-CONFIG_DEBUG_SPINLOCK=y +-CONFIG_DEBUG_INFO=y +-# CONFIG_FTRACE is not set ++# CONFIG_ARM_UNWIND is not set + CONFIG_CRYPTO=y + CONFIG_CRYPTO_CBC=y + CONFIG_CRYPTO_MD5=y +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0072-ARM-mach-shmobile-Use-DT_MACHINE-for-armadillo-800-e.patch b/patches.armadillo800/0072-ARM-mach-shmobile-Use-DT_MACHINE-for-armadillo-800-e.patch new file mode 100644 index 0000000000000..6050a9081e557 --- /dev/null +++ b/patches.armadillo800/0072-ARM-mach-shmobile-Use-DT_MACHINE-for-armadillo-800-e.patch @@ -0,0 +1,88 @@ +From e8f0e8b7d350aad665d17ffe656edaa2c2dda533 Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Mon, 14 May 2012 19:54:41 +0900 +Subject: ARM: mach-shmobile: Use DT_MACHINE for armadillo 800 eva + +Use DT_MACHINE_START() on the r8a7740 based armadillo 800 eva board. + +Also include a tiny DTS file to describe the board and update the +Kconfig dependencies to select CONFIG_USE_OF. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit e6bf705911a0b64c589b6c408a316e7d465acbbd) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/boot/dts/r8a7740-armadillo800eva.dts | 22 ++++++++++++++++++++++ + arch/arm/mach-shmobile/Kconfig | 1 + + arch/arm/mach-shmobile/board-armadillo800eva.c | 8 +++++++- + 3 files changed, 30 insertions(+), 1 deletion(-) + create mode 100644 arch/arm/boot/dts/r8a7740-armadillo800eva.dts + +diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts +new file mode 100644 +index 0000000..a7505a9 +--- /dev/null ++++ b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts +@@ -0,0 +1,22 @@ ++/* ++ * Device Tree Source for the armadillo 800 eva board ++ * ++ * Copyright (C) 2012 Renesas Solutions Corp. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/dts-v1/; ++/include/ "skeleton.dtsi" ++ ++/ { ++ model = "armadillo 800 eva"; ++ compatible = "renesas,armadillo800eva"; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x40000000 0x20000000>; ++ }; ++}; +diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig +index 799e996..da57dde 100644 +--- a/arch/arm/mach-shmobile/Kconfig ++++ b/arch/arm/mach-shmobile/Kconfig +@@ -99,6 +99,7 @@ config MACH_ARMADILLO800EVA + bool "Armadillo-800 EVA board" + depends on ARCH_R8A7740 + select ARCH_REQUIRE_GPIOLIB ++ select USE_OF + + config MACH_MARZEN + bool "MARZEN board" +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index e750ea6..9e37026 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -768,11 +768,17 @@ static void __init eva_add_early_devices(void) + shmobile_timer.init = eva_earlytimer_init; + } + +-MACHINE_START(ARMADILLO800EVA, "armadillo800eva") ++static const char *eva_boards_compat_dt[] __initdata = { ++ "renesas,armadillo800eva", ++ NULL, ++}; ++ ++DT_MACHINE_START(ARMADILLO800EVA_DT, "armadillo800eva") + .map_io = r8a7740_map_io, + .init_early = eva_add_early_devices, + .init_irq = r8a7740_init_irq, + .handle_irq = shmobile_handle_irq_intc, + .init_machine = eva_init, + .timer = &shmobile_timer, ++ .dt_compat = eva_boards_compat_dt, + MACHINE_END +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0073-ARM-shmobile-r8a7740-add-HDMI-interrupt-support.patch b/patches.armadillo800/0073-ARM-shmobile-r8a7740-add-HDMI-interrupt-support.patch new file mode 100644 index 0000000000000..d84ba6b9a4af1 --- /dev/null +++ b/patches.armadillo800/0073-ARM-shmobile-r8a7740-add-HDMI-interrupt-support.patch @@ -0,0 +1,82 @@ +From 86c25d5111c1edb9ca3cc28eaa0abd387250959a Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 12 Jun 2012 02:35:15 -0700 +Subject: ARM: shmobile: r8a7740: add HDMI interrupt support + +It is required from sh_mobile_hdmi driver. +This patch is based on v1.0 manual + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 7d7136cabcad632a81cd568a9c1135db276fe0f2) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/intc-r8a7740.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/arch/arm/mach-shmobile/intc-r8a7740.c b/arch/arm/mach-shmobile/intc-r8a7740.c +index 09c42af..9a69a31 100644 +--- a/arch/arm/mach-shmobile/intc-r8a7740.c ++++ b/arch/arm/mach-shmobile/intc-r8a7740.c +@@ -71,10 +71,12 @@ enum { + DMAC3_1_DEI0, DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3, + DMAC3_2_DEI4, DMAC3_2_DEI5, DMAC3_2_DADERR, + SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM, ++ HDMI, + USBH_INT, USBH_OHCI, USBH_EHCI, USBH_PME, USBH_BIND, + RSPI_OVRF, RSPI_SPTEF, RSPI_SPRF, + SPU2_0, SPU2_1, + FSI, FMSI, ++ HDMI_SSS, HDMI_KEY, + IPMMU, + AP_ARM_CTIIRQ, AP_ARM_PMURQ, + MFIS2, +@@ -182,6 +184,7 @@ static struct intc_vect intca_vectors[] __initdata = { + INTC_VECT(USBH_EHCI, 0x1580), + INTC_VECT(USBH_PME, 0x15A0), + INTC_VECT(USBH_BIND, 0x15C0), ++ INTC_VECT(HDMI, 0x1700), + INTC_VECT(RSPI_OVRF, 0x1780), + INTC_VECT(RSPI_SPTEF, 0x17A0), + INTC_VECT(RSPI_SPRF, 0x17C0), +@@ -189,6 +192,8 @@ static struct intc_vect intca_vectors[] __initdata = { + INTC_VECT(SPU2_1, 0x1820), + INTC_VECT(FSI, 0x1840), + INTC_VECT(FMSI, 0x1860), ++ INTC_VECT(HDMI_SSS, 0x18A0), ++ INTC_VECT(HDMI_KEY, 0x18C0), + INTC_VECT(IPMMU, 0x1920), + INTC_VECT(AP_ARM_CTIIRQ, 0x1980), + INTC_VECT(AP_ARM_PMURQ, 0x19A0), +@@ -304,11 +309,11 @@ static struct intc_mask_reg intca_mask_registers[] __initdata = { + USBH_EHCI, USBH_PME, USBH_BIND, 0 } }, + /* IMR3A3 / IMCR3A3 */ + { /* IMR4A3 / IMCR4A3 */ 0xe6950090, 0xe69500d0, 8, +- { 0, 0, 0, 0, ++ { HDMI, 0, 0, 0, + RSPI_OVRF, RSPI_SPTEF, RSPI_SPRF, 0 } }, + { /* IMR5A3 / IMCR5A3 */ 0xe6950094, 0xe69500d4, 8, + { SPU2_0, SPU2_1, FSI, FMSI, +- 0, 0, 0, 0 } }, ++ 0, HDMI_SSS, HDMI_KEY, 0 } }, + { /* IMR6A3 / IMCR6A3 */ 0xe6950098, 0xe69500d8, 8, + { 0, IPMMU, 0, 0, + AP_ARM_CTIIRQ, AP_ARM_PMURQ, 0, 0 } }, +@@ -353,10 +358,10 @@ static struct intc_prio_reg intca_prio_registers[] __initdata = { + { 0xe6950014, 0, 16, 4, /* IPRFA3 */ { USBH2, 0, 0, 0 } }, + /* IPRGA3 */ + /* IPRHA3 */ +- /* IPRIA3 */ ++ { 0xe6950020, 0, 16, 4, /* IPRIA3 */ { HDMI, 0, 0, 0 } }, + { 0xe6950024, 0, 16, 4, /* IPRJA3 */ { RSPI, 0, 0, 0 } }, + { 0xe6950028, 0, 16, 4, /* IPRKA3 */ { SPU2, 0, FSI, FMSI } }, +- /* IPRLA3 */ ++ { 0xe695002c, 0, 16, 4, /* IPRLA3 */ { 0, HDMI_SSS, HDMI_KEY, 0 } }, + { 0xe6950030, 0, 16, 4, /* IPRMA3 */ { IPMMU, 0, 0, 0 } }, + { 0xe6950034, 0, 16, 4, /* IPRNA3 */ { AP_ARM2, 0, 0, 0 } }, + { 0xe6950038, 0, 16, 4, /* IPROA3 */ { MFIS2, CPORTR2S, +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0074-ARM-shmobile-r8a7740-add-HDMI-clock-support.patch b/patches.armadillo800/0074-ARM-shmobile-r8a7740-add-HDMI-clock-support.patch new file mode 100644 index 0000000000000..707d43aec5dee --- /dev/null +++ b/patches.armadillo800/0074-ARM-shmobile-r8a7740-add-HDMI-clock-support.patch @@ -0,0 +1,146 @@ +From 86a946d62d5993f9f8bff6db6445a0a12893665d Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 12 Jun 2012 02:35:36 -0700 +Subject: ARM: shmobile: r8a7740: add HDMI clock support + +It is required from sh_mobile_hdmi driver. +This patch is based on v1.0 manual + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit c6750acb3b54c77c011045467770d5143be749ee) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-r8a7740.c | 84 ++++++++++++++++++++++++++++++++++ + 1 file changed, 84 insertions(+) + +diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c +index 26eea5f..b095343 100644 +--- a/arch/arm/mach-shmobile/clock-r8a7740.c ++++ b/arch/arm/mach-shmobile/clock-r8a7740.c +@@ -54,6 +54,7 @@ + #define MSTPSR2 0xe6150040 + #define MSTPSR3 0xe6150048 + #define MSTPSR4 0xe615004c ++#define HDMICKCR 0xe6150094 + #define SMSTPCR0 0xe6150130 + #define SMSTPCR1 0xe6150134 + #define SMSTPCR2 0xe6150138 +@@ -313,6 +314,79 @@ static struct clk_div4_table div4_table = { + .kick = div4_kick, + }; + ++/* DIV6 reparent */ ++enum { ++ DIV6_HDMI, ++ DIV6_REPARENT_NR, ++}; ++ ++static struct clk *hdmi_parent[] = { ++ [0] = &pllc1_div2_clk, ++ [1] = &system_clk, ++ [2] = &dv_clk ++}; ++ ++static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { ++ [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0, ++ hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2), ++}; ++ ++/* HDMI1/2 clock */ ++static unsigned long hdmi12_recalc(struct clk *clk) ++{ ++ u32 val = __raw_readl(HDMICKCR); ++ int shift = (int)clk->priv; ++ ++ val >>= shift; ++ val &= 0x3; ++ ++ return clk->parent->rate / (1 << val); ++}; ++ ++static int hdmi12_set_rate(struct clk *clk, unsigned long rate) ++{ ++ u32 val, mask; ++ int i, shift; ++ ++ for (i = 0; i < 3; i++) ++ if (rate == clk->parent->rate / (1 << i)) ++ goto find; ++ return -ENODEV; ++ ++find: ++ shift = (int)clk->priv; ++ ++ val = __raw_readl(HDMICKCR); ++ mask = ~(0x3 << shift); ++ val = (val & mask) | i << shift; ++ __raw_writel(val, HDMICKCR); ++ ++ return 0; ++}; ++ ++static struct sh_clk_ops hdmi12_clk_ops = { ++ .recalc = hdmi12_recalc, ++ .set_rate = hdmi12_set_rate, ++}; ++ ++static struct clk hdmi1_clk = { ++ .ops = &hdmi12_clk_ops, ++ .priv = (void *)9, ++ .parent = &div6_reparent_clks[DIV6_HDMI], /* late install */ ++}; ++ ++static struct clk hdmi2_clk = { ++ .ops = &hdmi12_clk_ops, ++ .priv = (void *)11, ++ .parent = &div6_reparent_clks[DIV6_HDMI], /* late install */ ++}; ++ ++static struct clk *late_main_clks[] = { ++ &hdmi1_clk, ++ &hdmi2_clk, ++}; ++ ++/* MSTP */ + enum { + DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP, + DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP, +@@ -408,6 +482,8 @@ static struct clk_lookup lookups[] = { + CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), + CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), + CLKDEV_CON_ID("usb24s", &usb24s_clk), ++ CLKDEV_CON_ID("hdmi1", &hdmi1_clk), ++ CLKDEV_CON_ID("hdmi2", &hdmi2_clk), + + /* DIV4 clocks */ + CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), +@@ -459,6 +535,7 @@ static struct clk_lookup lookups[] = { + CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]), + CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]), + CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk), ++ CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]), + }; + + void __init r8a7740_clock_init(u8 md_ck) +@@ -495,8 +572,15 @@ void __init r8a7740_clock_init(u8 md_ck) + ret = sh_clk_div6_register(div6_clks, DIV6_NR); + + if (!ret) ++ ret = sh_clk_div6_reparent_register(div6_reparent_clks, ++ DIV6_REPARENT_NR); ++ ++ if (!ret) + ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); + ++ for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++) ++ ret = clk_register(late_main_clks[k]); ++ + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + + if (!ret) +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0075-ARM-shmobile-r8a7740-add-HDMI-GPIO-support.patch b/patches.armadillo800/0075-ARM-shmobile-r8a7740-add-HDMI-GPIO-support.patch new file mode 100644 index 0000000000000..8619f0d0d14f3 --- /dev/null +++ b/patches.armadillo800/0075-ARM-shmobile-r8a7740-add-HDMI-GPIO-support.patch @@ -0,0 +1,76 @@ +From 77cd6be2b59e2839e6c2b8cab77a480e092aedec Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 12 Jun 2012 02:35:58 -0700 +Subject: ARM: shmobile: r8a7740: add HDMI GPIO support + +In order to enable HDMI GPIO selection from platform board, +this patch adds its interface to GPIO framework. + +This patch is based on v1.0 manual + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit e2dcd461a7ba0c3deb44336136ea784c8b972292) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/include/mach/r8a7740.h | 4 ++++ + arch/arm/mach-shmobile/pfc-r8a7740.c | 9 +++++++++ + 2 files changed, 13 insertions(+) + +diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h +index 9d447ab..2764846 100644 +--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h ++++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h +@@ -565,6 +565,10 @@ enum { + GPIO_FN_RESETP_PULLUP, + GPIO_FN_RESETP_PLAIN, + ++ /* HDMI */ ++ GPIO_FN_HDMI_HPD, ++ GPIO_FN_HDMI_CEC, ++ + /* SDENC */ + GPIO_FN_SDENC_CPG, + GPIO_FN_SDENC_DV_CLKI, +diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c +index 670fe18..0dda816 100644 +--- a/arch/arm/mach-shmobile/pfc-r8a7740.c ++++ b/arch/arm/mach-shmobile/pfc-r8a7740.c +@@ -560,6 +560,9 @@ enum { + /* SDENC */ + SDENC_CPG_MARK, SDENC_DV_CLKI_MARK, + ++ /* HDMI */ ++ HDMI_HPD_MARK, HDMI_CEC_MARK, ++ + /* DEBUG */ + EDEBGREQ_PULLUP_MARK, /* for JTAG */ + EDEBGREQ_PULLDOWN_MARK, +@@ -1620,9 +1623,11 @@ static pinmux_enum_t pinmux_data[] = { + + /* Port210 */ + PINMUX_DATA(IRQ9_PORT210_MARK, PORT210_FN0, MSEL1CR_9_1), ++ PINMUX_DATA(HDMI_HPD_MARK, PORT210_FN1), + + /* Port211 */ + PINMUX_DATA(IRQ16_PORT211_MARK, PORT211_FN0, MSEL1CR_16_1), ++ PINMUX_DATA(HDMI_CEC_MARK, PORT211_FN1), + + /* LCDC select */ + PINMUX_DATA(LCDC0_SELECT_MARK, MSEL3CR_6_0), +@@ -2097,6 +2102,10 @@ static struct pinmux_gpio pinmux_gpios[] = { + GPIO_FN(SDENC_CPG), + GPIO_FN(SDENC_DV_CLKI), + ++ /* HDMI */ ++ GPIO_FN(HDMI_HPD), ++ GPIO_FN(HDMI_CEC), ++ + /* SYSC */ + GPIO_FN(RESETP_PULLUP), + GPIO_FN(RESETP_PLAIN), +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0076-ARM-shmobile-r8a7740-add-MERAM-work-around.patch b/patches.armadillo800/0076-ARM-shmobile-r8a7740-add-MERAM-work-around.patch new file mode 100644 index 0000000000000..ac9838b85cc66 --- /dev/null +++ b/patches.armadillo800/0076-ARM-shmobile-r8a7740-add-MERAM-work-around.patch @@ -0,0 +1,34 @@ +From acd1ae033a03a0c6356e68d9d17427afb0f53eb0 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 12 Jun 2012 02:36:21 -0700 +Subject: ARM: shmobile: r8a7740: add MERAM work-around + +r8a7740 chip has lasting errata on MERAM buffer, and this patch adds +its work-around on setup-r8a7740.c +It solved CEU/VIO6C/2D-DMAC/VCP1/VPU5F/JPU/DISP memroy access error. + +But MERAM driver can't control this issue, +since this work-around requires access to non-MERAM register address. +So, This it will be called as board specific code at this point. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit d49679e5928709bce8937dce396458b139c4b34d) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -587,6 +587,7 @@ static void __init eva_init(void) + eva_clock_init(); + + r8a7740_pinmux_init(); ++ r8a7740_meram_workaround(); + + /* SCIFA1 */ + gpio_request(GPIO_FN_SCIFA1_RXD, NULL); diff --git a/patches.armadillo800/0077-ARM-shmobile-r8a7740-add-CEU-clock-support.patch b/patches.armadillo800/0077-ARM-shmobile-r8a7740-add-CEU-clock-support.patch new file mode 100644 index 0000000000000..8c3989bc6c5e5 --- /dev/null +++ b/patches.armadillo800/0077-ARM-shmobile-r8a7740-add-CEU-clock-support.patch @@ -0,0 +1,101 @@ +From 5484e5aba2cd92f69af04090ab0f4e018175df69 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 12 Jun 2012 02:36:39 -0700 +Subject: ARM: shmobile: r8a7740: add CEU clock support + +It is required from sh_mobile_ceu_camera driver. +This patch is based on v1.0 manual + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit ad9f1721c15b84f1a2e45a8a03f1ff7c86c2829b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-r8a7740.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c +index b095343..ce0930a 100644 +--- a/arch/arm/mach-shmobile/clock-r8a7740.c ++++ b/arch/arm/mach-shmobile/clock-r8a7740.c +@@ -43,6 +43,8 @@ + /* CPG registers */ + #define FRQCRA 0xe6150000 + #define FRQCRB 0xe6150004 ++#define VCLKCR1 0xE6150008 ++#define VCLKCR2 0xE615000c + #define FRQCRC 0xe61500e0 + #define PLLC01CR 0xe6150028 + +@@ -317,6 +319,7 @@ static struct clk_div4_table div4_table = { + /* DIV6 reparent */ + enum { + DIV6_HDMI, ++ DIV6_VCLK1, DIV6_VCLK2, + DIV6_REPARENT_NR, + }; + +@@ -326,9 +329,21 @@ static struct clk *hdmi_parent[] = { + [2] = &dv_clk + }; + ++static struct clk *vclk_parents[8] = { ++ [0] = &pllc1_div2_clk, ++ [2] = &dv_clk, ++ [3] = &usb24s_clk, ++ [4] = &extal1_div2_clk, ++ [5] = &extalr_clk, ++}; ++ + static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { + [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0, + hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2), ++ [DIV6_VCLK1] = SH_CLK_DIV6_EXT(VCLKCR1, 0, ++ vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3), ++ [DIV6_VCLK2] = SH_CLK_DIV6_EXT(VCLKCR2, 0, ++ vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3), + }; + + /* HDMI1/2 clock */ +@@ -417,7 +432,7 @@ static struct clk div6_clks[DIV6_NR] = { + }; + + enum { +- MSTP125, ++ MSTP128, MSTP127, MSTP125, + MSTP116, MSTP111, MSTP100, MSTP117, + + MSTP230, +@@ -434,6 +449,8 @@ enum { + }; + + static struct clk mstp_clks[MSTP_NR] = { ++ [MSTP128] = SH_CLK_MSTP32(&div4_clks[DIV4_S], SMSTPCR1, 28, 0), /* CEU21 */ ++ [MSTP127] = SH_CLK_MSTP32(&div4_clks[DIV4_S], SMSTPCR1, 27, 0), /* CEU20 */ + [MSTP125] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */ + [MSTP117] = SH_CLK_MSTP32(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */ + [MSTP116] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */ +@@ -484,6 +501,8 @@ static struct clk_lookup lookups[] = { + CLKDEV_CON_ID("usb24s", &usb24s_clk), + CLKDEV_CON_ID("hdmi1", &hdmi1_clk), + CLKDEV_CON_ID("hdmi2", &hdmi2_clk), ++ CLKDEV_CON_ID("video1", &div6_reparent_clks[DIV6_VCLK1]), ++ CLKDEV_CON_ID("video2", &div6_reparent_clks[DIV6_VCLK2]), + + /* DIV4 clocks */ + CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), +@@ -506,6 +525,8 @@ static struct clk_lookup lookups[] = { + CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), + CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), + CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP125]), ++ CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), ++ CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP128]), + + CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), + CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0078-ARM-shmobile-r8a7740-add-FSI-parent-clock-support.patch b/patches.armadillo800/0078-ARM-shmobile-r8a7740-add-FSI-parent-clock-support.patch new file mode 100644 index 0000000000000..f4e614367c9e7 --- /dev/null +++ b/patches.armadillo800/0078-ARM-shmobile-r8a7740-add-FSI-parent-clock-support.patch @@ -0,0 +1,125 @@ +From 3380d7910c8f2625a74337bd1a3f1d81bc146c73 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 12 Jun 2012 02:36:58 -0700 +Subject: ARM: shmobile: r8a7740: add FSI parent clock support + +r8a7740 FSI can select its parent clock, +and its selection is dependent on platform board. + +In order to enable FSI parent selection from platform board, +this patch adds its interface to clock framework. + +This patch is based on v1.0 manual + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 69efac9a8bc6d479bc4c339ae4ac4d353460def6) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-r8a7740.c | 31 +++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c +index ce0930a..7b9e4ab 100644 +--- a/arch/arm/mach-shmobile/clock-r8a7740.c ++++ b/arch/arm/mach-shmobile/clock-r8a7740.c +@@ -46,6 +46,7 @@ + #define VCLKCR1 0xE6150008 + #define VCLKCR2 0xE615000c + #define FRQCRC 0xe61500e0 ++#define FSIACKCR 0xe6150018 + #define PLLC01CR 0xe6150028 + + #define SUBCKCR 0xe6150080 +@@ -56,6 +57,7 @@ + #define MSTPSR2 0xe6150040 + #define MSTPSR3 0xe6150048 + #define MSTPSR4 0xe615004c ++#define FSIBCKCR 0xe6150090 + #define HDMICKCR 0xe6150094 + #define SMSTPCR0 0xe6150130 + #define SMSTPCR1 0xe6150134 +@@ -274,6 +276,13 @@ static struct clk usb24_clk = { + .parent = &usb24s_clk, + }; + ++/* External FSIACK/FSIBCK clock */ ++static struct clk fsiack_clk = { ++}; ++ ++static struct clk fsibck_clk = { ++}; ++ + struct clk *main_clks[] = { + &extalr_clk, + &extal1_clk, +@@ -291,6 +300,8 @@ struct clk *main_clks[] = { + &pllc1_div2_clk, + &usb24s_clk, + &usb24_clk, ++ &fsiack_clk, ++ &fsibck_clk, + }; + + static void div4_kick(struct clk *clk) +@@ -320,6 +331,7 @@ static struct clk_div4_table div4_table = { + enum { + DIV6_HDMI, + DIV6_VCLK1, DIV6_VCLK2, ++ DIV6_FSIA, DIV6_FSIB, + DIV6_REPARENT_NR, + }; + +@@ -337,6 +349,16 @@ static struct clk *vclk_parents[8] = { + [5] = &extalr_clk, + }; + ++static struct clk *fsia_parents[] = { ++ [0] = &pllc1_div2_clk, ++ [1] = &fsiack_clk, /* external clock */ ++}; ++ ++static struct clk *fsib_parents[] = { ++ [0] = &pllc1_div2_clk, ++ [1] = &fsibck_clk, /* external clock */ ++}; ++ + static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { + [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0, + hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2), +@@ -344,6 +366,10 @@ static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { + vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3), + [DIV6_VCLK2] = SH_CLK_DIV6_EXT(VCLKCR2, 0, + vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3), ++ [DIV6_FSIA] = SH_CLK_DIV6_EXT(FSIACKCR, 0, ++ fsia_parents, ARRAY_SIZE(fsia_parents), 6, 2), ++ [DIV6_FSIB] = SH_CLK_DIV6_EXT(FSIBCKCR, 0, ++ fsib_parents, ARRAY_SIZE(fsib_parents), 6, 2), + }; + + /* HDMI1/2 clock */ +@@ -503,6 +529,8 @@ static struct clk_lookup lookups[] = { + CLKDEV_CON_ID("hdmi2", &hdmi2_clk), + CLKDEV_CON_ID("video1", &div6_reparent_clks[DIV6_VCLK1]), + CLKDEV_CON_ID("video2", &div6_reparent_clks[DIV6_VCLK2]), ++ CLKDEV_CON_ID("fsiack", &fsiack_clk), ++ CLKDEV_CON_ID("fsibck", &fsibck_clk), + + /* DIV4 clocks */ + CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), +@@ -557,6 +585,9 @@ static struct clk_lookup lookups[] = { + CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]), + CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk), + CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]), ++ ++ CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]), ++ CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]), + }; + + void __init r8a7740_clock_init(u8 md_ck) +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0079-ARM-shmobile-r8a7740-add-FSI-B-for-HDMI-GPIO-support.patch b/patches.armadillo800/0079-ARM-shmobile-r8a7740-add-FSI-B-for-HDMI-GPIO-support.patch new file mode 100644 index 0000000000000..ddaab4fa15797 --- /dev/null +++ b/patches.armadillo800/0079-ARM-shmobile-r8a7740-add-FSI-B-for-HDMI-GPIO-support.patch @@ -0,0 +1,97 @@ +From ead2de820556aa2682e1505f691a5207365d4e69 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 12 Jun 2012 02:37:16 -0700 +Subject: ARM: shmobile: r8a7740: add FSI-B (for HDMI) GPIO support + +In order to enable FSI-B selection from platform board, +this patch adds its interface to GPIO framework. + +This patch is based on v1.0 manual + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 147d1ffdc21d067f0084f0911dbf1eee57e3d76b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/include/mach/r8a7740.h | 5 ++++- + arch/arm/mach-shmobile/pfc-r8a7740.c | 11 +++++++++-- + 2 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h +index 2764846..6468fcc 100644 +--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h ++++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h +@@ -139,7 +139,7 @@ enum { + GPIO_FN_DBGMD10, GPIO_FN_DBGMD11, GPIO_FN_DBGMD20, + GPIO_FN_DBGMD21, + +- /* FSI */ ++ /* FSI-A */ + GPIO_FN_FSIAISLD_PORT0, /* FSIAISLD Port 0/5 */ + GPIO_FN_FSIAISLD_PORT5, + GPIO_FN_FSIASPDIF_PORT9, /* FSIASPDIF Port 9/18 */ +@@ -150,6 +150,9 @@ enum { + GPIO_FN_FSIACK, GPIO_FN_FSIAILR, + GPIO_FN_FSIAIBT, + ++ /* FSI-B */ ++ GPIO_FN_FSIBCK, ++ + /* FMSI */ + GPIO_FN_FMSISLD_PORT1, /* FMSISLD Port 1/6 */ + GPIO_FN_FMSISLD_PORT6, +diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c +index 0dda816..03def0f 100644 +--- a/arch/arm/mach-shmobile/pfc-r8a7740.c ++++ b/arch/arm/mach-shmobile/pfc-r8a7740.c +@@ -169,7 +169,7 @@ enum { + DBGMD10_MARK, DBGMD11_MARK, DBGMD20_MARK, + DBGMD21_MARK, + +- /* FSI */ ++ /* FSI-A */ + FSIAISLD_PORT0_MARK, /* FSIAISLD Port 0/5 */ + FSIAISLD_PORT5_MARK, + FSIASPDIF_PORT9_MARK, /* FSIASPDIF Port 9/18 */ +@@ -178,6 +178,9 @@ enum { + FSIAOBT_MARK, FSIAOSLD_MARK, FSIAOMC_MARK, + FSIACK_MARK, FSIAILR_MARK, FSIAIBT_MARK, + ++ /* FSI-B */ ++ FSIBCK_MARK, ++ + /* FMSI */ + FMSISLD_PORT1_MARK, /* FMSISLD Port 1/6 */ + FMSISLD_PORT6_MARK, +@@ -774,6 +777,7 @@ static pinmux_enum_t pinmux_data[] = { + + /* Port11 */ + PINMUX_DATA(FSIACK_MARK, PORT11_FN1), ++ PINMUX_DATA(FSIBCK_MARK, PORT11_FN2), + PINMUX_DATA(IRQ2_PORT11_MARK, PORT11_FN0, MSEL1CR_2_0), + + /* Port12 */ +@@ -1696,7 +1700,7 @@ static struct pinmux_gpio pinmux_gpios[] = { + GPIO_FN(DBGMD10), GPIO_FN(DBGMD11), GPIO_FN(DBGMD20), + GPIO_FN(DBGMD21), + +- /* FSI */ ++ /* FSI-A */ + GPIO_FN(FSIAISLD_PORT0), /* FSIAISLD Port 0/5 */ + GPIO_FN(FSIAISLD_PORT5), + GPIO_FN(FSIASPDIF_PORT9), /* FSIASPDIF Port 9/18 */ +@@ -1705,6 +1709,9 @@ static struct pinmux_gpio pinmux_gpios[] = { + GPIO_FN(FSIAOBT), GPIO_FN(FSIAOSLD), GPIO_FN(FSIAOMC), + GPIO_FN(FSIACK), GPIO_FN(FSIAILR), GPIO_FN(FSIAIBT), + ++ /* FSI-B */ ++ GPIO_FN(FSIBCK), ++ + /* FMSI */ + GPIO_FN(FMSISLD_PORT1), /* FMSISLD Port 1/6 */ + GPIO_FN(FMSISLD_PORT6), +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0080-ARM-shmobile-armadillo800eva-enable-HDMI.patch b/patches.armadillo800/0080-ARM-shmobile-armadillo800eva-enable-HDMI.patch new file mode 100644 index 0000000000000..731d6c1e8e3ed --- /dev/null +++ b/patches.armadillo800/0080-ARM-shmobile-armadillo800eva-enable-HDMI.patch @@ -0,0 +1,197 @@ +From e92cdf42dfe94be35bc251b5eaa9a0db2c8679e9 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 12 Jun 2012 02:39:11 -0700 +Subject: ARM: shmobile: armadillo800eva: enable HDMI + +This patch enable HDMI support on CON3. +And removed unnecessary CONFIG_SYSFS_DEPRECATED_xxx config. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 910c14d0b8f121df420a878cbd973ffa7d549393) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/configs/armadillo800eva_defconfig | 10 +-- + arch/arm/mach-shmobile/board-armadillo800eva.c | 100 +++++++++++++++++++++++++ + 2 files changed, 101 insertions(+), 9 deletions(-) + +diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig +index ddc9fe6..f6ebdde 100644 +--- a/arch/arm/configs/armadillo800eva_defconfig ++++ b/arch/arm/configs/armadillo800eva_defconfig +@@ -5,10 +5,7 @@ CONFIG_IKCONFIG_PROC=y + CONFIG_LOG_BUF_SHIFT=16 + # CONFIG_UTS_NS is not set + # CONFIG_IPC_NS is not set +-# CONFIG_USER_NS is not set + # CONFIG_PID_NS is not set +-CONFIG_SYSFS_DEPRECATED=y +-CONFIG_SYSFS_DEPRECATED_V2=y + CONFIG_CC_OPTIMIZE_FOR_SIZE=y + CONFIG_SLAB=y + CONFIG_MODULES=y +@@ -90,25 +87,21 @@ CONFIG_I2C=y + CONFIG_I2C_SH_MOBILE=y + # CONFIG_HWMON is not set + CONFIG_FB=y +-CONFIG_FB_MODE_HELPERS=y + CONFIG_FB_SH_MOBILE_LCDC=y ++CONFIG_FB_SH_MOBILE_HDMI=y + CONFIG_LCD_CLASS_DEVICE=y + CONFIG_FRAMEBUFFER_CONSOLE=y + CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y + CONFIG_LOGO=y + # CONFIG_LOGO_LINUX_MONO is not set + # CONFIG_LOGO_LINUX_VGA16 is not set +-CONFIG_SOUND=y +-CONFIG_SND=y + # CONFIG_SND_SUPPORT_OLD_API is not set + # CONFIG_SND_VERBOSE_PROCFS is not set + # CONFIG_SND_DRIVERS is not set + # CONFIG_SND_ARM is not set +-CONFIG_SND_SOC=y + CONFIG_SND_SOC_SH4_FSI=y + # CONFIG_HID_SUPPORT is not set + CONFIG_USB=y +-# CONFIG_USB_DEVICE_CLASS is not set + CONFIG_USB_RENESAS_USBHS=y + CONFIG_USB_GADGET=y + CONFIG_USB_RENESAS_USBHS_UDC=y +@@ -124,7 +117,6 @@ CONFIG_VFAT_FS=y + CONFIG_TMPFS=y + # CONFIG_MISC_FILESYSTEMS is not set + CONFIG_NFS_FS=y +-CONFIG_NFS_V3=y + CONFIG_NFS_V3_ACL=y + CONFIG_NFS_V4=y + CONFIG_NFS_V4_1=y +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index 6e6839d..4e6893f 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -45,6 +45,7 @@ + #include <asm/hardware/cache-l2x0.h> + #include <mach/r8a7740.h> + #include <video/sh_mobile_lcdc.h> ++#include <video/sh_mobile_hdmi.h> + + /* + * CON1 Camera Module +@@ -384,6 +385,103 @@ static struct platform_device lcdc0_device = { + }, + }; + ++/* ++ * LCDC1/HDMI ++ */ ++static struct sh_mobile_hdmi_info hdmi_info = { ++ .flags = HDMI_OUTPUT_PUSH_PULL | ++ HDMI_OUTPUT_POLARITY_HI | ++ HDMI_32BIT_REG | ++ HDMI_HAS_HTOP1 | ++ HDMI_SND_SRC_SPDIF, ++}; ++ ++static struct resource hdmi_resources[] = { ++ [0] = { ++ .name = "HDMI", ++ .start = 0xe6be0000, ++ .end = 0xe6be03ff, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = evt2irq(0x1700), ++ .flags = IORESOURCE_IRQ, ++ }, ++ [2] = { ++ .name = "HDMI emma3pf", ++ .start = 0xe6be4000, ++ .end = 0xe6be43ff, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static struct platform_device hdmi_device = { ++ .name = "sh-mobile-hdmi", ++ .num_resources = ARRAY_SIZE(hdmi_resources), ++ .resource = hdmi_resources, ++ .id = -1, ++ .dev = { ++ .platform_data = &hdmi_info, ++ }, ++}; ++ ++static const struct fb_videomode lcdc1_mode = { ++ .name = "HDMI 720p", ++ .xres = 1280, ++ .yres = 720, ++ .pixclock = 13468, ++ .left_margin = 220, ++ .right_margin = 110, ++ .hsync_len = 40, ++ .upper_margin = 20, ++ .lower_margin = 5, ++ .vsync_len = 5, ++ .refresh = 60, ++ .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, ++}; ++ ++static struct sh_mobile_lcdc_info hdmi_lcdc_info = { ++ .clock_source = LCDC_CLK_PERIPHERAL, /* HDMI clock */ ++ .ch[0] = { ++ .chan = LCDC_CHAN_MAINLCD, ++ .fourcc = V4L2_PIX_FMT_RGB565, ++ .interface_type = RGB24, ++ .clock_divider = 1, ++ .flags = LCDC_FLAGS_DWPOL, ++ .lcd_modes = &lcdc1_mode, ++ .num_modes = 1, ++ .tx_dev = &hdmi_device, ++ .panel_cfg = { ++ .width = 1280, ++ .height = 720, ++ }, ++ }, ++}; ++ ++static struct resource hdmi_lcdc_resources[] = { ++ [0] = { ++ .name = "LCDC1", ++ .start = 0xfe944000, ++ .end = 0xfe948000 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = intcs_evt2irq(0x1780), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device hdmi_lcdc_device = { ++ .name = "sh_mobile_lcdc_fb", ++ .num_resources = ARRAY_SIZE(hdmi_lcdc_resources), ++ .resource = hdmi_lcdc_resources, ++ .id = 1, ++ .dev = { ++ .platform_data = &hdmi_lcdc_info, ++ .coherent_dma_mask = ~0, ++ }, ++}; ++ + /* GPIO KEY */ + #define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 } + +@@ -549,6 +647,8 @@ static struct platform_device *eva_devices[] __initdata = { + &sh_eth_device, + &sdhi0_device, + &sh_mmcif_device, ++ &hdmi_device, ++ &hdmi_lcdc_device, + }; + + static void __init eva_clock_init(void) +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0081-ARM-mach-shmobile-armadillo800eva-Use-late-init-mach.patch b/patches.armadillo800/0081-ARM-mach-shmobile-armadillo800eva-Use-late-init-mach.patch new file mode 100644 index 0000000000000..5854c1f663670 --- /dev/null +++ b/patches.armadillo800/0081-ARM-mach-shmobile-armadillo800eva-Use-late-init-mach.patch @@ -0,0 +1,35 @@ +From e942f8cdf5f982742f6bc8cb49fd546bb828ffce Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Wed, 20 Jun 2012 12:53:25 +0200 +Subject: ARM: mach-shmobile: armadillo800eva: Use late init machine hook + +Since commit 21cc1b7ede3cf456cf1d51f8a906093261f7c111 ("ARM: shmobile: +use machine specific hook for late init") suspend and CPU idle are not +initialized automatically anymore. Set shmobile_init_late() as the +machine late init hook to initialize them. + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 37f971b68009b8fadd322130787d693137302925) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index 4e6893f..bbf5ccff 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -880,6 +880,7 @@ DT_MACHINE_START(ARMADILLO800EVA_DT, "armadillo800eva") + .init_irq = r8a7740_init_irq, + .handle_irq = shmobile_handle_irq_intc, + .init_machine = eva_init, ++ .init_late = shmobile_init_late, + .timer = &shmobile_timer, + .dt_compat = eva_boards_compat_dt, + MACHINE_END +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0082-ARM-shmobile-armadillo800eva-enable-camera.patch b/patches.armadillo800/0082-ARM-shmobile-armadillo800eva-enable-camera.patch new file mode 100644 index 0000000000000..28a60b6f93b19 --- /dev/null +++ b/patches.armadillo800/0082-ARM-shmobile-armadillo800eva-enable-camera.patch @@ -0,0 +1,192 @@ +From c7934751659fc8d58c97d51edc6fdb5af8307330 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 12 Jun 2012 02:40:07 -0700 +Subject: ARM: shmobile: armadillo800eva: enable camera + +This patch enable camera support on CON1 + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 3760e79450f48e31fde2b2dd49c5ab6a685c3ea8) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/configs/armadillo800eva_defconfig | 10 +++ + arch/arm/mach-shmobile/board-armadillo800eva.c | 111 ++++++++++++++++++++++++- + 2 files changed, 120 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig +index f6ebdde..df1ce54 100644 +--- a/arch/arm/configs/armadillo800eva_defconfig ++++ b/arch/arm/configs/armadillo800eva_defconfig +@@ -86,6 +86,16 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y + CONFIG_I2C=y + CONFIG_I2C_SH_MOBILE=y + # CONFIG_HWMON is not set ++CONFIG_MEDIA_SUPPORT=y ++CONFIG_VIDEO_DEV=y ++# CONFIG_RC_CORE is not set ++# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set ++# CONFIG_V4L_USB_DRIVERS is not set ++CONFIG_V4L_PLATFORM_DRIVERS=y ++CONFIG_SOC_CAMERA=y ++CONFIG_SOC_CAMERA_MT9T112=y ++CONFIG_VIDEO_SH_MOBILE_CEU=y ++# CONFIG_RADIO_ADAPTERS is not set + CONFIG_FB=y + CONFIG_FB_SH_MOBILE_LCDC=y + CONFIG_FB_SH_MOBILE_HDMI=y +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index bbf5ccff..a513ebe 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -37,13 +37,16 @@ + #include <linux/mmc/sh_mobile_sdhi.h> + #include <mach/common.h> + #include <mach/irqs.h> ++#include <mach/r8a7740.h> ++#include <media/mt9t112.h> ++#include <media/sh_mobile_ceu.h> ++#include <media/soc_camera.h> + #include <asm/page.h> + #include <asm/mach-types.h> + #include <asm/mach/arch.h> + #include <asm/mach/map.h> + #include <asm/mach/time.h> + #include <asm/hardware/cache-l2x0.h> +-#include <mach/r8a7740.h> + #include <video/sh_mobile_lcdc.h> + #include <video/sh_mobile_hdmi.h> + +@@ -630,6 +633,87 @@ static struct platform_device sh_mmcif_device = { + .resource = sh_mmcif_resources, + }; + ++/* Camera */ ++static int mt9t111_power(struct device *dev, int mode) ++{ ++ struct clk *mclk = clk_get(NULL, "video1"); ++ ++ if (IS_ERR(mclk)) { ++ dev_err(dev, "can't get video1 clock\n"); ++ return -EINVAL; ++ } ++ ++ if (mode) { ++ /* video1 (= CON1 camera) expect 24MHz */ ++ clk_set_rate(mclk, clk_round_rate(mclk, 24000000)); ++ clk_enable(mclk); ++ gpio_direction_output(GPIO_PORT158, 1); ++ } else { ++ gpio_direction_output(GPIO_PORT158, 0); ++ clk_disable(mclk); ++ } ++ ++ clk_put(mclk); ++ ++ return 0; ++} ++ ++static struct i2c_board_info i2c_camera_mt9t111 = { ++ I2C_BOARD_INFO("mt9t112", 0x3d), ++}; ++ ++static struct mt9t112_camera_info mt9t111_info = { ++ .divider = { 16, 0, 0, 7, 0, 10, 14, 7, 7 }, ++}; ++ ++static struct soc_camera_link mt9t111_link = { ++ .i2c_adapter_id = 0, ++ .bus_id = 0, ++ .board_info = &i2c_camera_mt9t111, ++ .power = mt9t111_power, ++ .priv = &mt9t111_info, ++}; ++ ++static struct platform_device camera_device = { ++ .name = "soc-camera-pdrv", ++ .id = 0, ++ .dev = { ++ .platform_data = &mt9t111_link, ++ }, ++}; ++ ++/* CEU0 */ ++static struct sh_mobile_ceu_info sh_mobile_ceu0_info = { ++ .flags = SH_CEU_FLAG_LOWER_8BIT, ++}; ++ ++static struct resource ceu0_resources[] = { ++ [0] = { ++ .name = "CEU", ++ .start = 0xfe910000, ++ .end = 0xfe91009f, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = intcs_evt2irq(0x0500), ++ .flags = IORESOURCE_IRQ, ++ }, ++ [2] = { ++ /* place holder for contiguous memory */ ++ }, ++}; ++ ++static struct platform_device ceu0_device = { ++ .name = "sh_mobile_ceu", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(ceu0_resources), ++ .resource = ceu0_resources, ++ .dev = { ++ .platform_data = &sh_mobile_ceu0_info, ++ .coherent_dma_mask = 0xffffffff, ++ }, ++}; ++ + /* I2C */ + static struct i2c_board_info i2c0_devices[] = { + { +@@ -649,6 +733,8 @@ static struct platform_device *eva_devices[] __initdata = { + &sh_mmcif_device, + &hdmi_device, + &hdmi_lcdc_device, ++ &camera_device, ++ &ceu0_device, + }; + + static void __init eva_clock_init(void) +@@ -807,6 +893,29 @@ static void __init eva_init(void) + gpio_request(GPIO_FN_MMC1_D6_PORT143, NULL); + gpio_request(GPIO_FN_MMC1_D7_PORT142, NULL); + ++ /* CEU0 */ ++ gpio_request(GPIO_FN_VIO0_D7, NULL); ++ gpio_request(GPIO_FN_VIO0_D6, NULL); ++ gpio_request(GPIO_FN_VIO0_D5, NULL); ++ gpio_request(GPIO_FN_VIO0_D4, NULL); ++ gpio_request(GPIO_FN_VIO0_D3, NULL); ++ gpio_request(GPIO_FN_VIO0_D2, NULL); ++ gpio_request(GPIO_FN_VIO0_D1, NULL); ++ gpio_request(GPIO_FN_VIO0_D0, NULL); ++ gpio_request(GPIO_FN_VIO0_CLK, NULL); ++ gpio_request(GPIO_FN_VIO0_HD, NULL); ++ gpio_request(GPIO_FN_VIO0_VD, NULL); ++ gpio_request(GPIO_FN_VIO0_FIELD, NULL); ++ gpio_request(GPIO_FN_VIO_CKO, NULL); ++ ++ /* CON1/CON15 Camera */ ++ gpio_request(GPIO_PORT173, NULL); /* STANDBY */ ++ gpio_request(GPIO_PORT172, NULL); /* RST */ ++ gpio_request(GPIO_PORT158, NULL); /* CAM_PON */ ++ gpio_direction_output(GPIO_PORT173, 0); ++ gpio_direction_output(GPIO_PORT172, 1); ++ gpio_direction_output(GPIO_PORT158, 0); /* see mt9t111_power() */ ++ + /* + * CAUTION + * +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0083-ARM-shmobile-r8a7740-add-DMAEngine-support-for-FSI.patch b/patches.armadillo800/0083-ARM-shmobile-r8a7740-add-DMAEngine-support-for-FSI.patch new file mode 100644 index 0000000000000..5f28f1e2dfaef --- /dev/null +++ b/patches.armadillo800/0083-ARM-shmobile-r8a7740-add-DMAEngine-support-for-FSI.patch @@ -0,0 +1,299 @@ +From 0e0018e5c4b1d2d6c6fe9d67a8c5916752884589 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 25 Jun 2012 03:36:49 -0700 +Subject: ARM: shmobile: r8a7740: add DMAEngine support for FSI + +Current shdmac can support FSI DMAC on r8a7740. +This support reduce CPU duty when sound was playback. + +This patch is based on v1.0 manual + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 643c3307bbbe7e80c6693376137971fbdcbe1c82) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-r8a7740.c | 8 +- + arch/arm/mach-shmobile/include/mach/r8a7740.h | 8 ++ + arch/arm/mach-shmobile/setup-r8a7740.c | 198 ++++++++++++++++++++++++++ + 3 files changed, 213 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c +index 7b9e4ab..39b1311 100644 +--- a/arch/arm/mach-shmobile/clock-r8a7740.c ++++ b/arch/arm/mach-shmobile/clock-r8a7740.c +@@ -463,6 +463,7 @@ enum { + + MSTP230, + MSTP222, ++ MSTP218, MSTP217, MSTP216, + MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, + + MSTP329, MSTP328, MSTP323, MSTP320, +@@ -485,6 +486,9 @@ static struct clk mstp_clks[MSTP_NR] = { + + [MSTP230] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 30, 0), /* SCIFA6 */ + [MSTP222] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 22, 0), /* SCIFA7 */ ++ [MSTP218] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* DMAC1 */ ++ [MSTP217] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 17, 0), /* DMAC2 */ ++ [MSTP216] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 16, 0), /* DMAC3 */ + [MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */ + [MSTP206] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */ + [MSTP204] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */ +@@ -563,7 +567,9 @@ static struct clk_lookup lookups[] = { + CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), + CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]), + CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), +- ++ CLKDEV_DEV_ID("sh-dma-engine.2", &mstp_clks[MSTP216]), ++ CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]), ++ CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), + CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP222]), + CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP230]), + +diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h +index 6468fcc..f71507b 100644 +--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h ++++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h +@@ -588,4 +588,12 @@ enum { + GPIO_FN_TRACEAUD_FROM_MEMC, + }; + ++/* DMA slave IDs */ ++enum { ++ SHDMA_SLAVE_INVALID, ++ SHDMA_SLAVE_FSIA_RX, ++ SHDMA_SLAVE_FSIA_TX, ++ SHDMA_SLAVE_FSIB_TX, ++}; ++ + #endif /* __ASM_R8A7740_H__ */ +diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c +index 366311b..516a7ec 100644 +--- a/arch/arm/mach-shmobile/setup-r8a7740.c ++++ b/arch/arm/mach-shmobile/setup-r8a7740.c +@@ -24,7 +24,9 @@ + #include <linux/io.h> + #include <linux/platform_device.h> + #include <linux/serial_sci.h> ++#include <linux/sh_dma.h> + #include <linux/sh_timer.h> ++#include <linux/dma-mapping.h> + #include <mach/r8a7740.h> + #include <mach/common.h> + #include <mach/irqs.h> +@@ -276,6 +278,199 @@ static struct platform_device *r8a7740_early_devices[] __initdata = { + &cmt10_device, + }; + ++/* DMA */ ++enum { ++ XMIT_SZ_8BIT = 0, ++ XMIT_SZ_16BIT = 1, ++ XMIT_SZ_32BIT = 2, ++ XMIT_SZ_64BIT = 7, ++ XMIT_SZ_128BIT = 3, ++ XMIT_SZ_256BIT = 4, ++ XMIT_SZ_512BIT = 5, ++}; ++ ++/* log2(size / 8) - used to calculate number of transfers */ ++#define TS_SHIFT { \ ++ [XMIT_SZ_8BIT] = 0, \ ++ [XMIT_SZ_16BIT] = 1, \ ++ [XMIT_SZ_32BIT] = 2, \ ++ [XMIT_SZ_64BIT] = 3, \ ++ [XMIT_SZ_128BIT] = 4, \ ++ [XMIT_SZ_256BIT] = 5, \ ++ [XMIT_SZ_512BIT] = 6, \ ++} ++ ++#define TS_INDEX2VAL(i) ((((i) & 0x3) << 3) | (((i) & 0xc) << (20 - 2))) ++#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz))) ++#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz))) ++ ++static const struct sh_dmae_slave_config r8a7740_dmae_slaves[] = { ++ { ++ .slave_id = SHDMA_SLAVE_FSIA_TX, ++ .addr = 0xfe1f0024, ++ .chcr = CHCR_TX(XMIT_SZ_32BIT), ++ .mid_rid = 0xb1, ++ }, { ++ .slave_id = SHDMA_SLAVE_FSIA_RX, ++ .addr = 0xfe1f0020, ++ .chcr = CHCR_RX(XMIT_SZ_32BIT), ++ .mid_rid = 0xb2, ++ }, { ++ .slave_id = SHDMA_SLAVE_FSIB_TX, ++ .addr = 0xfe1f0064, ++ .chcr = CHCR_TX(XMIT_SZ_32BIT), ++ .mid_rid = 0xb5, ++ }, ++}; ++ ++#define DMA_CHANNEL(a, b, c) \ ++{ \ ++ .offset = a, \ ++ .dmars = b, \ ++ .dmars_bit = c, \ ++ .chclr_offset = (0x220 - 0x20) + a \ ++} ++ ++static const struct sh_dmae_channel r8a7740_dmae_channels[] = { ++ DMA_CHANNEL(0x00, 0, 0), ++ DMA_CHANNEL(0x10, 0, 8), ++ DMA_CHANNEL(0x20, 4, 0), ++ DMA_CHANNEL(0x30, 4, 8), ++ DMA_CHANNEL(0x50, 8, 0), ++ DMA_CHANNEL(0x60, 8, 8), ++}; ++ ++static const unsigned int ts_shift[] = TS_SHIFT; ++ ++static struct sh_dmae_pdata dma_platform_data = { ++ .slave = r8a7740_dmae_slaves, ++ .slave_num = ARRAY_SIZE(r8a7740_dmae_slaves), ++ .channel = r8a7740_dmae_channels, ++ .channel_num = ARRAY_SIZE(r8a7740_dmae_channels), ++ .ts_low_shift = 3, ++ .ts_low_mask = 0x18, ++ .ts_high_shift = (20 - 2), ++ .ts_high_mask = 0x00300000, ++ .ts_shift = ts_shift, ++ .ts_shift_num = ARRAY_SIZE(ts_shift), ++ .dmaor_init = DMAOR_DME, ++ .chclr_present = 1, ++}; ++ ++/* Resource order important! */ ++static struct resource r8a7740_dmae0_resources[] = { ++ { ++ /* Channel registers and DMAOR */ ++ .start = 0xfe008020, ++ .end = 0xfe00828f, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ /* DMARSx */ ++ .start = 0xfe009000, ++ .end = 0xfe00900b, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = "error_irq", ++ .start = evt2irq(0x20c0), ++ .end = evt2irq(0x20c0), ++ .flags = IORESOURCE_IRQ, ++ }, ++ { ++ /* IRQ for channels 0-5 */ ++ .start = evt2irq(0x2000), ++ .end = evt2irq(0x20a0), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++/* Resource order important! */ ++static struct resource r8a7740_dmae1_resources[] = { ++ { ++ /* Channel registers and DMAOR */ ++ .start = 0xfe018020, ++ .end = 0xfe01828f, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ /* DMARSx */ ++ .start = 0xfe019000, ++ .end = 0xfe01900b, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = "error_irq", ++ .start = evt2irq(0x21c0), ++ .end = evt2irq(0x21c0), ++ .flags = IORESOURCE_IRQ, ++ }, ++ { ++ /* IRQ for channels 0-5 */ ++ .start = evt2irq(0x2100), ++ .end = evt2irq(0x21a0), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++/* Resource order important! */ ++static struct resource r8a7740_dmae2_resources[] = { ++ { ++ /* Channel registers and DMAOR */ ++ .start = 0xfe028020, ++ .end = 0xfe02828f, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ /* DMARSx */ ++ .start = 0xfe029000, ++ .end = 0xfe02900b, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = "error_irq", ++ .start = evt2irq(0x22c0), ++ .end = evt2irq(0x22c0), ++ .flags = IORESOURCE_IRQ, ++ }, ++ { ++ /* IRQ for channels 0-5 */ ++ .start = evt2irq(0x2200), ++ .end = evt2irq(0x22a0), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device dma0_device = { ++ .name = "sh-dma-engine", ++ .id = 0, ++ .resource = r8a7740_dmae0_resources, ++ .num_resources = ARRAY_SIZE(r8a7740_dmae0_resources), ++ .dev = { ++ .platform_data = &dma_platform_data, ++ }, ++}; ++ ++static struct platform_device dma1_device = { ++ .name = "sh-dma-engine", ++ .id = 1, ++ .resource = r8a7740_dmae1_resources, ++ .num_resources = ARRAY_SIZE(r8a7740_dmae1_resources), ++ .dev = { ++ .platform_data = &dma_platform_data, ++ }, ++}; ++ ++static struct platform_device dma2_device = { ++ .name = "sh-dma-engine", ++ .id = 2, ++ .resource = r8a7740_dmae2_resources, ++ .num_resources = ARRAY_SIZE(r8a7740_dmae2_resources), ++ .dev = { ++ .platform_data = &dma_platform_data, ++ }, ++}; ++ + /* I2C */ + static struct resource i2c0_resources[] = { + [0] = { +@@ -322,6 +517,9 @@ static struct platform_device i2c1_device = { + static struct platform_device *r8a7740_late_devices[] __initdata = { + &i2c0_device, + &i2c1_device, ++ &dma0_device, ++ &dma1_device, ++ &dma2_device, + }; + + /* +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0084-ARM-shmobile-r8a7740-add-DMAEngine-support-for-SDHI.patch b/patches.armadillo800/0084-ARM-shmobile-r8a7740-add-DMAEngine-support-for-SDHI.patch new file mode 100644 index 0000000000000..c76b22f9c08ec --- /dev/null +++ b/patches.armadillo800/0084-ARM-shmobile-r8a7740-add-DMAEngine-support-for-SDHI.patch @@ -0,0 +1,80 @@ +From b96167a50df2468ba7f7eb96fab0bec5e0ee7106 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 25 Jun 2012 03:37:00 -0700 +Subject: ARM: shmobile: r8a7740: add DMAEngine support for SDHI + +Current shdmac can support SDHI DMAC on r8a7740. +This support reduce CPU duty when SDHI access. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit cb76eb812ee03187da3b46e190895b55019d2133) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/include/mach/r8a7740.h | 6 ++++++ + arch/arm/mach-shmobile/setup-r8a7740.c | 30 +++++++++++++++++++++++++++ + 2 files changed, 36 insertions(+) + +diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h +index f71507b..0f14ce8 100644 +--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h ++++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h +@@ -591,6 +591,12 @@ enum { + /* DMA slave IDs */ + enum { + SHDMA_SLAVE_INVALID, ++ SHDMA_SLAVE_SDHI0_RX, ++ SHDMA_SLAVE_SDHI0_TX, ++ SHDMA_SLAVE_SDHI1_RX, ++ SHDMA_SLAVE_SDHI1_TX, ++ SHDMA_SLAVE_SDHI2_RX, ++ SHDMA_SLAVE_SDHI2_TX, + SHDMA_SLAVE_FSIA_RX, + SHDMA_SLAVE_FSIA_TX, + SHDMA_SLAVE_FSIB_TX, +diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c +index 516a7ec..320c43a 100644 +--- a/arch/arm/mach-shmobile/setup-r8a7740.c ++++ b/arch/arm/mach-shmobile/setup-r8a7740.c +@@ -306,6 +306,36 @@ enum { + + static const struct sh_dmae_slave_config r8a7740_dmae_slaves[] = { + { ++ .slave_id = SHDMA_SLAVE_SDHI0_TX, ++ .addr = 0xe6850030, ++ .chcr = CHCR_TX(XMIT_SZ_16BIT), ++ .mid_rid = 0xc1, ++ }, { ++ .slave_id = SHDMA_SLAVE_SDHI0_RX, ++ .addr = 0xe6850030, ++ .chcr = CHCR_RX(XMIT_SZ_16BIT), ++ .mid_rid = 0xc2, ++ }, { ++ .slave_id = SHDMA_SLAVE_SDHI1_TX, ++ .addr = 0xe6860030, ++ .chcr = CHCR_TX(XMIT_SZ_16BIT), ++ .mid_rid = 0xc9, ++ }, { ++ .slave_id = SHDMA_SLAVE_SDHI1_RX, ++ .addr = 0xe6860030, ++ .chcr = CHCR_RX(XMIT_SZ_16BIT), ++ .mid_rid = 0xca, ++ }, { ++ .slave_id = SHDMA_SLAVE_SDHI2_TX, ++ .addr = 0xe6870030, ++ .chcr = CHCR_TX(XMIT_SZ_16BIT), ++ .mid_rid = 0xcd, ++ }, { ++ .slave_id = SHDMA_SLAVE_SDHI2_RX, ++ .addr = 0xe6870030, ++ .chcr = CHCR_RX(XMIT_SZ_16BIT), ++ .mid_rid = 0xce, ++ }, { + .slave_id = SHDMA_SLAVE_FSIA_TX, + .addr = 0xfe1f0024, + .chcr = CHCR_TX(XMIT_SZ_32BIT), +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0085-ARM-shmobile-r8a7740-add-DMAEngine-support-for-USB.patch b/patches.armadillo800/0085-ARM-shmobile-r8a7740-add-DMAEngine-support-for-USB.patch new file mode 100644 index 0000000000000..4384aca2946ff --- /dev/null +++ b/patches.armadillo800/0085-ARM-shmobile-r8a7740-add-DMAEngine-support-for-USB.patch @@ -0,0 +1,170 @@ +From 59ea669a42f7a0fa16df6d769a6843d3060b64f2 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 25 Jun 2012 03:37:10 -0700 +Subject: ARM: shmobile: r8a7740: add DMAEngine support for USB + +Current shdmac can support USB DMAC on r8a7740. +This support reduce CPU duty when USB access. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit dbf382e556931aa75b2d7970d64661544d6c327c) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-r8a7740.c | 4 +- + arch/arm/mach-shmobile/include/mach/r8a7740.h | 2 + + arch/arm/mach-shmobile/setup-r8a7740.c | 87 +++++++++++++++++++++++++++ + 3 files changed, 92 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c +index 39b1311..daf3eac 100644 +--- a/arch/arm/mach-shmobile/clock-r8a7740.c ++++ b/arch/arm/mach-shmobile/clock-r8a7740.c +@@ -463,7 +463,7 @@ enum { + + MSTP230, + MSTP222, +- MSTP218, MSTP217, MSTP216, ++ MSTP218, MSTP217, MSTP216, MSTP214, + MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, + + MSTP329, MSTP328, MSTP323, MSTP320, +@@ -489,6 +489,7 @@ static struct clk mstp_clks[MSTP_NR] = { + [MSTP218] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* DMAC1 */ + [MSTP217] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 17, 0), /* DMAC2 */ + [MSTP216] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 16, 0), /* DMAC3 */ ++ [MSTP214] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 14, 0), /* USBDMAC */ + [MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */ + [MSTP206] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */ + [MSTP204] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */ +@@ -567,6 +568,7 @@ static struct clk_lookup lookups[] = { + CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), + CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]), + CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), ++ CLKDEV_DEV_ID("sh-dma-engine.3", &mstp_clks[MSTP214]), + CLKDEV_DEV_ID("sh-dma-engine.2", &mstp_clks[MSTP216]), + CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]), + CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), +diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h +index 0f14ce8..8bd7b9c 100644 +--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h ++++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h +@@ -600,6 +600,8 @@ enum { + SHDMA_SLAVE_FSIA_RX, + SHDMA_SLAVE_FSIA_TX, + SHDMA_SLAVE_FSIB_TX, ++ SHDMA_SLAVE_USBHS_TX, ++ SHDMA_SLAVE_USBHS_RX, + }; + + #endif /* __ASM_R8A7740_H__ */ +diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c +index 320c43a..5e84609 100644 +--- a/arch/arm/mach-shmobile/setup-r8a7740.c ++++ b/arch/arm/mach-shmobile/setup-r8a7740.c +@@ -501,6 +501,92 @@ static struct platform_device dma2_device = { + }, + }; + ++/* USB-DMAC */ ++/* Transmit sizes and respective CHCR register values */ ++enum { ++ USBTS_XMIT_SZ_8BYTE = 0, ++ USBTS_XMIT_SZ_16BYTE = 1, ++ USBTS_XMIT_SZ_32BYTE = 2, ++}; ++ ++/* log2(size / 8) - used to calculate number of transfers */ ++static const unsigned int dma_usbts_shift[] = { ++ [USBTS_XMIT_SZ_8BYTE] = 3, ++ [USBTS_XMIT_SZ_16BYTE] = 4, ++ [USBTS_XMIT_SZ_32BYTE] = 5, ++}; ++ ++static const struct sh_dmae_channel r8a7740_usb_dma_channels[] = { ++ { ++ .offset = 0, ++ }, { ++ .offset = 0x20, ++ }, ++}; ++ ++#define USBTS_INDEX2VAL(i) (((i) & 3) << 6) ++ ++static const struct sh_dmae_slave_config r8a7740_usb_dma_slaves[] = { ++ { ++ .slave_id = SHDMA_SLAVE_USBHS_TX, ++ .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE), ++ }, { ++ .slave_id = SHDMA_SLAVE_USBHS_RX, ++ .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE), ++ }, ++}; ++ ++static struct sh_dmae_pdata usb_dma_platform_data = { ++ .slave = r8a7740_usb_dma_slaves, ++ .slave_num = ARRAY_SIZE(r8a7740_usb_dma_slaves), ++ .channel = r8a7740_usb_dma_channels, ++ .channel_num = ARRAY_SIZE(r8a7740_usb_dma_channels), ++ .ts_low_shift = 6, ++ .ts_low_mask = 0xc0, ++ .ts_high_shift = 0, ++ .ts_high_mask = 0, ++ .ts_shift = dma_usbts_shift, ++ .ts_shift_num = ARRAY_SIZE(dma_usbts_shift), ++ .dmaor_init = DMAOR_DME, ++ .chcr_offset = 0x14, ++ .chcr_ie_bit = 1 << 5, ++ .dmaor_is_32bit = 1, ++ .needs_tend_set = 1, ++ .no_dmars = 1, ++ .slave_only = 1, ++}; ++ ++static struct resource r8a7740_usb_dma_resources[] = { ++ { ++ /* Channel registers and DMAOR */ ++ .start = 0xe68a0020, ++ .end = 0xe68a0064 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ /* VCR/SWR/DMICR */ ++ .start = 0xe68a0000, ++ .end = 0xe68a0014 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ /* IRQ for channels */ ++ .start = evt2irq(0x0a00), ++ .end = evt2irq(0x0a00), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device usb_dma_device = { ++ .name = "sh-dma-engine", ++ .id = 3, ++ .resource = r8a7740_usb_dma_resources, ++ .num_resources = ARRAY_SIZE(r8a7740_usb_dma_resources), ++ .dev = { ++ .platform_data = &usb_dma_platform_data, ++ }, ++}; ++ + /* I2C */ + static struct resource i2c0_resources[] = { + [0] = { +@@ -550,6 +636,7 @@ static struct platform_device *r8a7740_late_devices[] __initdata = { + &dma0_device, + &dma1_device, + &dma2_device, ++ &usb_dma_device, + }; + + /* +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0086-ARM-shmobile-use-common-DMAEngine-definitions-on-r8a.patch b/patches.armadillo800/0086-ARM-shmobile-use-common-DMAEngine-definitions-on-r8a.patch new file mode 100644 index 0000000000000..8233c22cb7f12 --- /dev/null +++ b/patches.armadillo800/0086-ARM-shmobile-use-common-DMAEngine-definitions-on-r8a.patch @@ -0,0 +1,139 @@ +From 5fa62ea250079de3ea68853067d0935524c3e766 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 25 Jun 2012 03:43:10 -0700 +Subject: ARM: shmobile: use common DMAEngine definitions on r8a7740 + +This patch switch over to use common DMAEngine definitions, +and reduced a waste of code. + +It is easy to understand if sh_dmae_pdata / sh_dmae_slave_config +settings are used defined value instead of direct value. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit d7de938f3da618b1592427f625e150c0a68b9ecb) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/setup-r8a7740.c | 64 ++++++---------------------------- + 1 file changed, 11 insertions(+), 53 deletions(-) + +diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c +index 5e84609..48d7bbf 100644 +--- a/arch/arm/mach-shmobile/setup-r8a7740.c ++++ b/arch/arm/mach-shmobile/setup-r8a7740.c +@@ -27,6 +27,7 @@ + #include <linux/sh_dma.h> + #include <linux/sh_timer.h> + #include <linux/dma-mapping.h> ++#include <mach/dma-register.h> + #include <mach/r8a7740.h> + #include <mach/common.h> + #include <mach/irqs.h> +@@ -279,31 +280,6 @@ static struct platform_device *r8a7740_early_devices[] __initdata = { + }; + + /* DMA */ +-enum { +- XMIT_SZ_8BIT = 0, +- XMIT_SZ_16BIT = 1, +- XMIT_SZ_32BIT = 2, +- XMIT_SZ_64BIT = 7, +- XMIT_SZ_128BIT = 3, +- XMIT_SZ_256BIT = 4, +- XMIT_SZ_512BIT = 5, +-}; +- +-/* log2(size / 8) - used to calculate number of transfers */ +-#define TS_SHIFT { \ +- [XMIT_SZ_8BIT] = 0, \ +- [XMIT_SZ_16BIT] = 1, \ +- [XMIT_SZ_32BIT] = 2, \ +- [XMIT_SZ_64BIT] = 3, \ +- [XMIT_SZ_128BIT] = 4, \ +- [XMIT_SZ_256BIT] = 5, \ +- [XMIT_SZ_512BIT] = 6, \ +-} +- +-#define TS_INDEX2VAL(i) ((((i) & 0x3) << 3) | (((i) & 0xc) << (20 - 2))) +-#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz))) +-#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz))) +- + static const struct sh_dmae_slave_config r8a7740_dmae_slaves[] = { + { + .slave_id = SHDMA_SLAVE_SDHI0_TX, +@@ -370,19 +346,17 @@ static const struct sh_dmae_channel r8a7740_dmae_channels[] = { + DMA_CHANNEL(0x60, 8, 8), + }; + +-static const unsigned int ts_shift[] = TS_SHIFT; +- + static struct sh_dmae_pdata dma_platform_data = { + .slave = r8a7740_dmae_slaves, + .slave_num = ARRAY_SIZE(r8a7740_dmae_slaves), + .channel = r8a7740_dmae_channels, + .channel_num = ARRAY_SIZE(r8a7740_dmae_channels), +- .ts_low_shift = 3, +- .ts_low_mask = 0x18, +- .ts_high_shift = (20 - 2), +- .ts_high_mask = 0x00300000, +- .ts_shift = ts_shift, +- .ts_shift_num = ARRAY_SIZE(ts_shift), ++ .ts_low_shift = TS_LOW_SHIFT, ++ .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT, ++ .ts_high_shift = TS_HI_SHIFT, ++ .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT, ++ .ts_shift = dma_ts_shift, ++ .ts_shift_num = ARRAY_SIZE(dma_ts_shift), + .dmaor_init = DMAOR_DME, + .chclr_present = 1, + }; +@@ -502,20 +476,6 @@ static struct platform_device dma2_device = { + }; + + /* USB-DMAC */ +-/* Transmit sizes and respective CHCR register values */ +-enum { +- USBTS_XMIT_SZ_8BYTE = 0, +- USBTS_XMIT_SZ_16BYTE = 1, +- USBTS_XMIT_SZ_32BYTE = 2, +-}; +- +-/* log2(size / 8) - used to calculate number of transfers */ +-static const unsigned int dma_usbts_shift[] = { +- [USBTS_XMIT_SZ_8BYTE] = 3, +- [USBTS_XMIT_SZ_16BYTE] = 4, +- [USBTS_XMIT_SZ_32BYTE] = 5, +-}; +- + static const struct sh_dmae_channel r8a7740_usb_dma_channels[] = { + { + .offset = 0, +@@ -524,8 +484,6 @@ static const struct sh_dmae_channel r8a7740_usb_dma_channels[] = { + }, + }; + +-#define USBTS_INDEX2VAL(i) (((i) & 3) << 6) +- + static const struct sh_dmae_slave_config r8a7740_usb_dma_slaves[] = { + { + .slave_id = SHDMA_SLAVE_USBHS_TX, +@@ -541,10 +499,10 @@ static struct sh_dmae_pdata usb_dma_platform_data = { + .slave_num = ARRAY_SIZE(r8a7740_usb_dma_slaves), + .channel = r8a7740_usb_dma_channels, + .channel_num = ARRAY_SIZE(r8a7740_usb_dma_channels), +- .ts_low_shift = 6, +- .ts_low_mask = 0xc0, +- .ts_high_shift = 0, +- .ts_high_mask = 0, ++ .ts_low_shift = USBTS_LOW_SHIFT, ++ .ts_low_mask = USBTS_LOW_BIT << USBTS_LOW_SHIFT, ++ .ts_high_shift = USBTS_HI_SHIFT, ++ .ts_high_mask = USBTS_HI_BIT << USBTS_HI_SHIFT, + .ts_shift = dma_usbts_shift, + .ts_shift_num = ARRAY_SIZE(dma_usbts_shift), + .dmaor_init = DMAOR_DME, +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0087-ARM-shmobile-armadillo800eva-enable-FSI-WM8978-sound.patch b/patches.armadillo800/0087-ARM-shmobile-armadillo800eva-enable-FSI-WM8978-sound.patch new file mode 100644 index 0000000000000..b62ac1815ed1f --- /dev/null +++ b/patches.armadillo800/0087-ARM-shmobile-armadillo800eva-enable-FSI-WM8978-sound.patch @@ -0,0 +1,184 @@ +From 2b0c07b75a3b421285bae10961bf20e0011839b6 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 25 Jun 2012 03:32:50 -0700 +Subject: ARM: shmobile: armadillo800eva: enable FSI-WM8978 sound + +This patch enable sound support on CON11 + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 5389bf719f87101339f292256392bff5ae926917) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/Kconfig | 1 + + arch/arm/mach-shmobile/board-armadillo800eva.c | 99 ++++++++++++++++++++++++++ + 2 files changed, 100 insertions(+) + +diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig +index da57dde..c74b74a 100644 +--- a/arch/arm/mach-shmobile/Kconfig ++++ b/arch/arm/mach-shmobile/Kconfig +@@ -100,6 +100,7 @@ config MACH_ARMADILLO800EVA + depends on ARCH_R8A7740 + select ARCH_REQUIRE_GPIOLIB + select USE_OF ++ select SND_SOC_WM8978 if SND_SIMPLE_CARD + + config MACH_MARZEN + bool "MARZEN board" +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index a513ebe..afe7860 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -49,6 +49,8 @@ + #include <asm/hardware/cache-l2x0.h> + #include <video/sh_mobile_lcdc.h> + #include <video/sh_mobile_hdmi.h> ++#include <sound/sh_fsi.h> ++#include <sound/simple_card.h> + + /* + * CON1 Camera Module +@@ -112,6 +114,28 @@ + */ + + /* ++ * FSI-WM8978 ++ * ++ * this command is required when playback. ++ * ++ * # amixer set "Headphone" 50 ++ */ ++ ++/* ++ * FIXME !! ++ * ++ * gpio_no_direction ++ * ++ * current gpio frame work doesn't have ++ * the method to control only pull up/down/free. ++ * this function should be replaced by correct gpio function ++ */ ++static void __init gpio_no_direction(u32 addr) ++{ ++ __raw_writeb(0x00, addr); ++} ++ ++/* + * USB function + * + * When you use USB Function, +@@ -714,12 +738,71 @@ static struct platform_device ceu0_device = { + }, + }; + ++/* FSI */ ++static struct sh_fsi_platform_info fsi_info = { ++ /* FSI-WM8978 */ ++ .port_a = { ++ }, ++}; ++ ++static struct resource fsi_resources[] = { ++ [0] = { ++ .name = "FSI", ++ .start = 0xfe1f0000, ++ .end = 0xfe1f8400 - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = evt2irq(0x1840), ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device fsi_device = { ++ .name = "sh_fsi2", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(fsi_resources), ++ .resource = fsi_resources, ++ .dev = { ++ .platform_data = &fsi_info, ++ }, ++}; ++ ++/* FSI-WM8978 */ ++static struct asoc_simple_dai_init_info fsi_wm8978_init_info = { ++ .fmt = SND_SOC_DAIFMT_I2S, ++ .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_NB_NF, ++ .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS, ++ .sysclk = 12288000, ++}; ++ ++static struct asoc_simple_card_info fsi_wm8978_info = { ++ .name = "wm8978", ++ .card = "FSI2A-WM8978", ++ .cpu_dai = "fsia-dai", ++ .codec = "wm8978.0-001a", ++ .platform = "sh_fsi2", ++ .codec_dai = "wm8978-hifi", ++ .init = &fsi_wm8978_init_info, ++}; ++ ++static struct platform_device fsi_wm8978_device = { ++ .name = "asoc-simple-card", ++ .id = 0, ++ .dev = { ++ .platform_data = &fsi_wm8978_info, ++ }, ++}; ++ + /* I2C */ + static struct i2c_board_info i2c0_devices[] = { + { + I2C_BOARD_INFO("st1232-ts", 0x55), + .irq = evt2irq(0x0340), + }, ++ { ++ I2C_BOARD_INFO("wm8978", 0x1a), ++ }, + }; + + /* +@@ -735,6 +818,8 @@ static struct platform_device *eva_devices[] __initdata = { + &hdmi_lcdc_device, + &camera_device, + &ceu0_device, ++ &fsi_device, ++ &fsi_wm8978_device, + }; + + static void __init eva_clock_init(void) +@@ -768,6 +853,8 @@ clock_error: + /* + * board init + */ ++#define GPIO_PORT7CR 0xe6050007 ++#define GPIO_PORT8CR 0xe6050008 + static void __init eva_init(void) + { + eva_clock_init(); +@@ -916,6 +1003,18 @@ static void __init eva_init(void) + gpio_direction_output(GPIO_PORT172, 1); + gpio_direction_output(GPIO_PORT158, 0); /* see mt9t111_power() */ + ++ /* FSI-WM8978 */ ++ gpio_request(GPIO_FN_FSIAIBT, NULL); ++ gpio_request(GPIO_FN_FSIAILR, NULL); ++ gpio_request(GPIO_FN_FSIAOMC, NULL); ++ gpio_request(GPIO_FN_FSIAOSLD, NULL); ++ gpio_request(GPIO_FN_FSIAISLD_PORT5, NULL); ++ ++ gpio_request(GPIO_PORT7, NULL); ++ gpio_request(GPIO_PORT8, NULL); ++ gpio_no_direction(GPIO_PORT7CR); /* FSIAOBT needs no direction */ ++ gpio_no_direction(GPIO_PORT8CR); /* FSIAOLR needs no direction */ ++ + /* + * CAUTION + * +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0088-ARM-shmobile-armadillo800eva-enable-FSI-HDMI-sound.patch b/patches.armadillo800/0088-ARM-shmobile-armadillo800eva-enable-FSI-HDMI-sound.patch new file mode 100644 index 0000000000000..120c3153d5cdf --- /dev/null +++ b/patches.armadillo800/0088-ARM-shmobile-armadillo800eva-enable-FSI-HDMI-sound.patch @@ -0,0 +1,176 @@ +From 850c6f996ee51eddf540325ec5c892073dbc2567 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 25 Jun 2012 03:33:04 -0700 +Subject: ARM: shmobile: armadillo800eva: enable FSI-HDMI sound + +This patch enable HDMI sound support on CON3 + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 0676c05e57c6e37fc9f985a8f6ea2883e5b2cbda) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 82 +++++++++++++++++++++++++- + 1 file changed, 79 insertions(+), 3 deletions(-) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index afe7860..df5fd2c 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -739,10 +739,42 @@ static struct platform_device ceu0_device = { + }; + + /* FSI */ ++static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable) ++{ ++ struct clk *fsib; ++ int ret; ++ ++ /* it support 48KHz only */ ++ if (48000 != rate) ++ return -EINVAL; ++ ++ fsib = clk_get(dev, "ickb"); ++ if (IS_ERR(fsib)) ++ return -EINVAL; ++ ++ if (enable) { ++ ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; ++ clk_enable(fsib); ++ } else { ++ ret = 0; ++ clk_disable(fsib); ++ } ++ ++ clk_put(fsib); ++ ++ return ret; ++} ++ + static struct sh_fsi_platform_info fsi_info = { + /* FSI-WM8978 */ + .port_a = { + }, ++ /* FSI-HDMI */ ++ .port_b = { ++ .flags = SH_FSI_FMT_SPDIF | ++ SH_FSI_ENABLE_STREAM_MODE, ++ .set_rate = fsi_hdmi_set_rate, ++ } + }; + + static struct resource fsi_resources[] = { +@@ -794,6 +826,29 @@ static struct platform_device fsi_wm8978_device = { + }, + }; + ++/* FSI-HDMI */ ++static struct asoc_simple_dai_init_info fsi2_hdmi_init_info = { ++ .cpu_daifmt = SND_SOC_DAIFMT_CBM_CFM, ++}; ++ ++static struct asoc_simple_card_info fsi2_hdmi_info = { ++ .name = "HDMI", ++ .card = "FSI2B-HDMI", ++ .cpu_dai = "fsib-dai", ++ .codec = "sh-mobile-hdmi", ++ .platform = "sh_fsi2", ++ .codec_dai = "sh_mobile_hdmi-hifi", ++ .init = &fsi2_hdmi_init_info, ++}; ++ ++static struct platform_device fsi_hdmi_device = { ++ .name = "asoc-simple-card", ++ .id = 1, ++ .dev = { ++ .platform_data = &fsi2_hdmi_info, ++ }, ++}; ++ + /* I2C */ + static struct i2c_board_info i2c0_devices[] = { + { +@@ -819,6 +874,7 @@ static struct platform_device *eva_devices[] __initdata = { + &camera_device, + &ceu0_device, + &fsi_device, ++ &fsi_hdmi_device, + &fsi_wm8978_device, + }; + +@@ -827,10 +883,14 @@ static void __init eva_clock_init(void) + struct clk *system = clk_get(NULL, "system_clk"); + struct clk *xtal1 = clk_get(NULL, "extal1"); + struct clk *usb24s = clk_get(NULL, "usb24s"); ++ struct clk *fsibck = clk_get(NULL, "fsibck"); ++ struct clk *fsib = clk_get(&fsi_device.dev, "ickb"); + + if (IS_ERR(system) || + IS_ERR(xtal1) || +- IS_ERR(usb24s)) { ++ IS_ERR(usb24s) || ++ IS_ERR(fsibck) || ++ IS_ERR(fsib)) { + pr_err("armadillo800eva board clock init failed\n"); + goto clock_error; + } +@@ -841,6 +901,11 @@ static void __init eva_clock_init(void) + /* usb24s use extal1 (= system) clock (= 24MHz) */ + clk_set_parent(usb24s, system); + ++ /* FSIBCK is 12.288MHz, and it is parent of FSI-B */ ++ clk_set_parent(fsib, fsibck); ++ clk_set_rate(fsibck, 12288000); ++ clk_set_rate(fsib, 12288000); ++ + clock_error: + if (!IS_ERR(system)) + clk_put(system); +@@ -848,6 +913,10 @@ clock_error: + clk_put(xtal1); + if (!IS_ERR(usb24s)) + clk_put(usb24s); ++ if (!IS_ERR(fsibck)) ++ clk_put(fsibck); ++ if (!IS_ERR(fsib)) ++ clk_put(fsib); + } + + /* +@@ -857,8 +926,6 @@ clock_error: + #define GPIO_PORT8CR 0xe6050008 + static void __init eva_init(void) + { +- eva_clock_init(); +- + r8a7740_pinmux_init(); + r8a7740_meram_workaround(); + +@@ -1015,6 +1082,13 @@ static void __init eva_init(void) + gpio_no_direction(GPIO_PORT7CR); /* FSIAOBT needs no direction */ + gpio_no_direction(GPIO_PORT8CR); /* FSIAOLR needs no direction */ + ++ /* FSI-HDMI */ ++ gpio_request(GPIO_FN_FSIBCK, NULL); ++ ++ /* HDMI */ ++ gpio_request(GPIO_FN_HDMI_HPD, NULL); ++ gpio_request(GPIO_FN_HDMI_CEC, NULL); ++ + /* + * CAUTION + * +@@ -1061,6 +1135,8 @@ static void __init eva_init(void) + + platform_add_devices(eva_devices, + ARRAY_SIZE(eva_devices)); ++ ++ eva_clock_init(); + } + + static void __init eva_earlytimer_init(void) +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0089-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-FSI.patch b/patches.armadillo800/0089-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-FSI.patch new file mode 100644 index 0000000000000..e2c925f1c6a57 --- /dev/null +++ b/patches.armadillo800/0089-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-FSI.patch @@ -0,0 +1,54 @@ +From 95f8bc86715253ac6371cf581049a13a0a1d94eb Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 25 Jun 2012 03:37:20 -0700 +Subject: ARM: shmobile: armadillo800eva: enable DMAEngine on FSI + +It is possible to reduce CPU load if FSI playback used DMAEngine. +This patch enabled it. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit dc7dd5841f714c3bc3f358cb126ba4432947e854) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/configs/armadillo800eva_defconfig | 2 ++ + arch/arm/mach-shmobile/board-armadillo800eva.c | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig +index df1ce54..16bbb3f 100644 +--- a/arch/arm/configs/armadillo800eva_defconfig ++++ b/arch/arm/configs/armadillo800eva_defconfig +@@ -119,6 +119,8 @@ CONFIG_USB_ETH=m + CONFIG_MMC=y + CONFIG_MMC_SDHI=y + CONFIG_MMC_SH_MMCIF=y ++CONFIG_DMADEVICES=y ++CONFIG_SH_DMAE=y + CONFIG_UIO=y + CONFIG_UIO_PDRV_GENIRQ=y + # CONFIG_DNOTIFY is not set +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index df5fd2c..032e04d 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -768,12 +768,14 @@ static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable) + static struct sh_fsi_platform_info fsi_info = { + /* FSI-WM8978 */ + .port_a = { ++ .tx_id = SHDMA_SLAVE_FSIA_TX, + }, + /* FSI-HDMI */ + .port_b = { + .flags = SH_FSI_FMT_SPDIF | + SH_FSI_ENABLE_STREAM_MODE, + .set_rate = fsi_hdmi_set_rate, ++ .tx_id = SHDMA_SLAVE_FSIB_TX, + } + }; + +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0090-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-SDH.patch b/patches.armadillo800/0090-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-SDH.patch new file mode 100644 index 0000000000000..7b80c65db76bf --- /dev/null +++ b/patches.armadillo800/0090-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-SDH.patch @@ -0,0 +1,43 @@ +From 67c3e7eb10a9da8600072c0b2292287dafe97219 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 25 Jun 2012 03:37:38 -0700 +Subject: ARM: shmobile: armadillo800eva: enable DMAEngine on SDHI + +It is possible to reduce CPU load if SDHI used DMAEngine. +This patch enabled it. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 95798e350dde44920a021a7e7e720a3be15e8220) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index 032e04d..54bf618 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -543,6 +543,8 @@ static struct platform_device gpio_keys_device = { + */ + #define IRQ31 evt2irq(0x33E0) + static struct sh_mobile_sdhi_info sdhi0_info = { ++ .dma_slave_tx = SHDMA_SLAVE_SDHI0_TX, ++ .dma_slave_rx = SHDMA_SLAVE_SDHI0_RX, + .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |\ + MMC_CAP_NEEDS_POLL, + .tmio_ocr_mask = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34, +@@ -583,6 +585,8 @@ static struct platform_device sdhi0_device = { + + /* SDHI1 */ + static struct sh_mobile_sdhi_info sdhi1_info = { ++ .dma_slave_tx = SHDMA_SLAVE_SDHI1_TX, ++ .dma_slave_rx = SHDMA_SLAVE_SDHI1_RX, + .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, + .tmio_ocr_mask = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34, + .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT, +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0091-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-USB.patch b/patches.armadillo800/0091-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-USB.patch new file mode 100644 index 0000000000000..27ccbe4039b8a --- /dev/null +++ b/patches.armadillo800/0091-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-USB.patch @@ -0,0 +1,34 @@ +From ad78daa637449523d9cdfd7b28f5ea0150ac349a Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 25 Jun 2012 03:37:47 -0700 +Subject: ARM: shmobile: armadillo800eva: enable DMAEngine on USB + +It is possible to reduce CPU load if USB used DMAEngine. +This patch enabled it. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit f7e566fa26b7d34514d5ba7b8b4464934be8ff2c) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index 54bf618..539f1cf 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -297,6 +297,8 @@ static struct usbhsf_private usbhsf_private = { + .driver_param = { + .buswait_bwait = 5, + .detection_delay = 5, ++ .d0_rx_id = SHDMA_SLAVE_USBHS_RX, ++ .d1_tx_id = SHDMA_SLAVE_USBHS_TX, + }, + } + }; +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0092-ARM-shmobile-use-common-extra-gpio-functions-on-arma.patch b/patches.armadillo800/0092-ARM-shmobile-use-common-extra-gpio-functions-on-arma.patch new file mode 100644 index 0000000000000..897c4321f1f99 --- /dev/null +++ b/patches.armadillo800/0092-ARM-shmobile-use-common-extra-gpio-functions-on-arma.patch @@ -0,0 +1,60 @@ +From 2d6b318376b8c20432ed164d31b047a74c6d5215 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 25 Jun 2012 03:41:45 -0700 +Subject: ARM: shmobile: use common extra gpio functions on armadillo800eva + +This patch switch over to use common extra gpio method, +and reduced a waste of code on SH-ARM. + +But these functions should be replaced by correct +gpio function in the future. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit a01366b4b5cc669633d1cf6ee327c85a5406ef5f) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 18 ++---------------- + 1 file changed, 2 insertions(+), 16 deletions(-) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index 539f1cf..a4fd71a 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -122,20 +122,6 @@ + */ + + /* +- * FIXME !! +- * +- * gpio_no_direction +- * +- * current gpio frame work doesn't have +- * the method to control only pull up/down/free. +- * this function should be replaced by correct gpio function +- */ +-static void __init gpio_no_direction(u32 addr) +-{ +- __raw_writeb(0x00, addr); +-} +- +-/* + * USB function + * + * When you use USB Function, +@@ -1087,8 +1073,8 @@ static void __init eva_init(void) + + gpio_request(GPIO_PORT7, NULL); + gpio_request(GPIO_PORT8, NULL); +- gpio_no_direction(GPIO_PORT7CR); /* FSIAOBT needs no direction */ +- gpio_no_direction(GPIO_PORT8CR); /* FSIAOLR needs no direction */ ++ gpio_direction_none(GPIO_PORT7CR); /* FSIAOBT needs no direction */ ++ gpio_direction_none(GPIO_PORT8CR); /* FSIAOLR needs no direction */ + + /* FSI-HDMI */ + gpio_request(GPIO_FN_FSIBCK, NULL); +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0093-ARM-mach-shmobile-add-fixed-voltage-regulators-to-ar.patch b/patches.armadillo800/0093-ARM-mach-shmobile-add-fixed-voltage-regulators-to-ar.patch new file mode 100644 index 0000000000000..2024d81a86244 --- /dev/null +++ b/patches.armadillo800/0093-ARM-mach-shmobile-add-fixed-voltage-regulators-to-ar.patch @@ -0,0 +1,61 @@ +From 6a9259faadbdfcb18a8f2ee78d414ae7194a2b10 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Fri, 29 Jun 2012 08:33:11 +0200 +Subject: ARM: mach-shmobile: add fixed voltage regulators to armadillo800eva + +On armadillo800eva provide a 3.3V supply for its SD/MMC-card interfaces. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit f65ad7e36cbae24f05ea2314ad63e9dd23294c60) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index a4fd71a..7c77f07 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -28,6 +28,8 @@ + #include <linux/platform_device.h> + #include <linux/gpio.h> + #include <linux/gpio_keys.h> ++#include <linux/regulator/fixed.h> ++#include <linux/regulator/machine.h> + #include <linux/sh_eth.h> + #include <linux/videodev2.h> + #include <linux/usb/renesas_usbhs.h> +@@ -520,6 +522,17 @@ static struct platform_device gpio_keys_device = { + }, + }; + ++/* Fixed 3.3V regulator to be used by SDHI0, SDHI1, MMCIF */ ++static struct regulator_consumer_supply fixed3v3_power_consumers[] = ++{ ++ REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"), ++ REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"), ++ REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"), ++ REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.1"), ++ REGULATOR_SUPPLY("vmmc", "sh_mmcif"), ++ REGULATOR_SUPPLY("vqmmc", "sh_mmcif"), ++}; ++ + /* SDHI0 */ + /* + * FIXME +@@ -920,6 +933,9 @@ clock_error: + #define GPIO_PORT8CR 0xe6050008 + static void __init eva_init(void) + { ++ regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers, ++ ARRAY_SIZE(fixed3v3_power_consumers), 3300000); ++ + r8a7740_pinmux_init(); + r8a7740_meram_workaround(); + +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0094-ARM-mach-shmobile-Convert-sh_clk_mstp32_register-to-.patch b/patches.armadillo800/0094-ARM-mach-shmobile-Convert-sh_clk_mstp32_register-to-.patch new file mode 100644 index 0000000000000..0b7bb32b076a7 --- /dev/null +++ b/patches.armadillo800/0094-ARM-mach-shmobile-Convert-sh_clk_mstp32_register-to-.patch @@ -0,0 +1,107 @@ +From 34b7faf5447e1eefc86e43779a132ad8e8cf5c32 Mon Sep 17 00:00:00 2001 +From: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> +Date: Wed, 27 Jun 2012 09:59:00 +0900 +Subject: ARM: mach-shmobile: Convert sh_clk_mstp32_register to + sh_clk_mstp_register + +sh_clk_mstp32_register is deprecated. This convert to sh_clk_mstp_register. + +Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 64e9de2f854fb5d08d255b24568c60b090f2603a) + +Conflicts: + arch/arm/mach-shmobile/clock-r8a7740.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/clock-r8a7740.c | 2 +- + arch/arm/mach-shmobile/clock-r8a7779.c | 2 +- + arch/arm/mach-shmobile/clock-sh7367.c | 2 +- + arch/arm/mach-shmobile/clock-sh7372.c | 2 +- + arch/arm/mach-shmobile/clock-sh7377.c | 2 +- + arch/arm/mach-shmobile/clock-sh73a0.c | 2 +- + 6 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c +index daf3eac..ad5fccc 100644 +--- a/arch/arm/mach-shmobile/clock-r8a7740.c ++++ b/arch/arm/mach-shmobile/clock-r8a7740.c +@@ -636,7 +636,7 @@ void __init r8a7740_clock_init(u8 md_ck) + DIV6_REPARENT_NR); + + if (!ret) +- ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); ++ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); + + for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++) + ret = clk_register(late_main_clks[k]); +diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c +index 7d6e9fe..339c62c 100644 +--- a/arch/arm/mach-shmobile/clock-r8a7779.c ++++ b/arch/arm/mach-shmobile/clock-r8a7779.c +@@ -162,7 +162,7 @@ void __init r8a7779_clock_init(void) + ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); + + if (!ret) +- ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); ++ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); + + for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++) + ret = clk_register(late_main_clks[k]); +diff --git a/arch/arm/mach-shmobile/clock-sh7367.c b/arch/arm/mach-shmobile/clock-sh7367.c +index 006e7b5..162b791 100644 +--- a/arch/arm/mach-shmobile/clock-sh7367.c ++++ b/arch/arm/mach-shmobile/clock-sh7367.c +@@ -344,7 +344,7 @@ void __init sh7367_clock_init(void) + ret = sh_clk_div6_register(div6_clks, DIV6_NR); + + if (!ret) +- ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); ++ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); + + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + +diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c +index 94d1f88..5a2894b 100644 +--- a/arch/arm/mach-shmobile/clock-sh7372.c ++++ b/arch/arm/mach-shmobile/clock-sh7372.c +@@ -704,7 +704,7 @@ void __init sh7372_clock_init(void) + ret = sh_clk_div6_reparent_register(div6_reparent_clks, DIV6_REPARENT_NR); + + if (!ret) +- ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); ++ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); + + for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++) + ret = clk_register(late_main_clks[k]); +diff --git a/arch/arm/mach-shmobile/clock-sh7377.c b/arch/arm/mach-shmobile/clock-sh7377.c +index 0798a15..85f2a3e 100644 +--- a/arch/arm/mach-shmobile/clock-sh7377.c ++++ b/arch/arm/mach-shmobile/clock-sh7377.c +@@ -355,7 +355,7 @@ void __init sh7377_clock_init(void) + ret = sh_clk_div6_register(div6_clks, DIV6_NR); + + if (!ret) +- ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); ++ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); + + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + +diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c +index 472d1f5..f6788be 100644 +--- a/arch/arm/mach-shmobile/clock-sh73a0.c ++++ b/arch/arm/mach-shmobile/clock-sh73a0.c +@@ -612,7 +612,7 @@ void __init sh73a0_clock_init(void) + ret = sh_clk_div6_reparent_register(div6_clks, DIV6_NR); + + if (!ret) +- ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); ++ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); + + for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++) + ret = clk_register(late_main_clks[k]); +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0095-ARM-shmobile-r8a7740-fixup-MSEL1CR-7bit-control.patch b/patches.armadillo800/0095-ARM-shmobile-r8a7740-fixup-MSEL1CR-7bit-control.patch new file mode 100644 index 0000000000000..f609f35d3a170 --- /dev/null +++ b/patches.armadillo800/0095-ARM-shmobile-r8a7740-fixup-MSEL1CR-7bit-control.patch @@ -0,0 +1,45 @@ +From e52c21c95e6ce158bd78d4b0d3b55fb4350beb4a Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 5 Jul 2012 01:25:24 -0700 +Subject: ARM: shmobile: r8a7740: fixup: MSEL1CR 7bit control + +MSEL1CR 7bit selects IRQ7 source pin which was +VBUS pin or A21/MSIOF0_RSYNC/MSIOF1_TSYNC pin. +But current pfc-r8a7740 MSEL1CR 7bit setting was wrong. +This patch fix it up + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 444c5ed8d746140cd8f5591f708e5f1f84a9876e) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/pfc-r8a7740.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c +index 03def0f..ce9e7fa 100644 +--- a/arch/arm/mach-shmobile/pfc-r8a7740.c ++++ b/arch/arm/mach-shmobile/pfc-r8a7740.c +@@ -1261,7 +1261,7 @@ static pinmux_enum_t pinmux_data[] = { + PINMUX_DATA(A21_MARK, PORT120_FN1), + PINMUX_DATA(MSIOF0_RSYNC_MARK, PORT120_FN2), + PINMUX_DATA(MSIOF1_TSYNC_PORT120_MARK, PORT120_FN3, MSEL4CR_10_0), +- PINMUX_DATA(IRQ7_PORT120_MARK, PORT120_FN0, MSEL1CR_7_0), ++ PINMUX_DATA(IRQ7_PORT120_MARK, PORT120_FN0, MSEL1CR_7_1), + + /* Port121 */ + PINMUX_DATA(A20_MARK, PORT121_FN1), +@@ -1623,7 +1623,7 @@ static pinmux_enum_t pinmux_data[] = { + + /* Port209 */ + PINMUX_DATA(VBUS_MARK, PORT209_FN1), +- PINMUX_DATA(IRQ7_PORT209_MARK, PORT209_FN0, MSEL1CR_7_1), ++ PINMUX_DATA(IRQ7_PORT209_MARK, PORT209_FN0, MSEL1CR_7_0), + + /* Port210 */ + PINMUX_DATA(IRQ9_PORT210_MARK, PORT210_FN0, MSEL1CR_9_1), +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0096-ARM-shmobile-r8a7740-add-A4S-pm-domain-support.patch b/patches.armadillo800/0096-ARM-shmobile-r8a7740-add-A4S-pm-domain-support.patch new file mode 100644 index 0000000000000..be5eee6388c00 --- /dev/null +++ b/patches.armadillo800/0096-ARM-shmobile-r8a7740-add-A4S-pm-domain-support.patch @@ -0,0 +1,122 @@ +From cfbc3351777b8b9160e410b3f1dfdb2558214b1a Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 5 Jul 2012 01:25:58 -0700 +Subject: ARM: shmobile: r8a7740: add A4S pm domain support + +This patch adds basic A4S pm domain support. +Now, below devices can be controled by PM + +Common-SHwy, Common-HPB, BSC, MFI, MMFROM, HS-SHwy, +SYS-HPB, INTCA, DBSC, DDRPHY (Logic), +ATAPI, GbEther, AXI-bus + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 8459293c27bcd13aabacb7ee8097f6818f2ceedb) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/Makefile | 1 + + arch/arm/mach-shmobile/include/mach/r8a7740.h | 6 ++++++ + arch/arm/mach-shmobile/pm-r8a7740.c | 30 +++++++++++++++++++++++++++ + arch/arm/mach-shmobile/setup-r8a7740.c | 5 +++++ + 4 files changed, 42 insertions(+) + create mode 100644 arch/arm/mach-shmobile/pm-r8a7740.c + +diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile +index b39033b..7804bd1 100644 +--- a/arch/arm/mach-shmobile/Makefile ++++ b/arch/arm/mach-shmobile/Makefile +@@ -39,6 +39,7 @@ obj-$(CONFIG_SUSPEND) += suspend.o + obj-$(CONFIG_CPU_IDLE) += cpuidle.o + obj-$(CONFIG_ARCH_SHMOBILE) += pm-rmobile.o + obj-$(CONFIG_ARCH_SH7372) += pm-sh7372.o sleep-sh7372.o ++obj-$(CONFIG_ARCH_R8A7740) += pm-r8a7740.o + obj-$(CONFIG_ARCH_R8A7779) += pm-r8a7779.o + + # Board objects +diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h +index 8bd7b9c..e8c87e9 100644 +--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h ++++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h +@@ -19,6 +19,8 @@ + #ifndef __ASM_R8A7740_H__ + #define __ASM_R8A7740_H__ + ++#include <mach/pm-rmobile.h> ++ + /* + * MD_CKx pin + */ +@@ -604,4 +606,8 @@ enum { + SHDMA_SLAVE_USBHS_RX, + }; + ++#ifdef CONFIG_PM ++extern struct rmobile_pm_domain r8a7740_pd_a4s; ++#endif /* CONFIG_PM */ ++ + #endif /* __ASM_R8A7740_H__ */ +diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c +new file mode 100644 +index 0000000..d2fe815 +--- /dev/null ++++ b/arch/arm/mach-shmobile/pm-r8a7740.c +@@ -0,0 +1,30 @@ ++/* ++ * r8a7740 power management support ++ * ++ * Copyright (C) 2012 Renesas Solutions Corp. ++ * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> ++ * ++ * 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 <mach/pm-rmobile.h> ++ ++#ifdef CONFIG_PM ++static int r8a7740_pd_a4s_suspend(void) ++{ ++ /* ++ * The A4S domain contains the CPU core and therefore it should ++ * only be turned off if the CPU is in use. ++ */ ++ return -EBUSY; ++} ++ ++struct rmobile_pm_domain r8a7740_pd_a4s = { ++ .genpd.name = "A4S", ++ .bit_shift = 10, ++ .gov = &pm_domain_always_on_gov, ++ .no_debug = true, ++ .suspend = r8a7740_pd_a4s_suspend, ++}; ++#endif /* CONFIG_PM */ +diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c +index 48d7bbf..c37ad75 100644 +--- a/arch/arm/mach-shmobile/setup-r8a7740.c ++++ b/arch/arm/mach-shmobile/setup-r8a7740.c +@@ -29,6 +29,7 @@ + #include <linux/dma-mapping.h> + #include <mach/dma-register.h> + #include <mach/r8a7740.h> ++#include <mach/pm-rmobile.h> + #include <mach/common.h> + #include <mach/irqs.h> + #include <asm/mach-types.h> +@@ -671,6 +672,10 @@ void __init r8a7740_add_standard_devices(void) + r8a7740_i2c_workaround(&i2c0_device); + r8a7740_i2c_workaround(&i2c1_device); + ++ /* PM domain */ ++ rmobile_init_pm_domain(&r8a7740_pd_a4s); ++ ++ /* add devices */ + platform_add_devices(r8a7740_early_devices, + ARRAY_SIZE(r8a7740_early_devices)); + platform_add_devices(r8a7740_late_devices, +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0097-ARM-shmobile-r8a7740-add-A3SP-pm-domain-support.patch b/patches.armadillo800/0097-ARM-shmobile-r8a7740-add-A3SP-pm-domain-support.patch new file mode 100644 index 0000000000000..3a6b491842d2a --- /dev/null +++ b/patches.armadillo800/0097-ARM-shmobile-r8a7740-add-A3SP-pm-domain-support.patch @@ -0,0 +1,107 @@ +From 12c6836de664df0456e3d827b605ef1bf4bb323a Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 5 Jul 2012 01:26:31 -0700 +Subject: ARM: shmobile: r8a7740: add A3SP pm domain support + +This patch adds basic A3SP pm domain support. +Now, below devices can be controled by PM + +DMAC1/2/3, IPMMU, DDM, FLCTL, SYS-HPB, BBIF1, MSIOF1/2, +SCIFA,SCIFB, IIC1, IrDA, USBH, USBDMAC, SDHI0/1/2, TPU, +DREQPAK (Sys), MMCIF, RSPI, SIM, USBF + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 802a5639aa7041b27cb865d3be289cd8afe3387b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/include/mach/r8a7740.h | 1 + + arch/arm/mach-shmobile/pm-r8a7740.c | 19 +++++++++++++++++++ + arch/arm/mach-shmobile/setup-r8a7740.c | 16 ++++++++++++++++ + 3 files changed, 36 insertions(+) + +diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h +index e8c87e9..a5691cf 100644 +--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h ++++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h +@@ -608,6 +608,7 @@ enum { + + #ifdef CONFIG_PM + extern struct rmobile_pm_domain r8a7740_pd_a4s; ++extern struct rmobile_pm_domain r8a7740_pd_a3sp; + #endif /* CONFIG_PM */ + + #endif /* __ASM_R8A7740_H__ */ +diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c +index d2fe815..de7c621 100644 +--- a/arch/arm/mach-shmobile/pm-r8a7740.c ++++ b/arch/arm/mach-shmobile/pm-r8a7740.c +@@ -8,6 +8,7 @@ + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ ++#include <linux/console.h> + #include <mach/pm-rmobile.h> + + #ifdef CONFIG_PM +@@ -27,4 +28,22 @@ struct rmobile_pm_domain r8a7740_pd_a4s = { + .no_debug = true, + .suspend = r8a7740_pd_a4s_suspend, + }; ++ ++static int r8a7740_pd_a3sp_suspend(void) ++{ ++ /* ++ * Serial consoles make use of SCIF hardware located in A3SP, ++ * keep such power domain on if "no_console_suspend" is set. ++ */ ++ return console_suspend_enabled ? 0 : -EBUSY; ++} ++ ++struct rmobile_pm_domain r8a7740_pd_a3sp = { ++ .genpd.name = "A3SP", ++ .bit_shift = 11, ++ .gov = &pm_domain_always_on_gov, ++ .no_debug = true, ++ .suspend = r8a7740_pd_a3sp_suspend, ++}; ++ + #endif /* CONFIG_PM */ +diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c +index c37ad75..59c79412 100644 +--- a/arch/arm/mach-shmobile/setup-r8a7740.c ++++ b/arch/arm/mach-shmobile/setup-r8a7740.c +@@ -674,12 +674,28 @@ void __init r8a7740_add_standard_devices(void) + + /* PM domain */ + rmobile_init_pm_domain(&r8a7740_pd_a4s); ++ rmobile_init_pm_domain(&r8a7740_pd_a3sp); ++ ++ rmobile_pm_add_subdomain(&r8a7740_pd_a4s, &r8a7740_pd_a3sp); + + /* add devices */ + platform_add_devices(r8a7740_early_devices, + ARRAY_SIZE(r8a7740_early_devices)); + platform_add_devices(r8a7740_late_devices, + ARRAY_SIZE(r8a7740_late_devices)); ++ ++ /* add devices to PM domain */ ++ ++ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif0_device); ++ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif1_device); ++ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif2_device); ++ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif3_device); ++ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif4_device); ++ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif5_device); ++ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif6_device); ++ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif7_device); ++ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scifb_device); ++ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &i2c1_device); + } + + static void __init r8a7740_earlytimer_init(void) +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0098-ARM-shmobile-r8a7740-add-A4LC-pm-domain-support.patch b/patches.armadillo800/0098-ARM-shmobile-r8a7740-add-A4LC-pm-domain-support.patch new file mode 100644 index 0000000000000..b3b936d34863d --- /dev/null +++ b/patches.armadillo800/0098-ARM-shmobile-r8a7740-add-A4LC-pm-domain-support.patch @@ -0,0 +1,63 @@ +From ffd8b73a5eead1c3d0361edd426cd5560a853b6c Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 5 Jul 2012 01:26:53 -0700 +Subject: ARM: shmobile: r8a7740: add A4LC pm domain support + +This patch adds basic A4LC pm domain support. +Now, below devices can be controled by PM + +MERAM, LCDC, VOU, ICBS, SDENC-Link + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit a330ce3cdaba5202051edf8ae69482e15fdc9db5) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/include/mach/r8a7740.h | 1 + + arch/arm/mach-shmobile/pm-r8a7740.c | 5 +++++ + arch/arm/mach-shmobile/setup-r8a7740.c | 1 + + 3 files changed, 7 insertions(+) + +diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h +index a5691cf..7143147 100644 +--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h ++++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h +@@ -609,6 +609,7 @@ enum { + #ifdef CONFIG_PM + extern struct rmobile_pm_domain r8a7740_pd_a4s; + extern struct rmobile_pm_domain r8a7740_pd_a3sp; ++extern struct rmobile_pm_domain r8a7740_pd_a4lc; + #endif /* CONFIG_PM */ + + #endif /* __ASM_R8A7740_H__ */ +diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c +index de7c621..893504d 100644 +--- a/arch/arm/mach-shmobile/pm-r8a7740.c ++++ b/arch/arm/mach-shmobile/pm-r8a7740.c +@@ -46,4 +46,9 @@ struct rmobile_pm_domain r8a7740_pd_a3sp = { + .suspend = r8a7740_pd_a3sp_suspend, + }; + ++struct rmobile_pm_domain r8a7740_pd_a4lc = { ++ .genpd.name = "A4LC", ++ .bit_shift = 1, ++}; ++ + #endif /* CONFIG_PM */ +diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c +index 59c79412..c006d8d 100644 +--- a/arch/arm/mach-shmobile/setup-r8a7740.c ++++ b/arch/arm/mach-shmobile/setup-r8a7740.c +@@ -675,6 +675,7 @@ void __init r8a7740_add_standard_devices(void) + /* PM domain */ + rmobile_init_pm_domain(&r8a7740_pd_a4s); + rmobile_init_pm_domain(&r8a7740_pd_a3sp); ++ rmobile_init_pm_domain(&r8a7740_pd_a4lc); + + rmobile_pm_add_subdomain(&r8a7740_pd_a4s, &r8a7740_pd_a3sp); + +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0099-ARM-shmobile-armadillo800eva-USB-Func-enables-extern.patch b/patches.armadillo800/0099-ARM-shmobile-armadillo800eva-USB-Func-enables-extern.patch new file mode 100644 index 0000000000000..05a8453ce3075 --- /dev/null +++ b/patches.armadillo800/0099-ARM-shmobile-armadillo800eva-USB-Func-enables-extern.patch @@ -0,0 +1,130 @@ +From a15b184d2c262c2133a1573ae9516633fdaf6f60 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 5 Jul 2012 01:27:14 -0700 +Subject: ARM: shmobile: armadillo800eva: USB Func enables external IRQ mode + +We can control renesas_usbhs driver as 2 way which are +autonomy mode and external IRQ trigger mode. + +Autonomy mode is very easy settings for platform, +but it required USB power domain always ON, +since its connection/disconnection IRQ come from it. + +If platform uses external IRQ trigger mode, +USB power domain can be OFF, since its +connection/disconnection IRQ come from external IRQ. + +This patch enable external IRQ mode. +Now it is possible to add USB support on A4SP domain. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit d483b983a5efaa101714186a8485a5fd4de42fba) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 46 +++++++++++++++++++++----- + 1 file changed, 38 insertions(+), 8 deletions(-) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index 7c77f07..5002f64 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -133,14 +133,8 @@ + * These are a little bit complex. + * see + * usbhsf_power_ctrl() +- * +- * CAUTION +- * +- * It uses autonomy mode for USB hotplug at this point +- * (= usbhs_private.platform_callback.get_vbus is NULL), +- * since we don't know what's happen on PM control +- * on this workaround. + */ ++#define IRQ7 evt2irq(0x02e0) + #define USBCR1 0xe605810a + #define USBH 0xC6700000 + #define USBH_USBCTR 0x10834 +@@ -220,6 +214,20 @@ static void usbhsf_power_ctrl(struct platform_device *pdev, + } + } + ++static int usbhsf_get_vbus(struct platform_device *pdev) ++{ ++ return gpio_get_value(GPIO_PORT209); ++} ++ ++static irqreturn_t usbhsf_interrupt(int irq, void *data) ++{ ++ struct platform_device *pdev = data; ++ ++ renesas_usbhs_call_notify_hotplug(pdev); ++ ++ return IRQ_HANDLED; ++} ++ + static void usbhsf_hardware_exit(struct platform_device *pdev) + { + struct usbhsf_private *priv = usbhsf_get_priv(pdev); +@@ -243,11 +251,14 @@ static void usbhsf_hardware_exit(struct platform_device *pdev) + priv->host = NULL; + priv->func = NULL; + priv->usbh_base = NULL; ++ ++ free_irq(IRQ7, pdev); + } + + static int usbhsf_hardware_init(struct platform_device *pdev) + { + struct usbhsf_private *priv = usbhsf_get_priv(pdev); ++ int ret; + + priv->phy = clk_get(&pdev->dev, "phy"); + priv->usb24 = clk_get(&pdev->dev, "usb24"); +@@ -267,6 +278,14 @@ static int usbhsf_hardware_init(struct platform_device *pdev) + return -EIO; + } + ++ ret = request_irq(IRQ7, usbhsf_interrupt, IRQF_TRIGGER_NONE, ++ dev_name(&pdev->dev), pdev); ++ if (ret) { ++ dev_err(&pdev->dev, "request_irq err\n"); ++ return ret; ++ } ++ irq_set_irq_type(IRQ7, IRQ_TYPE_EDGE_BOTH); ++ + /* usb24 use 1/1 of parent clock (= usb24s = 24MHz) */ + clk_set_rate(priv->usb24, + clk_get_rate(clk_get_parent(priv->usb24))); +@@ -278,6 +297,7 @@ static struct usbhsf_private usbhsf_private = { + .info = { + .platform_callback = { + .get_id = usbhsf_get_id, ++ .get_vbus = usbhsf_get_vbus, + .hardware_init = usbhsf_hardware_init, + .hardware_exit = usbhsf_hardware_exit, + .power_ctrl = usbhsf_power_ctrl, +@@ -1018,7 +1038,17 @@ static void __init eva_init(void) + /* USB Host */ + } else { + /* USB Func */ +- gpio_request(GPIO_FN_VBUS, NULL); ++ /* ++ * A1 chip has 2 IRQ7 pin and it was controled by MSEL register. ++ * OTOH, usbhs interrupt needs its value (HI/LOW) to decide ++ * USB connection/disconnection (usbhsf_get_vbus()). ++ * This means we needs to select GPIO_FN_IRQ7_PORT209 first, ++ * and select GPIO_PORT209 here ++ */ ++ gpio_request(GPIO_FN_IRQ7_PORT209, NULL); ++ gpio_request(GPIO_PORT209, NULL); ++ gpio_direction_input(GPIO_PORT209); ++ + platform_device_register(&usbhsf_device); + } + +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0100-ARM-shmobile-armadillo800eva-A4LC-domain-includes-LC.patch b/patches.armadillo800/0100-ARM-shmobile-armadillo800eva-A4LC-domain-includes-LC.patch new file mode 100644 index 0000000000000..77f0990b4887d --- /dev/null +++ b/patches.armadillo800/0100-ARM-shmobile-armadillo800eva-A4LC-domain-includes-LC.patch @@ -0,0 +1,35 @@ +From ac8b41bd50ebd214726fffdac141ee4d37d3fb40 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 5 Jul 2012 01:27:37 -0700 +Subject: ARM: shmobile: armadillo800eva: A4LC domain includes LCDC + +It is possible to control LCDC under A4LC domain to reduce power. +This patch enable it. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 1000076a88d58acf77d8fa8bf5d2567425b8ea1b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index 5002f64..101242a 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -1177,6 +1177,9 @@ static void __init eva_init(void) + ARRAY_SIZE(eva_devices)); + + eva_clock_init(); ++ ++ rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &lcdc0_device); ++ rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &hdmi_lcdc_device); + } + + static void __init eva_earlytimer_init(void) +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0101-ARM-shmobile-armadillo800eva-A3SP-domain-includes-US.patch b/patches.armadillo800/0101-ARM-shmobile-armadillo800eva-A3SP-domain-includes-US.patch new file mode 100644 index 0000000000000..03ae976fb3584 --- /dev/null +++ b/patches.armadillo800/0101-ARM-shmobile-armadillo800eva-A3SP-domain-includes-US.patch @@ -0,0 +1,55 @@ +From 481b82720f5d1da8062da229cecc6ccfd875fb68 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Thu, 5 Jul 2012 01:28:00 -0700 +Subject: ARM: shmobile: armadillo800eva: A3SP domain includes USB + +Because USB Func is controlled by external IRQ mode, +it is possible to control USB under A3SP domain to reduce power. +This patch enables it. + +Armadillo800eva board switchs USB Host/Func by SW1.6, +So, the device to adds into domain is selected on this patch. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 0f54788d8b4f7aa8d74b0a5a0ad706bcc216b3c7) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index 101242a..cf10f92 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -953,6 +953,8 @@ clock_error: + #define GPIO_PORT8CR 0xe6050008 + static void __init eva_init(void) + { ++ struct platform_device *usb = NULL; ++ + regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers, + ARRAY_SIZE(fixed3v3_power_consumers), 3300000); + +@@ -1050,6 +1052,7 @@ static void __init eva_init(void) + gpio_direction_input(GPIO_PORT209); + + platform_device_register(&usbhsf_device); ++ usb = &usbhsf_device; + } + + /* SDHI0 */ +@@ -1180,6 +1183,8 @@ static void __init eva_init(void) + + rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &lcdc0_device); + rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &hdmi_lcdc_device); ++ if (usb) ++ rmobile_add_device_to_domain(&r8a7740_pd_a3sp, usb); + } + + static void __init eva_earlytimer_init(void) +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0102-ARM-mach-shmobile-r8a7740-generic-board-support-via-.patch b/patches.armadillo800/0102-ARM-mach-shmobile-r8a7740-generic-board-support-via-.patch new file mode 100644 index 0000000000000..d3e0e1c9ba671 --- /dev/null +++ b/patches.armadillo800/0102-ARM-mach-shmobile-r8a7740-generic-board-support-via-.patch @@ -0,0 +1,118 @@ +From db4818fde4a8b81acde03834936d131a21c4ae4f Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Fri, 6 Jul 2012 17:08:07 +0900 +Subject: ARM: mach-shmobile: r8a7740 generic board support via DT + +Add generic DT board support for the r8a7740 SoC. + +SCIF serial ports and timers are kept as regular +platform devices. Other on-chip and on-board devices +should be configured via the device tree. + +At this point there is no interrupt controller support +in place but such code will be added over time when +proper IRQ domain support has been added to INTC. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 755d57b2229bd8cfa1d553c0b6878f2096f55ec3) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/boot/dts/r8a7740.dtsi | 21 +++++++++++++++ + arch/arm/mach-shmobile/setup-r8a7740.c | 47 ++++++++++++++++++++++++++++++++++ + 2 files changed, 68 insertions(+) + create mode 100644 arch/arm/boot/dts/r8a7740.dtsi + +diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi +new file mode 100644 +index 0000000..798fa35 +--- /dev/null ++++ b/arch/arm/boot/dts/r8a7740.dtsi +@@ -0,0 +1,21 @@ ++/* ++ * Device Tree Source for the r8a7740 SoC ++ * ++ * Copyright (C) 2012 Renesas Solutions Corp. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/include/ "skeleton.dtsi" ++ ++/ { ++ compatible = "renesas,r8a7740"; ++ ++ cpus { ++ cpu@0 { ++ compatible = "arm,cortex-a9"; ++ }; ++ }; ++}; +diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c +index c006d8d..78948a9 100644 +--- a/arch/arm/mach-shmobile/setup-r8a7740.c ++++ b/arch/arm/mach-shmobile/setup-r8a7740.c +@@ -23,6 +23,7 @@ + #include <linux/init.h> + #include <linux/io.h> + #include <linux/platform_device.h> ++#include <linux/of_platform.h> + #include <linux/serial_sci.h> + #include <linux/sh_dma.h> + #include <linux/sh_timer.h> +@@ -716,3 +717,49 @@ void __init r8a7740_add_early_devices(void) + /* override timer setup with soc-specific code */ + shmobile_timer.init = r8a7740_earlytimer_init; + } ++ ++#ifdef CONFIG_USE_OF ++ ++void __init r8a7740_add_early_devices_dt(void) ++{ ++ shmobile_setup_delay(800, 1, 3); /* Cortex-A9 @ 800MHz */ ++ ++ early_platform_add_devices(r8a7740_early_devices, ++ ARRAY_SIZE(r8a7740_early_devices)); ++ ++ /* setup early console here as well */ ++ shmobile_setup_console(); ++} ++ ++static const struct of_dev_auxdata r8a7740_auxdata_lookup[] __initconst = { ++ { } ++}; ++ ++void __init r8a7740_add_standard_devices_dt(void) ++{ ++ /* clocks are setup late during boot in the case of DT */ ++ r8a7740_clock_init(0); ++ ++ platform_add_devices(r8a7740_early_devices, ++ ARRAY_SIZE(r8a7740_early_devices)); ++ ++ of_platform_populate(NULL, of_default_bus_match_table, ++ r8a7740_auxdata_lookup, NULL); ++} ++ ++static const char *r8a7740_boards_compat_dt[] __initdata = { ++ "renesas,r8a7740", ++ NULL, ++}; ++ ++DT_MACHINE_START(SH7372_DT, "Generic R8A7740 (Flattened Device Tree)") ++ .map_io = r8a7740_map_io, ++ .init_early = r8a7740_add_early_devices_dt, ++ .init_irq = r8a7740_init_irq, ++ .handle_irq = shmobile_handle_irq_intc, ++ .init_machine = r8a7740_add_standard_devices_dt, ++ .timer = &shmobile_timer, ++ .dt_compat = r8a7740_boards_compat_dt, ++MACHINE_END ++ ++#endif /* CONFIG_USE_OF */ +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0103-ARM-mach-shmobile-armadillo800eva-defconfig-Allow-us.patch b/patches.armadillo800/0103-ARM-mach-shmobile-armadillo800eva-defconfig-Allow-us.patch new file mode 100644 index 0000000000000..3b6f0565cf068 --- /dev/null +++ b/patches.armadillo800/0103-ARM-mach-shmobile-armadillo800eva-defconfig-Allow-us.patch @@ -0,0 +1,43 @@ +From 8a8dced180f83f64ff5d6098281f27053df630ad Mon Sep 17 00:00:00 2001 +From: Simon Horman <horms@verge.net.au> +Date: Fri, 6 Jul 2012 20:08:15 +0900 +Subject: ARM: mach-shmobile: armadillo800eva: defconfig Allow use of armhf + userspace + +This allows use a Debian armhf usespace +as well as the existing ability to use a Debian armel userspace. + +Signed-off-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 70523b4e57cb6eeb1da7c8ebf19df855221825ad) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/configs/armadillo800eva_defconfig | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig +index 16bbb3f..7d87184 100644 +--- a/arch/arm/configs/armadillo800eva_defconfig ++++ b/arch/arm/configs/armadillo800eva_defconfig +@@ -18,7 +18,7 @@ CONFIG_ARCH_SHMOBILE=y + CONFIG_ARCH_R8A7740=y + CONFIG_MACH_ARMADILLO800EVA=y + # CONFIG_SH_TIMER_TMU is not set +-# CONFIG_ARM_THUMB is not set ++CONFIG_ARM_THUMB=y + CONFIG_CPU_BPREDICT_DISABLE=y + # CONFIG_CACHE_L2X0 is not set + CONFIG_ARM_ERRATA_430973=y +@@ -36,6 +36,7 @@ CONFIG_ZBOOT_ROM_BSS=0x0 + CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096" + CONFIG_CMDLINE_FORCE=y + CONFIG_KEXEC=y ++CONFIG_VFP=y + # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set + # CONFIG_SUSPEND is not set + CONFIG_NET=y +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0104-ARM-mach-shmobile-armadillo800eva-Fix-GPIO-buttons-d.patch b/patches.armadillo800/0104-ARM-mach-shmobile-armadillo800eva-Fix-GPIO-buttons-d.patch new file mode 100644 index 0000000000000..8184e72a98c73 --- /dev/null +++ b/patches.armadillo800/0104-ARM-mach-shmobile-armadillo800eva-Fix-GPIO-buttons-d.patch @@ -0,0 +1,40 @@ +From fdfc19ff5c71ac77f6cc8781402dd92452e4e053 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Tue, 24 Jul 2012 15:26:08 +0200 +Subject: ARM: mach-shmobile: armadillo800eva: Fix GPIO buttons descriptions + +The GPIO buttons are named SW3, SW4, SW5 and SW6 on the board +silkscreen. Update the buttons descriptions accordingly. + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +(cherry picked from commit 2d85b9494d10501f20ebf043f8d599e45736d78f) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index cf10f92..a002504 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -523,10 +523,10 @@ static struct platform_device hdmi_lcdc_device = { + #define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 } + + static struct gpio_keys_button gpio_buttons[] = { +- GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW1"), +- GPIO_KEY(KEY_BACK, GPIO_PORT100, "SW2"), +- GPIO_KEY(KEY_MENU, GPIO_PORT97, "SW3"), +- GPIO_KEY(KEY_HOME, GPIO_PORT98, "SW4"), ++ GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW3"), ++ GPIO_KEY(KEY_BACK, GPIO_PORT100, "SW4"), ++ GPIO_KEY(KEY_MENU, GPIO_PORT97, "SW5"), ++ GPIO_KEY(KEY_HOME, GPIO_PORT98, "SW6"), + }; + + static struct gpio_keys_platform_data gpio_key_info = { +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0105-ARM-mach-shmobile-armadillo800eva-Enable-power-butto.patch b/patches.armadillo800/0105-ARM-mach-shmobile-armadillo800eva-Enable-power-butto.patch new file mode 100644 index 0000000000000..3e9c99ce7b035 --- /dev/null +++ b/patches.armadillo800/0105-ARM-mach-shmobile-armadillo800eva-Enable-power-butto.patch @@ -0,0 +1,37 @@ +From 10ee1d677c8fa257269f2c5e062525035b866a61 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Tue, 24 Jul 2012 15:26:09 +0200 +Subject: ARM: mach-shmobile: armadillo800eva: Enable power button as wakeup + source + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +(cherry picked from commit 5c1d2d16772e2d7d4e2e8da99a92d6f50b9102f0) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index a002504..65cb793 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -520,10 +520,11 @@ static struct platform_device hdmi_lcdc_device = { + }; + + /* GPIO KEY */ +-#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 } ++#define GPIO_KEY(c, g, d, ...) \ ++ { .code = c, .gpio = g, .desc = d, .active_low = 1, __VA_ARGS__ } + + static struct gpio_keys_button gpio_buttons[] = { +- GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW3"), ++ GPIO_KEY(KEY_POWER, GPIO_PORT99, "SW3", .wakeup = 1), + GPIO_KEY(KEY_BACK, GPIO_PORT100, "SW4"), + GPIO_KEY(KEY_MENU, GPIO_PORT97, "SW5"), + GPIO_KEY(KEY_HOME, GPIO_PORT98, "SW6"), +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0106-ARM-shmobile-armadillo800eva-fixup-sound-card-detect.patch b/patches.armadillo800/0106-ARM-shmobile-armadillo800eva-fixup-sound-card-detect.patch new file mode 100644 index 0000000000000..58ffe1c24a30e --- /dev/null +++ b/patches.armadillo800/0106-ARM-shmobile-armadillo800eva-fixup-sound-card-detect.patch @@ -0,0 +1,43 @@ +From 974462b8ff3fbb6468b94d52690a5707b2ccb955 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Wed, 8 Aug 2012 23:03:07 -0700 +Subject: ARM: shmobile: armadillo800eva: fixup: sound card detection order + +Since armadillo800eva has 2 sound cards, +and had reversed deferred probe order issue, +it was purposely registered in reverse order. + +But it was solved by +1d29cfa57471a5e4b8a7c2a7433eeba170d3ad92 +(driver core: fixup reversed deferred probe order) + +armadillo800eva board is expecting that +FSI-WM8978 is the 1st, and FSI-HDMI is the 2nd sound card. +This patch fixes it up + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +(cherry picked from commit ee3c843d0fc21c68ced93b982b5731178a24df68) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-armadillo800eva.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c +index 65cb793..453a6e5 100644 +--- a/arch/arm/mach-shmobile/board-armadillo800eva.c ++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c +@@ -902,8 +902,8 @@ static struct platform_device *eva_devices[] __initdata = { + &camera_device, + &ceu0_device, + &fsi_device, +- &fsi_hdmi_device, + &fsi_wm8978_device, ++ &fsi_hdmi_device, + }; + + static void __init eva_clock_init(void) +-- +1.8.0.197.g5a90748 + diff --git a/patches.armadillo800/0107-ARM-shmobile-armadillo800eva-enable-rw-rootfs-mount.patch b/patches.armadillo800/0107-ARM-shmobile-armadillo800eva-enable-rw-rootfs-mount.patch new file mode 100644 index 0000000000000..b53acd69ee321 --- /dev/null +++ b/patches.armadillo800/0107-ARM-shmobile-armadillo800eva-enable-rw-rootfs-mount.patch @@ -0,0 +1,39 @@ +From 1b5f7629ee098b784f2b8e2ee49d03d90e01f811 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Sun, 2 Sep 2012 23:06:52 -0700 +Subject: ARM: shmobile: armadillo800eva: enable rw rootfs mount + +armadillo800eva default boot loader is "hermit", +and it's tag->u.core.flags has flag when kernel boots. +Because of this, ${LINUX}/arch/arm/kernel/setup.c :: parse_tag_core() +didn't remove MS_RDONLY flag from root_mountflags. +Thus, the rootfs is mounted as "readonly". +This patch adds "rw" kernel parameter, +and enable read/write mounts for rootfs + +Cc: Masahiro Nakai <nakai@atmark-techno.com> +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +(cherry picked from commit 28e515878f8896b33c325ff9767cb0237210fb4c) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/configs/armadillo800eva_defconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig +index 7d87184..90610c7 100644 +--- a/arch/arm/configs/armadillo800eva_defconfig ++++ b/arch/arm/configs/armadillo800eva_defconfig +@@ -33,7 +33,7 @@ CONFIG_AEABI=y + CONFIG_FORCE_MAX_ZONEORDER=13 + CONFIG_ZBOOT_ROM_TEXT=0x0 + CONFIG_ZBOOT_ROM_BSS=0x0 +-CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096" ++CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096 rw" + CONFIG_CMDLINE_FORCE=y + CONFIG_KEXEC=y + CONFIG_VFP=y +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0001-sh-clkfwk-Support-variable-size-accesses-for-MSTP-cl.patch b/patches.marzen/0001-sh-clkfwk-Support-variable-size-accesses-for-MSTP-cl.patch new file mode 100644 index 0000000000000..f043fca8c27fa --- /dev/null +++ b/patches.marzen/0001-sh-clkfwk-Support-variable-size-accesses-for-MSTP-cl.patch @@ -0,0 +1,154 @@ +From aa9210ec33e000900e3ad25d7b98c7897027b1f2 Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Wed, 11 Apr 2012 12:05:50 +0900 +Subject: sh: clkfwk: Support variable size accesses for MSTP clocks. + +The bulk of the MSTP users require 32-bit access, but this isn't the case +for some of the SH-2A parts, so add in some basic infrastructure to let +the CPU define its required access size in preparation. + +Requested-by: Phil Edworthy <phil.edworthy@renesas.com> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 4d6ddb08acc48368c5b7ac431f9d00db7227d2ed) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/sh/clk/cpg.c | 38 +++++++++++++++++++++++++++----------- + include/linux/sh_clk.h | 34 +++++++++++++++++++++++++++++++--- + 2 files changed, 58 insertions(+), 14 deletions(-) + +diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c +index 91b6d52..6cbda48 100644 +--- a/drivers/sh/clk/cpg.c ++++ b/drivers/sh/clk/cpg.c +@@ -2,6 +2,7 @@ + * Helper routines for SuperH Clock Pulse Generator blocks (CPG). + * + * Copyright (C) 2010 Magnus Damm ++ * Copyright (C) 2010 - 2012 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 +@@ -13,26 +14,41 @@ + #include <linux/io.h> + #include <linux/sh_clk.h> + +-static int sh_clk_mstp32_enable(struct clk *clk) ++static int sh_clk_mstp_enable(struct clk *clk) + { +- iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit), +- clk->mapped_reg); ++ if (clk->flags & CLK_ENABLE_REG_8BIT) ++ iowrite8(ioread8(clk->mapped_reg) & ~(1 << clk->enable_bit), ++ clk->mapped_reg); ++ else if (clk->flags & CLK_ENABLE_REG_16BIT) ++ iowrite16(ioread16(clk->mapped_reg) & ~(1 << clk->enable_bit), ++ clk->mapped_reg); ++ else ++ iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit), ++ clk->mapped_reg); ++ + return 0; + } + +-static void sh_clk_mstp32_disable(struct clk *clk) ++static void sh_clk_mstp_disable(struct clk *clk) + { +- iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit), +- clk->mapped_reg); ++ if (clk->flags & CLK_ENABLE_REG_8BIT) ++ iowrite8(ioread8(clk->mapped_reg) | (1 << clk->enable_bit), ++ clk->mapped_reg); ++ else if (clk->flags & CLK_ENABLE_REG_16BIT) ++ iowrite16(ioread16(clk->mapped_reg) | (1 << clk->enable_bit), ++ clk->mapped_reg); ++ else ++ iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit), ++ clk->mapped_reg); + } + +-static struct sh_clk_ops sh_clk_mstp32_clk_ops = { +- .enable = sh_clk_mstp32_enable, +- .disable = sh_clk_mstp32_disable, ++static struct sh_clk_ops sh_clk_mstp_clk_ops = { ++ .enable = sh_clk_mstp_enable, ++ .disable = sh_clk_mstp_disable, + .recalc = followparent_recalc, + }; + +-int __init sh_clk_mstp32_register(struct clk *clks, int nr) ++int __init sh_clk_mstp_register(struct clk *clks, int nr) + { + struct clk *clkp; + int ret = 0; +@@ -40,7 +56,7 @@ int __init sh_clk_mstp32_register(struct clk *clks, int nr) + + for (k = 0; !ret && (k < nr); k++) { + clkp = clks + k; +- clkp->ops = &sh_clk_mstp32_clk_ops; ++ clkp->ops = &sh_clk_mstp_clk_ops; + ret |= clk_register(clkp); + } + +diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h +index 0a9d8f2..c513b73 100644 +--- a/include/linux/sh_clk.h ++++ b/include/linux/sh_clk.h +@@ -59,7 +59,15 @@ struct clk { + unsigned int nr_freqs; + }; + +-#define CLK_ENABLE_ON_INIT (1 << 0) ++#define CLK_ENABLE_ON_INIT BIT(0) ++ ++#define CLK_ENABLE_REG_32BIT BIT(1) /* default access size */ ++#define CLK_ENABLE_REG_16BIT BIT(2) ++#define CLK_ENABLE_REG_8BIT BIT(3) ++ ++#define CLK_ENABLE_REG_MASK (CLK_ENABLE_REG_32BIT | \ ++ CLK_ENABLE_REG_16BIT | \ ++ CLK_ENABLE_REG_8BIT) + + /* drivers/sh/clk.c */ + unsigned long followparent_recalc(struct clk *); +@@ -102,7 +110,7 @@ long clk_round_parent(struct clk *clk, unsigned long target, + unsigned long *best_freq, unsigned long *parent_freq, + unsigned int div_min, unsigned int div_max); + +-#define SH_CLK_MSTP32(_parent, _enable_reg, _enable_bit, _flags) \ ++#define SH_CLK_MSTP(_parent, _enable_reg, _enable_bit, _flags) \ + { \ + .parent = _parent, \ + .enable_reg = (void __iomem *)_enable_reg, \ +@@ -110,7 +118,27 @@ long clk_round_parent(struct clk *clk, unsigned long target, + .flags = _flags, \ + } + +-int sh_clk_mstp32_register(struct clk *clks, int nr); ++#define SH_CLK_MSTP32(_p, _r, _b, _f) \ ++ SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_32BIT) ++ ++#define SH_CLK_MSTP16(_p, _r, _b, _f) \ ++ SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_16BIT) ++ ++#define SH_CLK_MSTP8(_p, _r, _b, _f) \ ++ SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_8BIT) ++ ++int sh_clk_mstp_register(struct clk *clks, int nr); ++ ++/* ++ * MSTP registration never really cared about access size, despite the ++ * original enable/disable pairs assuming a 32-bit access. Clocks are ++ * responsible for defining their access sizes either directly or via the ++ * clock definition wrappers. ++ */ ++static inline int __deprecated sh_clk_mstp32_register(struct clk *clks, int nr) ++{ ++ return sh_clk_mstp_register(clks, nr); ++} + + #define SH_CLK_DIV4(_parent, _reg, _shift, _div_bitmap, _flags) \ + { \ +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0002-sh-clkfwk-Support-variable-size-accesses-for-div4-di.patch b/patches.marzen/0002-sh-clkfwk-Support-variable-size-accesses-for-div4-di.patch new file mode 100644 index 0000000000000..5d1fac6d005fe --- /dev/null +++ b/patches.marzen/0002-sh-clkfwk-Support-variable-size-accesses-for-div4-di.patch @@ -0,0 +1,202 @@ +From 5a1639b2287a62e965e2355c68ef52da597b9a3c Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Thu, 12 Apr 2012 19:50:40 +0900 +Subject: sh: clkfwk: Support variable size accesses for div4/div6 clocks. + +This follows the MSTP clock change and implements variable access size +support for the rest of the CPG clocks, too. Upcoming SH-2A support has +need of this for 16-bit div4 clocks, while others will follow. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 104fa61a7dd83197160d5cafedc0e94ad9cd7fcc) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/sh/clk/cpg.c | 71 +++++++++++++++++++++++++++------------------------- + 1 file changed, 37 insertions(+), 34 deletions(-) + +diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c +index 6cbda48..f0d015d 100644 +--- a/drivers/sh/clk/cpg.c ++++ b/drivers/sh/clk/cpg.c +@@ -14,32 +14,35 @@ + #include <linux/io.h> + #include <linux/sh_clk.h> + +-static int sh_clk_mstp_enable(struct clk *clk) ++static unsigned int sh_clk_read(struct clk *clk) + { + if (clk->flags & CLK_ENABLE_REG_8BIT) +- iowrite8(ioread8(clk->mapped_reg) & ~(1 << clk->enable_bit), +- clk->mapped_reg); ++ return ioread8(clk->mapped_reg); + else if (clk->flags & CLK_ENABLE_REG_16BIT) +- iowrite16(ioread16(clk->mapped_reg) & ~(1 << clk->enable_bit), +- clk->mapped_reg); +- else +- iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit), +- clk->mapped_reg); ++ return ioread16(clk->mapped_reg); + +- return 0; ++ return ioread32(clk->mapped_reg); + } + +-static void sh_clk_mstp_disable(struct clk *clk) ++static void sh_clk_write(int value, struct clk *clk) + { + if (clk->flags & CLK_ENABLE_REG_8BIT) +- iowrite8(ioread8(clk->mapped_reg) | (1 << clk->enable_bit), +- clk->mapped_reg); ++ iowrite8(value, clk->mapped_reg); + else if (clk->flags & CLK_ENABLE_REG_16BIT) +- iowrite16(ioread16(clk->mapped_reg) | (1 << clk->enable_bit), +- clk->mapped_reg); ++ iowrite16(value, clk->mapped_reg); + else +- iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit), +- clk->mapped_reg); ++ iowrite32(value, clk->mapped_reg); ++} ++ ++static int sh_clk_mstp_enable(struct clk *clk) ++{ ++ sh_clk_write(sh_clk_read(clk) & ~(1 << clk->enable_bit), clk); ++ return 0; ++} ++ ++static void sh_clk_mstp_disable(struct clk *clk) ++{ ++ sh_clk_write(sh_clk_read(clk) | (1 << clk->enable_bit), clk); + } + + static struct sh_clk_ops sh_clk_mstp_clk_ops = { +@@ -88,7 +91,7 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk) + clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, + table, NULL); + +- idx = ioread32(clk->mapped_reg) & 0x003f; ++ idx = sh_clk_read(clk) & 0x003f; + + return clk->freq_table[idx].frequency; + } +@@ -114,10 +117,10 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent) + if (ret < 0) + return ret; + +- value = ioread32(clk->mapped_reg) & ++ value = sh_clk_read(clk) & + ~(((1 << clk->src_width) - 1) << clk->src_shift); + +- iowrite32(value | (i << clk->src_shift), clk->mapped_reg); ++ sh_clk_write(value | (i << clk->src_shift), clk); + + /* Rebuild the frequency table */ + clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, +@@ -135,10 +138,10 @@ static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate) + if (idx < 0) + return idx; + +- value = ioread32(clk->mapped_reg); ++ value = sh_clk_read(clk); + value &= ~0x3f; + value |= idx; +- iowrite32(value, clk->mapped_reg); ++ sh_clk_write(value, clk); + return 0; + } + +@@ -149,9 +152,9 @@ static int sh_clk_div6_enable(struct clk *clk) + + ret = sh_clk_div6_set_rate(clk, clk->rate); + if (ret == 0) { +- value = ioread32(clk->mapped_reg); ++ value = sh_clk_read(clk); + value &= ~0x100; /* clear stop bit to enable clock */ +- iowrite32(value, clk->mapped_reg); ++ sh_clk_write(value, clk); + } + return ret; + } +@@ -160,10 +163,10 @@ static void sh_clk_div6_disable(struct clk *clk) + { + unsigned long value; + +- value = ioread32(clk->mapped_reg); ++ value = sh_clk_read(clk); + value |= 0x100; /* stop clock */ + value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */ +- iowrite32(value, clk->mapped_reg); ++ sh_clk_write(value, clk); + } + + static struct sh_clk_ops sh_clk_div6_clk_ops = { +@@ -198,7 +201,7 @@ static int __init sh_clk_init_parent(struct clk *clk) + return -EINVAL; + } + +- val = (ioread32(clk->mapped_reg) >> clk->src_shift); ++ val = (sh_clk_read(clk) >> clk->src_shift); + val &= (1 << clk->src_width) - 1; + + if (val >= clk->parent_num) { +@@ -268,7 +271,7 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk) + clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, + table, &clk->arch_flags); + +- idx = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0x000f; ++ idx = (sh_clk_read(clk) >> clk->enable_bit) & 0x000f; + + return clk->freq_table[idx].frequency; + } +@@ -286,15 +289,15 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) + */ + + if (parent->flags & CLK_ENABLE_ON_INIT) +- value = ioread32(clk->mapped_reg) & ~(1 << 7); ++ value = sh_clk_read(clk) & ~(1 << 7); + else +- value = ioread32(clk->mapped_reg) | (1 << 7); ++ value = sh_clk_read(clk) | (1 << 7); + + ret = clk_reparent(clk, parent); + if (ret < 0) + return ret; + +- iowrite32(value, clk->mapped_reg); ++ sh_clk_write(value, clk); + + /* Rebiuld the frequency table */ + clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, +@@ -311,10 +314,10 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate) + if (idx < 0) + return idx; + +- value = ioread32(clk->mapped_reg); ++ value = sh_clk_read(clk); + value &= ~(0xf << clk->enable_bit); + value |= (idx << clk->enable_bit); +- iowrite32(value, clk->mapped_reg); ++ sh_clk_write(value, clk); + + if (d4t->kick) + d4t->kick(clk); +@@ -324,13 +327,13 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate) + + static int sh_clk_div4_enable(struct clk *clk) + { +- iowrite32(ioread32(clk->mapped_reg) & ~(1 << 8), clk->mapped_reg); ++ sh_clk_write(sh_clk_read(clk) & ~(1 << 8), clk); + return 0; + } + + static void sh_clk_div4_disable(struct clk *clk) + { +- iowrite32(ioread32(clk->mapped_reg) | (1 << 8), clk->mapped_reg); ++ sh_clk_write(sh_clk_read(clk) | (1 << 8), clk); + } + + static struct sh_clk_ops sh_clk_div4_clk_ops = { +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0003-sh-clkfwk-Move-to-common-clk_div_table-accessors-for.patch b/patches.marzen/0003-sh-clkfwk-Move-to-common-clk_div_table-accessors-for.patch new file mode 100644 index 0000000000000..c7a6b9b0b9344 --- /dev/null +++ b/patches.marzen/0003-sh-clkfwk-Move-to-common-clk_div_table-accessors-for.patch @@ -0,0 +1,169 @@ +From cd33eef0c195fa40494a8115aa1202bdaed860a0 Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Fri, 25 May 2012 14:59:26 +0900 +Subject: sh: clkfwk: Move to common clk_div_table accessors for div4/div6. + +This plugs in a generic clk_div_table, based on the div4 version. div6 is +then adopted to use it for encapsulating its div table, which permits us +to start div6/4 unification, as well as preparation for other div types. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit a60977a51333a8108f0574aa26094d66b7fedf34) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/sh/clk/cpg.c | 46 +++++++++++++++++++++++++++++++++++----------- + include/linux/sh_clk.h | 5 +++-- + 2 files changed, 38 insertions(+), 13 deletions(-) + +diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c +index f0d015d..9dea329 100644 +--- a/drivers/sh/clk/cpg.c ++++ b/drivers/sh/clk/cpg.c +@@ -71,6 +71,22 @@ static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate) + return clk_rate_table_round(clk, clk->freq_table, rate); + } + ++/* ++ * Div/mult table lookup helpers ++ */ ++static inline struct clk_div_table *clk_to_div_table(struct clk *clk) ++{ ++ return clk->priv; ++} ++ ++static inline struct clk_div_mult_table *clk_to_div_mult_table(struct clk *clk) ++{ ++ return clk_to_div_table(clk)->div_mult_table; ++} ++ ++/* ++ * div6 support ++ */ + static int sh_clk_div6_divisors[64] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, +@@ -78,14 +94,18 @@ static int sh_clk_div6_divisors[64] = { + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 + }; + +-static struct clk_div_mult_table sh_clk_div6_table = { ++static struct clk_div_mult_table div6_div_mult_table = { + .divisors = sh_clk_div6_divisors, + .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors), + }; + ++static struct clk_div_table sh_clk_div6_table = { ++ .div_mult_table = &div6_div_mult_table, ++}; ++ + static unsigned long sh_clk_div6_recalc(struct clk *clk) + { +- struct clk_div_mult_table *table = &sh_clk_div6_table; ++ struct clk_div_mult_table *table = clk_to_div_mult_table(clk); + unsigned int idx; + + clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, +@@ -98,7 +118,7 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk) + + static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent) + { +- struct clk_div_mult_table *table = &sh_clk_div6_table; ++ struct clk_div_mult_table *table = clk_to_div_mult_table(clk); + u32 value; + int ret, i; + +@@ -223,7 +243,8 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr, + { + struct clk *clkp; + void *freq_table; +- int nr_divs = sh_clk_div6_table.nr_divisors; ++ struct clk_div_table *table = &sh_clk_div6_table; ++ int nr_divs = table->div_mult_table->nr_divisors; + int freq_table_size = sizeof(struct cpufreq_frequency_table); + int ret = 0; + int k; +@@ -239,6 +260,7 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr, + clkp = clks + k; + + clkp->ops = ops; ++ clkp->priv = table; + clkp->freq_table = freq_table + (k * freq_table_size); + clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; + ret = clk_register(clkp); +@@ -262,10 +284,12 @@ int __init sh_clk_div6_reparent_register(struct clk *clks, int nr) + &sh_clk_div6_reparent_clk_ops); + } + ++/* ++ * div4 support ++ */ + static unsigned long sh_clk_div4_recalc(struct clk *clk) + { +- struct clk_div4_table *d4t = clk->priv; +- struct clk_div_mult_table *table = d4t->div_mult_table; ++ struct clk_div_mult_table *table = clk_to_div_mult_table(clk); + unsigned int idx; + + clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, +@@ -278,8 +302,7 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk) + + static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) + { +- struct clk_div4_table *d4t = clk->priv; +- struct clk_div_mult_table *table = d4t->div_mult_table; ++ struct clk_div_mult_table *table = clk_to_div_mult_table(clk); + u32 value; + int ret; + +@@ -308,7 +331,7 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) + + static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate) + { +- struct clk_div4_table *d4t = clk->priv; ++ struct clk_div_table *dt = clk_to_div_table(clk); + unsigned long value; + int idx = clk_rate_table_find(clk, clk->freq_table, rate); + if (idx < 0) +@@ -319,8 +342,9 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate) + value |= (idx << clk->enable_bit); + sh_clk_write(value, clk); + +- if (d4t->kick) +- d4t->kick(clk); ++ /* XXX: Should use a post-change notifier */ ++ if (dt->kick) ++ dt->kick(clk); + + return 0; + } +diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h +index c513b73..706b803 100644 +--- a/include/linux/sh_clk.h ++++ b/include/linux/sh_clk.h +@@ -18,7 +18,6 @@ struct clk_mapping { + struct kref ref; + }; + +- + struct sh_clk_ops { + #ifdef CONFIG_SH_CLK_CPG_LEGACY + void (*init)(struct clk *clk); +@@ -149,11 +148,13 @@ static inline int __deprecated sh_clk_mstp32_register(struct clk *clks, int nr) + .flags = _flags, \ + } + +-struct clk_div4_table { ++struct clk_div_table { + struct clk_div_mult_table *div_mult_table; + void (*kick)(struct clk *clk); + }; + ++#define clk_div4_table clk_div_table ++ + int sh_clk_div4_register(struct clk *clks, int nr, + struct clk_div4_table *table); + int sh_clk_div4_enable_register(struct clk *clks, int nr, +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0004-sh-clkfwk-Introduce-a-div_mask-for-variable-div-type.patch b/patches.marzen/0004-sh-clkfwk-Introduce-a-div_mask-for-variable-div-type.patch new file mode 100644 index 0000000000000..f8629fb9d0541 --- /dev/null +++ b/patches.marzen/0004-sh-clkfwk-Introduce-a-div_mask-for-variable-div-type.patch @@ -0,0 +1,117 @@ +From a0643bdb2770016b5930f9cbe5dee7a36e6951fc Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Fri, 25 May 2012 15:21:43 +0900 +Subject: sh: clkfwk: Introduce a div_mask for variable div types. + +This plugs in a div_mask for the clock and sets it up for the existing +div6/4 cases. This will make it possible to support other div types, as +well as share more div6/4 infrastructure. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 1111cc1e8080b5ff46f5b945acb2f99d6176b2d1) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/sh/clk/cpg.c | 10 +++++----- + include/linux/sh_clk.h | 8 ++++++++ + 2 files changed, 13 insertions(+), 5 deletions(-) + +diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c +index 9dea329..9386bd2 100644 +--- a/drivers/sh/clk/cpg.c ++++ b/drivers/sh/clk/cpg.c +@@ -111,7 +111,7 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk) + clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, + table, NULL); + +- idx = sh_clk_read(clk) & 0x003f; ++ idx = sh_clk_read(clk) & clk->div_mask; + + return clk->freq_table[idx].frequency; + } +@@ -159,7 +159,7 @@ static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate) + return idx; + + value = sh_clk_read(clk); +- value &= ~0x3f; ++ value &= ~clk->div_mask; + value |= idx; + sh_clk_write(value, clk); + return 0; +@@ -185,7 +185,7 @@ static void sh_clk_div6_disable(struct clk *clk) + + value = sh_clk_read(clk); + value |= 0x100; /* stop clock */ +- value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */ ++ value |= clk->div_mask; /* VDIV bits must be non-zero, overwrite divider */ + sh_clk_write(value, clk); + } + +@@ -295,7 +295,7 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk) + clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, + table, &clk->arch_flags); + +- idx = (sh_clk_read(clk) >> clk->enable_bit) & 0x000f; ++ idx = (sh_clk_read(clk) >> clk->enable_bit) & clk->div_mask; + + return clk->freq_table[idx].frequency; + } +@@ -338,7 +338,7 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate) + return idx; + + value = sh_clk_read(clk); +- value &= ~(0xf << clk->enable_bit); ++ value &= ~(clk->div_mask << clk->enable_bit); + value |= (idx << clk->enable_bit); + sh_clk_write(value, clk); + +diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h +index 706b803..d540b81 100644 +--- a/include/linux/sh_clk.h ++++ b/include/linux/sh_clk.h +@@ -30,6 +30,10 @@ struct sh_clk_ops { + long (*round_rate)(struct clk *clk, unsigned long rate); + }; + ++#define SH_CLK_DIV_MSK(div) ((1 << (div)) - 1) ++#define SH_CLK_DIV4_MSK SH_CLK_DIV_MSK(4) ++#define SH_CLK_DIV6_MSK SH_CLK_DIV_MSK(6) ++ + struct clk { + struct list_head node; + struct clk *parent; +@@ -51,6 +55,7 @@ struct clk { + unsigned int enable_bit; + void __iomem *mapped_reg; + ++ unsigned int div_mask; + unsigned long arch_flags; + void *priv; + struct clk_mapping *mapping; +@@ -145,6 +150,7 @@ static inline int __deprecated sh_clk_mstp32_register(struct clk *clks, int nr) + .enable_reg = (void __iomem *)_reg, \ + .enable_bit = _shift, \ + .arch_flags = _div_bitmap, \ ++ .div_mask = SH_CLK_DIV4_MSK, \ + .flags = _flags, \ + } + +@@ -167,6 +173,7 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr, + { \ + .enable_reg = (void __iomem *)_reg, \ + .flags = _flags, \ ++ .div_mask = SH_CLK_DIV6_MSK, \ + .parent_table = _parents, \ + .parent_num = _num_parents, \ + .src_shift = _src_shift, \ +@@ -177,6 +184,7 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr, + { \ + .parent = _parent, \ + .enable_reg = (void __iomem *)_reg, \ ++ .div_mask = SH_CLK_DIV6_MSK, \ + .flags = _flags, \ + } + +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0005-sh-clkfwk-Use-shared-sh_clk_div_recalc.patch b/patches.marzen/0005-sh-clkfwk-Use-shared-sh_clk_div_recalc.patch new file mode 100644 index 0000000000000..beb1b9ba8e5ca --- /dev/null +++ b/patches.marzen/0005-sh-clkfwk-Use-shared-sh_clk_div_recalc.patch @@ -0,0 +1,167 @@ +From 4a3185214cc3715feff6d802b0df478e7e61901e Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Fri, 25 May 2012 15:26:01 +0900 +Subject: sh: clkfwk: Use shared sh_clk_div_recalc(). + +This generalizes the div4 recalc routine for use by div6 and others, then +makes it the default. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 75f5f8a56e0fdf6d32b3ae9c44c10bc0acd3857c) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/sh/clk/cpg.c | 62 +++++++++++++++++++++----------------------------- + include/linux/sh_clk.h | 2 ++ + 2 files changed, 28 insertions(+), 36 deletions(-) + +diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c +index 9386bd2..84aeeb8 100644 +--- a/drivers/sh/clk/cpg.c ++++ b/drivers/sh/clk/cpg.c +@@ -66,11 +66,6 @@ int __init sh_clk_mstp_register(struct clk *clks, int nr) + return ret; + } + +-static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate) +-{ +- return clk_rate_table_round(clk, clk->freq_table, rate); +-} +- + /* + * Div/mult table lookup helpers + */ +@@ -85,6 +80,27 @@ static inline struct clk_div_mult_table *clk_to_div_mult_table(struct clk *clk) + } + + /* ++ * Common div ops ++ */ ++static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate) ++{ ++ return clk_rate_table_round(clk, clk->freq_table, rate); ++} ++ ++static unsigned long sh_clk_div_recalc(struct clk *clk) ++{ ++ struct clk_div_mult_table *table = clk_to_div_mult_table(clk); ++ unsigned int idx; ++ ++ clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, ++ table, clk->arch_flags ? &clk->arch_flags : NULL); ++ ++ idx = (sh_clk_read(clk) >> clk->enable_bit) & clk->div_mask; ++ ++ return clk->freq_table[idx].frequency; ++} ++ ++/* + * div6 support + */ + static int sh_clk_div6_divisors[64] = { +@@ -103,19 +119,6 @@ static struct clk_div_table sh_clk_div6_table = { + .div_mult_table = &div6_div_mult_table, + }; + +-static unsigned long sh_clk_div6_recalc(struct clk *clk) +-{ +- struct clk_div_mult_table *table = clk_to_div_mult_table(clk); +- unsigned int idx; +- +- clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, +- table, NULL); +- +- idx = sh_clk_read(clk) & clk->div_mask; +- +- return clk->freq_table[idx].frequency; +-} +- + static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent) + { + struct clk_div_mult_table *table = clk_to_div_mult_table(clk); +@@ -190,7 +193,7 @@ static void sh_clk_div6_disable(struct clk *clk) + } + + static struct sh_clk_ops sh_clk_div6_clk_ops = { +- .recalc = sh_clk_div6_recalc, ++ .recalc = sh_clk_div_recalc, + .round_rate = sh_clk_div_round_rate, + .set_rate = sh_clk_div6_set_rate, + .enable = sh_clk_div6_enable, +@@ -198,7 +201,7 @@ static struct sh_clk_ops sh_clk_div6_clk_ops = { + }; + + static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = { +- .recalc = sh_clk_div6_recalc, ++ .recalc = sh_clk_div_recalc, + .round_rate = sh_clk_div_round_rate, + .set_rate = sh_clk_div6_set_rate, + .enable = sh_clk_div6_enable, +@@ -287,19 +290,6 @@ int __init sh_clk_div6_reparent_register(struct clk *clks, int nr) + /* + * div4 support + */ +-static unsigned long sh_clk_div4_recalc(struct clk *clk) +-{ +- struct clk_div_mult_table *table = clk_to_div_mult_table(clk); +- unsigned int idx; +- +- clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, +- table, &clk->arch_flags); +- +- idx = (sh_clk_read(clk) >> clk->enable_bit) & clk->div_mask; +- +- return clk->freq_table[idx].frequency; +-} +- + static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) + { + struct clk_div_mult_table *table = clk_to_div_mult_table(clk); +@@ -361,13 +351,13 @@ static void sh_clk_div4_disable(struct clk *clk) + } + + static struct sh_clk_ops sh_clk_div4_clk_ops = { +- .recalc = sh_clk_div4_recalc, ++ .recalc = sh_clk_div_recalc, + .set_rate = sh_clk_div4_set_rate, + .round_rate = sh_clk_div_round_rate, + }; + + static struct sh_clk_ops sh_clk_div4_enable_clk_ops = { +- .recalc = sh_clk_div4_recalc, ++ .recalc = sh_clk_div_recalc, + .set_rate = sh_clk_div4_set_rate, + .round_rate = sh_clk_div_round_rate, + .enable = sh_clk_div4_enable, +@@ -375,7 +365,7 @@ static struct sh_clk_ops sh_clk_div4_enable_clk_ops = { + }; + + static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = { +- .recalc = sh_clk_div4_recalc, ++ .recalc = sh_clk_div_recalc, + .set_rate = sh_clk_div4_set_rate, + .round_rate = sh_clk_div_round_rate, + .enable = sh_clk_div4_enable, +diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h +index d540b81..35a04f1 100644 +--- a/include/linux/sh_clk.h ++++ b/include/linux/sh_clk.h +@@ -172,6 +172,7 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr, + _num_parents, _src_shift, _src_width) \ + { \ + .enable_reg = (void __iomem *)_reg, \ ++ .enable_bit = 0, /* unused */ \ + .flags = _flags, \ + .div_mask = SH_CLK_DIV6_MSK, \ + .parent_table = _parents, \ +@@ -184,6 +185,7 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr, + { \ + .parent = _parent, \ + .enable_reg = (void __iomem *)_reg, \ ++ .enable_bit = 0, /* unused */ \ + .div_mask = SH_CLK_DIV6_MSK, \ + .flags = _flags, \ + } +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0006-sh-clkfwk-Use-shared-sh_clk_div_set_rate.patch b/patches.marzen/0006-sh-clkfwk-Use-shared-sh_clk_div_set_rate.patch new file mode 100644 index 0000000000000..49ad18a75d81f --- /dev/null +++ b/patches.marzen/0006-sh-clkfwk-Use-shared-sh_clk_div_set_rate.patch @@ -0,0 +1,151 @@ +From df94ddc15bc18c4fd96707fce2b3983e6f013f83 Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Fri, 25 May 2012 15:52:10 +0900 +Subject: sh: clkfwk: Use shared sh_clk_div_set_rate() + +Follows the sh_clk_div_recalc() change. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 0fa22168e00106797f28b2655aaefd0d16a6e67b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/sh/clk/cpg.c | 70 +++++++++++++++++++++------------------------------- + 1 file changed, 28 insertions(+), 42 deletions(-) + +diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c +index 84aeeb8..29ee5f7 100644 +--- a/drivers/sh/clk/cpg.c ++++ b/drivers/sh/clk/cpg.c +@@ -100,6 +100,28 @@ static unsigned long sh_clk_div_recalc(struct clk *clk) + return clk->freq_table[idx].frequency; + } + ++static int sh_clk_div_set_rate(struct clk *clk, unsigned long rate) ++{ ++ struct clk_div_table *dt = clk_to_div_table(clk); ++ unsigned long value; ++ int idx; ++ ++ idx = clk_rate_table_find(clk, clk->freq_table, rate); ++ if (idx < 0) ++ return idx; ++ ++ value = sh_clk_read(clk); ++ value &= ~(clk->div_mask << clk->enable_bit); ++ value |= (idx << clk->enable_bit); ++ sh_clk_write(value, clk); ++ ++ /* XXX: Should use a post-change notifier */ ++ if (dt->kick) ++ dt->kick(clk); ++ ++ return 0; ++} ++ + /* + * div6 support + */ +@@ -152,28 +174,12 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent) + return 0; + } + +-static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate) +-{ +- unsigned long value; +- int idx; +- +- idx = clk_rate_table_find(clk, clk->freq_table, rate); +- if (idx < 0) +- return idx; +- +- value = sh_clk_read(clk); +- value &= ~clk->div_mask; +- value |= idx; +- sh_clk_write(value, clk); +- return 0; +-} +- + static int sh_clk_div6_enable(struct clk *clk) + { + unsigned long value; + int ret; + +- ret = sh_clk_div6_set_rate(clk, clk->rate); ++ ret = sh_clk_div_set_rate(clk, clk->rate); + if (ret == 0) { + value = sh_clk_read(clk); + value &= ~0x100; /* clear stop bit to enable clock */ +@@ -195,7 +201,7 @@ static void sh_clk_div6_disable(struct clk *clk) + static struct sh_clk_ops sh_clk_div6_clk_ops = { + .recalc = sh_clk_div_recalc, + .round_rate = sh_clk_div_round_rate, +- .set_rate = sh_clk_div6_set_rate, ++ .set_rate = sh_clk_div_set_rate, + .enable = sh_clk_div6_enable, + .disable = sh_clk_div6_disable, + }; +@@ -203,7 +209,7 @@ static struct sh_clk_ops sh_clk_div6_clk_ops = { + static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = { + .recalc = sh_clk_div_recalc, + .round_rate = sh_clk_div_round_rate, +- .set_rate = sh_clk_div6_set_rate, ++ .set_rate = sh_clk_div_set_rate, + .enable = sh_clk_div6_enable, + .disable = sh_clk_div6_disable, + .set_parent = sh_clk_div6_set_parent, +@@ -319,26 +325,6 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) + return 0; + } + +-static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate) +-{ +- struct clk_div_table *dt = clk_to_div_table(clk); +- unsigned long value; +- int idx = clk_rate_table_find(clk, clk->freq_table, rate); +- if (idx < 0) +- return idx; +- +- value = sh_clk_read(clk); +- value &= ~(clk->div_mask << clk->enable_bit); +- value |= (idx << clk->enable_bit); +- sh_clk_write(value, clk); +- +- /* XXX: Should use a post-change notifier */ +- if (dt->kick) +- dt->kick(clk); +- +- return 0; +-} +- + static int sh_clk_div4_enable(struct clk *clk) + { + sh_clk_write(sh_clk_read(clk) & ~(1 << 8), clk); +@@ -352,13 +338,13 @@ static void sh_clk_div4_disable(struct clk *clk) + + static struct sh_clk_ops sh_clk_div4_clk_ops = { + .recalc = sh_clk_div_recalc, +- .set_rate = sh_clk_div4_set_rate, ++ .set_rate = sh_clk_div_set_rate, + .round_rate = sh_clk_div_round_rate, + }; + + static struct sh_clk_ops sh_clk_div4_enable_clk_ops = { + .recalc = sh_clk_div_recalc, +- .set_rate = sh_clk_div4_set_rate, ++ .set_rate = sh_clk_div_set_rate, + .round_rate = sh_clk_div_round_rate, + .enable = sh_clk_div4_enable, + .disable = sh_clk_div4_disable, +@@ -366,7 +352,7 @@ static struct sh_clk_ops sh_clk_div4_enable_clk_ops = { + + static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = { + .recalc = sh_clk_div_recalc, +- .set_rate = sh_clk_div4_set_rate, ++ .set_rate = sh_clk_div_set_rate, + .round_rate = sh_clk_div_round_rate, + .enable = sh_clk_div4_enable, + .disable = sh_clk_div4_disable, +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0007-sh-clkfwk-Use-shared-sh_clk_div_enable-disable.patch b/patches.marzen/0007-sh-clkfwk-Use-shared-sh_clk_div_enable-disable.patch new file mode 100644 index 0000000000000..420a1b44271eb --- /dev/null +++ b/patches.marzen/0007-sh-clkfwk-Use-shared-sh_clk_div_enable-disable.patch @@ -0,0 +1,186 @@ +From c4dd62f54d65dfd226383c7c2aab74d9b33e71f5 Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Fri, 25 May 2012 16:34:48 +0900 +Subject: sh: clkfwk: Use shared sh_clk_div_enable/disable(). + +This introduces a new flag for clocks that need to have their divisor +ratio set back to their initial mask at disable time to prevent +interactivity problems with the clock stop bit (presently div6 only). +With this in place it's possible to handle the corner case on top of the +div4 op without any particular need for leaving things split out. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 764f4e4e33d18cde4dcaf8a0d860b749c6d6d08b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/sh/clk/cpg.c | 77 ++++++++++++++++++++++---------------------------- + include/linux/sh_clk.h | 6 ++-- + 2 files changed, 38 insertions(+), 45 deletions(-) + +diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c +index 29ee5f7..06537f2 100644 +--- a/drivers/sh/clk/cpg.c ++++ b/drivers/sh/clk/cpg.c +@@ -14,6 +14,8 @@ + #include <linux/io.h> + #include <linux/sh_clk.h> + ++#define CPG_CKSTP_BIT BIT(8) ++ + static unsigned int sh_clk_read(struct clk *clk) + { + if (clk->flags & CLK_ENABLE_REG_8BIT) +@@ -122,6 +124,30 @@ static int sh_clk_div_set_rate(struct clk *clk, unsigned long rate) + return 0; + } + ++static int sh_clk_div_enable(struct clk *clk) ++{ ++ sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk); ++ return 0; ++} ++ ++static void sh_clk_div_disable(struct clk *clk) ++{ ++ unsigned int val; ++ ++ val = sh_clk_read(clk); ++ val |= CPG_CKSTP_BIT; ++ ++ /* ++ * div6 clocks require the divisor field to be non-zero or the ++ * above CKSTP toggle silently fails. Ensure that the divisor ++ * array is reset to its initial state on disable. ++ */ ++ if (clk->flags & CLK_MASK_DIV_ON_DISABLE) ++ val |= clk->div_mask; ++ ++ sh_clk_write(val, clk); ++} ++ + /* + * div6 support + */ +@@ -174,44 +200,20 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent) + return 0; + } + +-static int sh_clk_div6_enable(struct clk *clk) +-{ +- unsigned long value; +- int ret; +- +- ret = sh_clk_div_set_rate(clk, clk->rate); +- if (ret == 0) { +- value = sh_clk_read(clk); +- value &= ~0x100; /* clear stop bit to enable clock */ +- sh_clk_write(value, clk); +- } +- return ret; +-} +- +-static void sh_clk_div6_disable(struct clk *clk) +-{ +- unsigned long value; +- +- value = sh_clk_read(clk); +- value |= 0x100; /* stop clock */ +- value |= clk->div_mask; /* VDIV bits must be non-zero, overwrite divider */ +- sh_clk_write(value, clk); +-} +- + static struct sh_clk_ops sh_clk_div6_clk_ops = { + .recalc = sh_clk_div_recalc, + .round_rate = sh_clk_div_round_rate, + .set_rate = sh_clk_div_set_rate, +- .enable = sh_clk_div6_enable, +- .disable = sh_clk_div6_disable, ++ .enable = sh_clk_div_enable, ++ .disable = sh_clk_div_disable, + }; + + static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = { + .recalc = sh_clk_div_recalc, + .round_rate = sh_clk_div_round_rate, + .set_rate = sh_clk_div_set_rate, +- .enable = sh_clk_div6_enable, +- .disable = sh_clk_div6_disable, ++ .enable = sh_clk_div_enable, ++ .disable = sh_clk_div_disable, + .set_parent = sh_clk_div6_set_parent, + }; + +@@ -325,17 +327,6 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) + return 0; + } + +-static int sh_clk_div4_enable(struct clk *clk) +-{ +- sh_clk_write(sh_clk_read(clk) & ~(1 << 8), clk); +- return 0; +-} +- +-static void sh_clk_div4_disable(struct clk *clk) +-{ +- sh_clk_write(sh_clk_read(clk) | (1 << 8), clk); +-} +- + static struct sh_clk_ops sh_clk_div4_clk_ops = { + .recalc = sh_clk_div_recalc, + .set_rate = sh_clk_div_set_rate, +@@ -346,16 +337,16 @@ static struct sh_clk_ops sh_clk_div4_enable_clk_ops = { + .recalc = sh_clk_div_recalc, + .set_rate = sh_clk_div_set_rate, + .round_rate = sh_clk_div_round_rate, +- .enable = sh_clk_div4_enable, +- .disable = sh_clk_div4_disable, ++ .enable = sh_clk_div_enable, ++ .disable = sh_clk_div_disable, + }; + + static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = { + .recalc = sh_clk_div_recalc, + .set_rate = sh_clk_div_set_rate, + .round_rate = sh_clk_div_round_rate, +- .enable = sh_clk_div4_enable, +- .disable = sh_clk_div4_disable, ++ .enable = sh_clk_div_enable, ++ .disable = sh_clk_div_disable, + .set_parent = sh_clk_div4_set_parent, + }; + +diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h +index 35a04f1..5091091 100644 +--- a/include/linux/sh_clk.h ++++ b/include/linux/sh_clk.h +@@ -69,6 +69,8 @@ struct clk { + #define CLK_ENABLE_REG_16BIT BIT(2) + #define CLK_ENABLE_REG_8BIT BIT(3) + ++#define CLK_MASK_DIV_ON_DISABLE BIT(4) ++ + #define CLK_ENABLE_REG_MASK (CLK_ENABLE_REG_32BIT | \ + CLK_ENABLE_REG_16BIT | \ + CLK_ENABLE_REG_8BIT) +@@ -173,7 +175,7 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr, + { \ + .enable_reg = (void __iomem *)_reg, \ + .enable_bit = 0, /* unused */ \ +- .flags = _flags, \ ++ .flags = _flags | CLK_MASK_DIV_ON_DISABLE, \ + .div_mask = SH_CLK_DIV6_MSK, \ + .parent_table = _parents, \ + .parent_num = _num_parents, \ +@@ -187,7 +189,7 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr, + .enable_reg = (void __iomem *)_reg, \ + .enable_bit = 0, /* unused */ \ + .div_mask = SH_CLK_DIV6_MSK, \ +- .flags = _flags, \ ++ .flags = _flags | CLK_MASK_DIV_ON_DISABLE, \ + } + + int sh_clk_div6_register(struct clk *clks, int nr); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0008-sh-clkfwk-Consolidate-div6-div4-clk_ops-definitions.patch b/patches.marzen/0008-sh-clkfwk-Consolidate-div6-div4-clk_ops-definitions.patch new file mode 100644 index 0000000000000..581bf9ad84759 --- /dev/null +++ b/patches.marzen/0008-sh-clkfwk-Consolidate-div6-div4-clk_ops-definitions.patch @@ -0,0 +1,106 @@ +From d50dd1ccae270ab558c081c9a7697137a92afdce Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Fri, 25 May 2012 16:43:42 +0900 +Subject: sh: clkfwk: Consolidate div6/div4 clk_ops definitions. + +Everything with the exception of the _reparent ops are now shared, so +switch everything over to common types. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit e3c87607731e1a8937567e92a52eedee1bec622d) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/sh/clk/cpg.c | 42 +++++++++++++++++------------------------- + 1 file changed, 17 insertions(+), 25 deletions(-) + +diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c +index 06537f2..eeaec79 100644 +--- a/drivers/sh/clk/cpg.c ++++ b/drivers/sh/clk/cpg.c +@@ -148,6 +148,20 @@ static void sh_clk_div_disable(struct clk *clk) + sh_clk_write(val, clk); + } + ++static struct sh_clk_ops sh_clk_div_clk_ops = { ++ .recalc = sh_clk_div_recalc, ++ .set_rate = sh_clk_div_set_rate, ++ .round_rate = sh_clk_div_round_rate, ++}; ++ ++static struct sh_clk_ops sh_clk_div_enable_clk_ops = { ++ .recalc = sh_clk_div_recalc, ++ .set_rate = sh_clk_div_set_rate, ++ .round_rate = sh_clk_div_round_rate, ++ .enable = sh_clk_div_enable, ++ .disable = sh_clk_div_disable, ++}; ++ + /* + * div6 support + */ +@@ -200,14 +214,6 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent) + return 0; + } + +-static struct sh_clk_ops sh_clk_div6_clk_ops = { +- .recalc = sh_clk_div_recalc, +- .round_rate = sh_clk_div_round_rate, +- .set_rate = sh_clk_div_set_rate, +- .enable = sh_clk_div_enable, +- .disable = sh_clk_div_disable, +-}; +- + static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = { + .recalc = sh_clk_div_recalc, + .round_rate = sh_clk_div_round_rate, +@@ -286,7 +292,7 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr, + + int __init sh_clk_div6_register(struct clk *clks, int nr) + { +- return sh_clk_div6_register_ops(clks, nr, &sh_clk_div6_clk_ops); ++ return sh_clk_div6_register_ops(clks, nr, &sh_clk_div_enable_clk_ops); + } + + int __init sh_clk_div6_reparent_register(struct clk *clks, int nr) +@@ -327,20 +333,6 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) + return 0; + } + +-static struct sh_clk_ops sh_clk_div4_clk_ops = { +- .recalc = sh_clk_div_recalc, +- .set_rate = sh_clk_div_set_rate, +- .round_rate = sh_clk_div_round_rate, +-}; +- +-static struct sh_clk_ops sh_clk_div4_enable_clk_ops = { +- .recalc = sh_clk_div_recalc, +- .set_rate = sh_clk_div_set_rate, +- .round_rate = sh_clk_div_round_rate, +- .enable = sh_clk_div_enable, +- .disable = sh_clk_div_disable, +-}; +- + static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = { + .recalc = sh_clk_div_recalc, + .set_rate = sh_clk_div_set_rate, +@@ -385,14 +377,14 @@ static int __init sh_clk_div4_register_ops(struct clk *clks, int nr, + int __init sh_clk_div4_register(struct clk *clks, int nr, + struct clk_div4_table *table) + { +- return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div4_clk_ops); ++ return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div_clk_ops); + } + + int __init sh_clk_div4_enable_register(struct clk *clks, int nr, + struct clk_div4_table *table) + { + return sh_clk_div4_register_ops(clks, nr, table, +- &sh_clk_div4_enable_clk_ops); ++ &sh_clk_div_enable_clk_ops); + } + + int __init sh_clk_div4_reparent_register(struct clk *clks, int nr, +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0009-sh-clkfwk-Consolidate-div-clk-registration-helper.patch b/patches.marzen/0009-sh-clkfwk-Consolidate-div-clk-registration-helper.patch new file mode 100644 index 0000000000000..bb9f3ea14c5fb --- /dev/null +++ b/patches.marzen/0009-sh-clkfwk-Consolidate-div-clk-registration-helper.patch @@ -0,0 +1,245 @@ +From 14bb73c341fd8f669c5c48c59811c8e27f3fefce Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Fri, 25 May 2012 16:55:05 +0900 +Subject: sh: clkfwk: Consolidate div clk registration helper. + +This consolidates the div6/4 versions of the clk registration wrapper. +The existing wrappers with their own sh_clk_ops are maintained for API +compatability, though in the future it should be possible to be rid of +them entirely. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 609d7558f232e583a31951c65a6ee43d81c65720) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/sh/clk/cpg.c | 182 +++++++++++++++++++++------------------------------ + 1 file changed, 75 insertions(+), 107 deletions(-) + +diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c +index eeaec79..07e9fb4 100644 +--- a/drivers/sh/clk/cpg.c ++++ b/drivers/sh/clk/cpg.c +@@ -162,6 +162,72 @@ static struct sh_clk_ops sh_clk_div_enable_clk_ops = { + .disable = sh_clk_div_disable, + }; + ++static int __init sh_clk_init_parent(struct clk *clk) ++{ ++ u32 val; ++ ++ if (clk->parent) ++ return 0; ++ ++ if (!clk->parent_table || !clk->parent_num) ++ return 0; ++ ++ if (!clk->src_width) { ++ pr_err("sh_clk_init_parent: cannot select parent clock\n"); ++ return -EINVAL; ++ } ++ ++ val = (sh_clk_read(clk) >> clk->src_shift); ++ val &= (1 << clk->src_width) - 1; ++ ++ if (val >= clk->parent_num) { ++ pr_err("sh_clk_init_parent: parent table size failed\n"); ++ return -EINVAL; ++ } ++ ++ clk_reparent(clk, clk->parent_table[val]); ++ if (!clk->parent) { ++ pr_err("sh_clk_init_parent: unable to set parent"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int __init sh_clk_div_register_ops(struct clk *clks, int nr, ++ struct clk_div_table *table, struct sh_clk_ops *ops) ++{ ++ struct clk *clkp; ++ void *freq_table; ++ int nr_divs = table->div_mult_table->nr_divisors; ++ int freq_table_size = sizeof(struct cpufreq_frequency_table); ++ int ret = 0; ++ int k; ++ ++ freq_table_size *= (nr_divs + 1); ++ freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL); ++ if (!freq_table) { ++ pr_err("%s: unable to alloc memory\n", __func__); ++ return -ENOMEM; ++ } ++ ++ for (k = 0; !ret && (k < nr); k++) { ++ clkp = clks + k; ++ ++ clkp->ops = ops; ++ clkp->priv = table; ++ ++ clkp->freq_table = freq_table + (k * freq_table_size); ++ clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; ++ ++ ret = clk_register(clkp); ++ if (ret == 0) ++ ret = sh_clk_init_parent(clkp); ++ } ++ ++ return ret; ++} ++ + /* + * div6 support + */ +@@ -223,82 +289,16 @@ static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = { + .set_parent = sh_clk_div6_set_parent, + }; + +-static int __init sh_clk_init_parent(struct clk *clk) +-{ +- u32 val; +- +- if (clk->parent) +- return 0; +- +- if (!clk->parent_table || !clk->parent_num) +- return 0; +- +- if (!clk->src_width) { +- pr_err("sh_clk_init_parent: cannot select parent clock\n"); +- return -EINVAL; +- } +- +- val = (sh_clk_read(clk) >> clk->src_shift); +- val &= (1 << clk->src_width) - 1; +- +- if (val >= clk->parent_num) { +- pr_err("sh_clk_init_parent: parent table size failed\n"); +- return -EINVAL; +- } +- +- clk_reparent(clk, clk->parent_table[val]); +- if (!clk->parent) { +- pr_err("sh_clk_init_parent: unable to set parent"); +- return -EINVAL; +- } +- +- return 0; +-} +- +-static int __init sh_clk_div6_register_ops(struct clk *clks, int nr, +- struct sh_clk_ops *ops) +-{ +- struct clk *clkp; +- void *freq_table; +- struct clk_div_table *table = &sh_clk_div6_table; +- int nr_divs = table->div_mult_table->nr_divisors; +- int freq_table_size = sizeof(struct cpufreq_frequency_table); +- int ret = 0; +- int k; +- +- freq_table_size *= (nr_divs + 1); +- freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL); +- if (!freq_table) { +- pr_err("sh_clk_div6_register: unable to alloc memory\n"); +- return -ENOMEM; +- } +- +- for (k = 0; !ret && (k < nr); k++) { +- clkp = clks + k; +- +- clkp->ops = ops; +- clkp->priv = table; +- clkp->freq_table = freq_table + (k * freq_table_size); +- clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; +- ret = clk_register(clkp); +- if (ret < 0) +- break; +- +- ret = sh_clk_init_parent(clkp); +- } +- +- return ret; +-} +- + int __init sh_clk_div6_register(struct clk *clks, int nr) + { +- return sh_clk_div6_register_ops(clks, nr, &sh_clk_div_enable_clk_ops); ++ return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table, ++ &sh_clk_div_enable_clk_ops); + } + + int __init sh_clk_div6_reparent_register(struct clk *clks, int nr) + { +- return sh_clk_div6_register_ops(clks, nr, +- &sh_clk_div6_reparent_clk_ops); ++ return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table, ++ &sh_clk_div6_reparent_clk_ops); + } + + /* +@@ -342,54 +342,22 @@ static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = { + .set_parent = sh_clk_div4_set_parent, + }; + +-static int __init sh_clk_div4_register_ops(struct clk *clks, int nr, +- struct clk_div4_table *table, struct sh_clk_ops *ops) +-{ +- struct clk *clkp; +- void *freq_table; +- int nr_divs = table->div_mult_table->nr_divisors; +- int freq_table_size = sizeof(struct cpufreq_frequency_table); +- int ret = 0; +- int k; +- +- freq_table_size *= (nr_divs + 1); +- freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL); +- if (!freq_table) { +- pr_err("sh_clk_div4_register: unable to alloc memory\n"); +- return -ENOMEM; +- } +- +- for (k = 0; !ret && (k < nr); k++) { +- clkp = clks + k; +- +- clkp->ops = ops; +- clkp->priv = table; +- +- clkp->freq_table = freq_table + (k * freq_table_size); +- clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; +- +- ret = clk_register(clkp); +- } +- +- return ret; +-} +- + int __init sh_clk_div4_register(struct clk *clks, int nr, + struct clk_div4_table *table) + { +- return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div_clk_ops); ++ return sh_clk_div_register_ops(clks, nr, table, &sh_clk_div_clk_ops); + } + + int __init sh_clk_div4_enable_register(struct clk *clks, int nr, + struct clk_div4_table *table) + { +- return sh_clk_div4_register_ops(clks, nr, table, +- &sh_clk_div_enable_clk_ops); ++ return sh_clk_div_register_ops(clks, nr, table, ++ &sh_clk_div_enable_clk_ops); + } + + int __init sh_clk_div4_reparent_register(struct clk *clks, int nr, + struct clk_div4_table *table) + { +- return sh_clk_div4_register_ops(clks, nr, table, +- &sh_clk_div4_reparent_clk_ops); ++ return sh_clk_div_register_ops(clks, nr, table, ++ &sh_clk_div4_reparent_clk_ops); + } +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0010-irqdomain-Support-removal-of-IRQ-domains.patch b/patches.marzen/0010-irqdomain-Support-removal-of-IRQ-domains.patch new file mode 100644 index 0000000000000..1a0d5128a3cef --- /dev/null +++ b/patches.marzen/0010-irqdomain-Support-removal-of-IRQ-domains.patch @@ -0,0 +1,128 @@ +From 0ee607349ba34cf8cdb94370c297faed58f64e39 Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Sat, 19 May 2012 15:11:41 +0900 +Subject: irqdomain: Support removal of IRQ domains. + +Now that IRQ domains are being used by modules it's necessary to support +removing them, too. This adds a new irq_domain_remove() routine for doing +the bulk of the heavy lifting. It's left as an exercise to the caller to +ensure all mappings have been appropriatey disposed of before attempting +to remove the domain. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +(cherry picked from commit 58ee99ada293b5ed971a023304fcfbc1a0ccdb1c) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/irqdomain.h | 4 +++- + kernel/irq/irqdomain.c | 61 +++++++++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 62 insertions(+), 3 deletions(-) + +diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h +index c65740d..a796dbf 100644 +--- a/include/linux/irqdomain.h ++++ b/include/linux/irqdomain.h +@@ -141,10 +141,12 @@ static inline struct irq_domain *irq_domain_add_legacy_isa( + return irq_domain_add_legacy(of_node, NUM_ISA_INTERRUPTS, 0, 0, ops, + host_data); + } ++ ++extern void irq_domain_remove(struct irq_domain *host); ++ + extern struct irq_domain *irq_find_host(struct device_node *node); + extern void irq_set_default_host(struct irq_domain *host); + +- + extern unsigned int irq_create_mapping(struct irq_domain *host, + irq_hw_number_t hwirq); + extern void irq_dispose_mapping(unsigned int virq); +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 0e0ba5f..9cae0b2 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -56,6 +56,12 @@ static struct irq_domain *irq_domain_alloc(struct device_node *of_node, + return domain; + } + ++static void irq_domain_free(struct irq_domain *domain) ++{ ++ of_node_put(domain->of_node); ++ kfree(domain); ++} ++ + static void irq_domain_add(struct irq_domain *domain) + { + mutex_lock(&irq_domain_mutex); +@@ -65,6 +71,58 @@ static void irq_domain_add(struct irq_domain *domain) + domain->revmap_type, domain); + } + ++/** ++ * irq_domain_remove() - Remove an irq domain. ++ * @domain: domain to remove ++ * ++ * This routine is used to remove an irq domain. The caller must ensure ++ * that all mappings within the domain have been disposed of prior to ++ * use, depending on the revmap type. ++ */ ++void irq_domain_remove(struct irq_domain *domain) ++{ ++ mutex_lock(&irq_domain_mutex); ++ ++ switch (domain->revmap_type) { ++ case IRQ_DOMAIN_MAP_LEGACY: ++ /* ++ * Legacy domains don't manage their own irq_desc ++ * allocations, we expect the caller to handle irq_desc ++ * freeing on their own. ++ */ ++ break; ++ case IRQ_DOMAIN_MAP_TREE: ++ /* ++ * radix_tree_delete() takes care of destroying the root ++ * node when all entries are removed. Shout if there are ++ * any mappings left. ++ */ ++ WARN_ON(domain->revmap_data.tree.height); ++ break; ++ case IRQ_DOMAIN_MAP_LINEAR: ++ kfree(domain->revmap_data.linear.revmap); ++ domain->revmap_data.linear.size = 0; ++ break; ++ case IRQ_DOMAIN_MAP_NOMAP: ++ break; ++ } ++ ++ list_del(&domain->link); ++ ++ /* ++ * If the going away domain is the default one, reset it. ++ */ ++ if (unlikely(irq_default_domain == domain)) ++ irq_set_default_host(NULL); ++ ++ mutex_unlock(&irq_domain_mutex); ++ ++ pr_debug("irq: Removed domain of type %d @0x%p\n", ++ domain->revmap_type, domain); ++ ++ irq_domain_free(domain); ++} ++ + static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain, + irq_hw_number_t hwirq) + { +@@ -117,8 +175,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, + + if (WARN_ON(!irq_data || irq_data->domain)) { + mutex_unlock(&irq_domain_mutex); +- of_node_put(domain->of_node); +- kfree(domain); ++ irq_domain_free(domain); + return NULL; + } + } +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0011-irqdomain-Export-remaining-public-API-symbols.patch b/patches.marzen/0011-irqdomain-Export-remaining-public-API-symbols.patch new file mode 100644 index 0000000000000..4489c8e283376 --- /dev/null +++ b/patches.marzen/0011-irqdomain-Export-remaining-public-API-symbols.patch @@ -0,0 +1,109 @@ +From fd54923383b7dee6af8b53a91d2c6768d2726d77 Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Sat, 19 May 2012 15:11:42 +0900 +Subject: irqdomain: Export remaining public API symbols. + +modules making use of irq domains at the very least need access to the +add/remove/lookup routines, though there's nothing preventing them from +using the remainder of the public API, either. + +The current set of exports seem primarily geared at DT-enabled platforms +using DT-backed IRQ domains, where many of the API accesses are hidden +away in OF code. The non-DT cases need to do most of this on their own. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +(cherry picked from commit ecd84eb20a08841197d6bbda5961dcf5f4e424fc) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + kernel/irq/irqdomain.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 9cae0b2..01d4a0d 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -122,6 +122,7 @@ void irq_domain_remove(struct irq_domain *domain) + + irq_domain_free(domain); + } ++EXPORT_SYMBOL_GPL(irq_domain_remove); + + static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain, + irq_hw_number_t hwirq) +@@ -209,6 +210,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, + irq_domain_add(domain); + return domain; + } ++EXPORT_SYMBOL_GPL(irq_domain_add_legacy); + + /** + * irq_domain_add_linear() - Allocate and register a legacy revmap irq_domain. +@@ -238,6 +240,7 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node, + irq_domain_add(domain); + return domain; + } ++EXPORT_SYMBOL_GPL(irq_domain_add_linear); + + struct irq_domain *irq_domain_add_nomap(struct device_node *of_node, + unsigned int max_irq, +@@ -252,6 +255,7 @@ struct irq_domain *irq_domain_add_nomap(struct device_node *of_node, + } + return domain; + } ++EXPORT_SYMBOL_GPL(irq_domain_add_nomap); + + /** + * irq_domain_add_tree() +@@ -273,6 +277,7 @@ struct irq_domain *irq_domain_add_tree(struct device_node *of_node, + } + return domain; + } ++EXPORT_SYMBOL_GPL(irq_domain_add_tree); + + /** + * irq_find_host() - Locates a domain for a given device node +@@ -320,6 +325,7 @@ void irq_set_default_host(struct irq_domain *domain) + + irq_default_domain = domain; + } ++EXPORT_SYMBOL_GPL(irq_set_default_host); + + static int irq_setup_virq(struct irq_domain *domain, unsigned int virq, + irq_hw_number_t hwirq) +@@ -378,6 +384,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain) + + return virq; + } ++EXPORT_SYMBOL_GPL(irq_create_direct_mapping); + + /** + * irq_create_mapping() - Map a hardware interrupt into linux irq space +@@ -617,6 +624,7 @@ unsigned int irq_radix_revmap_lookup(struct irq_domain *domain, + */ + return irq_data ? irq_data->irq : irq_find_mapping(domain, hwirq); + } ++EXPORT_SYMBOL_GPL(irq_radix_revmap_lookup); + + /** + * irq_radix_revmap_insert() - Insert a hw irq to linux irq number mapping. +@@ -641,6 +649,7 @@ void irq_radix_revmap_insert(struct irq_domain *domain, unsigned int virq, + mutex_unlock(&revmap_trees_mutex); + } + } ++EXPORT_SYMBOL_GPL(irq_radix_revmap_insert); + + /** + * irq_linear_revmap() - Find a linux irq from a hw irq number. +@@ -674,6 +683,7 @@ unsigned int irq_linear_revmap(struct irq_domain *domain, + + return revmap[hwirq]; + } ++EXPORT_SYMBOL_GPL(irq_linear_revmap); + + #ifdef CONFIG_IRQ_DOMAIN_DEBUG + static int virq_debug_show(struct seq_file *m, void *private) +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0012-irqdomain-Make-irq_domain_simple_map-static.patch b/patches.marzen/0012-irqdomain-Make-irq_domain_simple_map-static.patch new file mode 100644 index 0000000000000..17332a5efb4a3 --- /dev/null +++ b/patches.marzen/0012-irqdomain-Make-irq_domain_simple_map-static.patch @@ -0,0 +1,38 @@ +From 5cfad4570d46fe50c16ce73dcf3f2d6bf76f2b33 Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Sat, 19 May 2012 15:11:43 +0900 +Subject: irqdomain: Make irq_domain_simple_map() static. + +Presently irq_domain_simple_map() isn't labelled as static, but there's +no definition for it in the public irqdomain header either. At present +all in-tree ->map users have meaningful work to do, and all others are +using irq_domain_simple_ops directly. Make it static for now, as it can +always be exported and added to the public API later. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +(cherry picked from commit 5c5806e50b9fd4ca435acdf0eceddda64da9be5b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + kernel/irq/irqdomain.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 01d4a0d..92e06442 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -758,8 +758,8 @@ static int __init irq_debugfs_init(void) + __initcall(irq_debugfs_init); + #endif /* CONFIG_IRQ_DOMAIN_DEBUG */ + +-int irq_domain_simple_map(struct irq_domain *d, unsigned int irq, +- irq_hw_number_t hwirq) ++static int irq_domain_simple_map(struct irq_domain *d, unsigned int irq, ++ irq_hw_number_t hwirq) + { + return 0; + } +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0013-irqdomain-Kill-off-duplicate-definitions.patch b/patches.marzen/0013-irqdomain-Kill-off-duplicate-definitions.patch new file mode 100644 index 0000000000000..ad6a35bf3040d --- /dev/null +++ b/patches.marzen/0013-irqdomain-Kill-off-duplicate-definitions.patch @@ -0,0 +1,35 @@ +From 4eb9577004521127daa39444ae35279e8f07eccd Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Sat, 19 May 2012 15:11:45 +0900 +Subject: irqdomain: Kill off duplicate definitions. + +Presently irqdomain.h has duplicate definitions for irq_find_host() and +irq_set_default_host(), presumably from merge damage. Kill off the +duplicates. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +(cherry picked from commit cb5557bec9f14d05204a9014ae1b23aca8b04f1d) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/irqdomain.h | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h +index a796dbf..5abb533 100644 +--- a/include/linux/irqdomain.h ++++ b/include/linux/irqdomain.h +@@ -144,9 +144,6 @@ static inline struct irq_domain *irq_domain_add_legacy_isa( + + extern void irq_domain_remove(struct irq_domain *host); + +-extern struct irq_domain *irq_find_host(struct device_node *node); +-extern void irq_set_default_host(struct irq_domain *host); +- + extern unsigned int irq_create_mapping(struct irq_domain *host, + irq_hw_number_t hwirq); + extern void irq_dispose_mapping(unsigned int virq); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0014-irqdomain-trivial-pr_fmt-conversion.patch b/patches.marzen/0014-irqdomain-trivial-pr_fmt-conversion.patch new file mode 100644 index 0000000000000..8211a8768fc0c --- /dev/null +++ b/patches.marzen/0014-irqdomain-trivial-pr_fmt-conversion.patch @@ -0,0 +1,142 @@ +From acccf0bbf24e13673a3d5d76e49f389d736d4882 Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Sat, 19 May 2012 15:11:47 +0900 +Subject: irqdomain: trivial pr_fmt conversion. + +Convert to pr_fmt before things start to get out of hand and some +janitors start getting overly excited. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +(cherry picked from commit 54a9058860f2b7ed8d2fe5bf7be19bb901866dc2) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + kernel/irq/irqdomain.c | 32 +++++++++++++++++--------------- + 1 file changed, 17 insertions(+), 15 deletions(-) + +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 92e06442..9a6e8a8 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -1,3 +1,5 @@ ++#define pr_fmt(fmt) "irq: " fmt ++ + #include <linux/debugfs.h> + #include <linux/hardirq.h> + #include <linux/interrupt.h> +@@ -67,7 +69,7 @@ static void irq_domain_add(struct irq_domain *domain) + mutex_lock(&irq_domain_mutex); + list_add(&domain->link, &irq_domain_list); + mutex_unlock(&irq_domain_mutex); +- pr_debug("irq: Allocated domain of type %d @0x%p\n", ++ pr_debug("Allocated domain of type %d @0x%p\n", + domain->revmap_type, domain); + } + +@@ -117,7 +119,7 @@ void irq_domain_remove(struct irq_domain *domain) + + mutex_unlock(&irq_domain_mutex); + +- pr_debug("irq: Removed domain of type %d @0x%p\n", ++ pr_debug("Removed domain of type %d @0x%p\n", + domain->revmap_type, domain); + + irq_domain_free(domain); +@@ -321,7 +323,7 @@ EXPORT_SYMBOL_GPL(irq_find_host); + */ + void irq_set_default_host(struct irq_domain *domain) + { +- pr_debug("irq: Default domain set to @0x%p\n", domain); ++ pr_debug("Default domain set to @0x%p\n", domain); + + irq_default_domain = domain; + } +@@ -335,7 +337,7 @@ static int irq_setup_virq(struct irq_domain *domain, unsigned int virq, + irq_data->hwirq = hwirq; + irq_data->domain = domain; + if (domain->ops->map(domain, virq, hwirq)) { +- pr_debug("irq: -> mapping failed, freeing\n"); ++ pr_debug("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq); + irq_data->domain = NULL; + irq_data->hwirq = 0; + return -1; +@@ -366,7 +368,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain) + + virq = irq_alloc_desc_from(1, 0); + if (!virq) { +- pr_debug("irq: create_direct virq allocation failed\n"); ++ pr_debug("create_direct virq allocation failed\n"); + return 0; + } + if (virq >= domain->revmap_data.nomap.max_irq) { +@@ -375,7 +377,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain) + irq_free_desc(virq); + return 0; + } +- pr_debug("irq: create_direct obtained virq %d\n", virq); ++ pr_debug("create_direct obtained virq %d\n", virq); + + if (irq_setup_virq(domain, virq, virq)) { + irq_free_desc(virq); +@@ -402,23 +404,23 @@ unsigned int irq_create_mapping(struct irq_domain *domain, + unsigned int hint; + int virq; + +- pr_debug("irq: irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq); ++ pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq); + + /* Look for default domain if nececssary */ + if (domain == NULL) + domain = irq_default_domain; + if (domain == NULL) { +- printk(KERN_WARNING "irq_create_mapping called for" +- " NULL domain, hwirq=%lx\n", hwirq); ++ pr_warning("irq_create_mapping called for" ++ " NULL domain, hwirq=%lx\n", hwirq); + WARN_ON(1); + return 0; + } +- pr_debug("irq: -> using domain @%p\n", domain); ++ pr_debug("-> using domain @%p\n", domain); + + /* Check if mapping already exists */ + virq = irq_find_mapping(domain, hwirq); + if (virq) { +- pr_debug("irq: -> existing mapping on virq %d\n", virq); ++ pr_debug("-> existing mapping on virq %d\n", virq); + return virq; + } + +@@ -434,7 +436,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain, + if (virq <= 0) + virq = irq_alloc_desc_from(1, 0); + if (virq <= 0) { +- pr_debug("irq: -> virq allocation failed\n"); ++ pr_debug("-> virq allocation failed\n"); + return 0; + } + +@@ -444,7 +446,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain, + return 0; + } + +- pr_debug("irq: irq %lu on domain %s mapped to virtual irq %u\n", ++ pr_debug("irq %lu on domain %s mapped to virtual irq %u\n", + hwirq, domain->of_node ? domain->of_node->full_name : "null", virq); + + return virq; +@@ -473,8 +475,8 @@ unsigned int irq_create_of_mapping(struct device_node *controller, + if (intsize > 0) + return intspec[0]; + #endif +- printk(KERN_WARNING "irq: no irq domain found for %s !\n", +- controller->full_name); ++ pr_warning("no irq domain found for %s !\n", ++ controller->full_name); + return 0; + } + +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0015-irqdomain-Document-size-parameter-of-irq_domain_add_.patch b/patches.marzen/0015-irqdomain-Document-size-parameter-of-irq_domain_add_.patch new file mode 100644 index 0000000000000..c58ba4285e19a --- /dev/null +++ b/patches.marzen/0015-irqdomain-Document-size-parameter-of-irq_domain_add_.patch @@ -0,0 +1,29 @@ +From b1308eaacaa94b41421129c2cd44b69e4e83f2de Mon Sep 17 00:00:00 2001 +From: Mark Brown <broonie@opensource.wolfsonmicro.com> +Date: Sat, 19 May 2012 12:15:35 +0100 +Subject: irqdomain: Document size parameter of irq_domain_add_linear() + +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +(cherry picked from commit a87487e687ceafdc696b8cb1fb27e37cc463586b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + kernel/irq/irqdomain.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 9a6e8a8..41c1564 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -217,6 +217,7 @@ EXPORT_SYMBOL_GPL(irq_domain_add_legacy); + /** + * irq_domain_add_linear() - Allocate and register a legacy revmap irq_domain. + * @of_node: pointer to interrupt controller's device tree node. ++ * @size: Number of interrupts in the domain. + * @ops: map/unmap domain callbacks + * @host_data: Controller private data pointer + */ +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0016-devicetree-add-helper-inline-for-retrieving-a-node-s.patch b/patches.marzen/0016-devicetree-add-helper-inline-for-retrieving-a-node-s.patch new file mode 100644 index 0000000000000..24847e4eed646 --- /dev/null +++ b/patches.marzen/0016-devicetree-add-helper-inline-for-retrieving-a-node-s.patch @@ -0,0 +1,232 @@ +From e572a45ad1741b29429e38cfd2be60e23e1ebc57 Mon Sep 17 00:00:00 2001 +From: Grant Likely <grant.likely@secretlab.ca> +Date: Fri, 15 Jun 2012 11:50:25 -0600 +Subject: devicetree: add helper inline for retrieving a node's full name + +The pattern (np ? np->full_name : "<none>") is rather common in the +kernel, but can also make for quite long lines. This patch adds a new +inline function, of_node_full_name() so that the test for a valid node +pointer doesn't need to be open coded at all call sites. + +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +Cc: Paul Mundt <lethal@linux-sh.org> +Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Signed-off-by: Rob Herring <rob.herring@calxeda.com> +(cherry picked from commit 74a7f08448adea6cb47cd9b260c98ff168117e92) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/microblaze/pci/pci-common.c | 6 ++---- + arch/powerpc/kernel/pci-common.c | 6 ++---- + arch/powerpc/kernel/vio.c | 5 ++--- + arch/powerpc/platforms/cell/iommu.c | 3 +-- + arch/powerpc/platforms/pseries/iommu.c | 2 +- + arch/sparc/kernel/of_device_64.c | 2 +- + drivers/of/base.c | 2 +- + drivers/of/irq.c | 2 +- + include/linux/of.h | 10 ++++++++++ + kernel/irq/irqdomain.c | 8 ++++---- + 10 files changed, 25 insertions(+), 21 deletions(-) + +diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c +index d10403d..162b4e5 100644 +--- a/arch/microblaze/pci/pci-common.c ++++ b/arch/microblaze/pci/pci-common.c +@@ -249,8 +249,7 @@ int pci_read_irq_line(struct pci_dev *pci_dev) + } else { + pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n", + oirq.size, oirq.specifier[0], oirq.specifier[1], +- oirq.controller ? oirq.controller->full_name : +- "<default>"); ++ of_node_full_name(oirq.controller)); + + virq = irq_create_of_mapping(oirq.controller, oirq.specifier, + oirq.size); +@@ -1492,8 +1491,7 @@ static void __devinit pcibios_scan_phb(struct pci_controller *hose) + struct pci_bus *bus; + struct device_node *node = hose->dn; + +- pr_debug("PCI: Scanning PHB %s\n", +- node ? node->full_name : "<NO NAME>"); ++ pr_debug("PCI: Scanning PHB %s\n", of_node_full_name(node)); + + pcibios_setup_phb_resources(hose, &resources); + +diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c +index 8e78e93..886c254 100644 +--- a/arch/powerpc/kernel/pci-common.c ++++ b/arch/powerpc/kernel/pci-common.c +@@ -248,8 +248,7 @@ static int pci_read_irq_line(struct pci_dev *pci_dev) + } else { + pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n", + oirq.size, oirq.specifier[0], oirq.specifier[1], +- oirq.controller ? oirq.controller->full_name : +- "<default>"); ++ of_node_full_name(oirq.controller)); + + virq = irq_create_of_mapping(oirq.controller, oirq.specifier, + oirq.size); +@@ -1628,8 +1627,7 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) + struct device_node *node = hose->dn; + int mode; + +- pr_debug("PCI: Scanning PHB %s\n", +- node ? node->full_name : "<NO NAME>"); ++ pr_debug("PCI: Scanning PHB %s\n", of_node_full_name(node)); + + /* Get some IO space for the new PHB */ + pcibios_setup_phb_io_space(hose); +diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c +index a3a9990..ea6081a 100644 +--- a/arch/powerpc/kernel/vio.c ++++ b/arch/powerpc/kernel/vio.c +@@ -1193,8 +1193,7 @@ static void __devinit vio_dev_release(struct device *dev) + struct iommu_table *tbl = get_iommu_table_base(dev); + + if (tbl) +- iommu_free_table(tbl, dev->of_node ? +- dev->of_node->full_name : dev_name(dev)); ++ iommu_free_table(tbl, of_node_full_name(dev->of_node)); + of_node_put(dev->of_node); + kfree(to_vio_dev(dev)); + } +@@ -1330,7 +1329,7 @@ static ssize_t devspec_show(struct device *dev, + { + struct device_node *of_node = dev->of_node; + +- return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none"); ++ return sprintf(buf, "%s\n", of_node_full_name(of_node)); + } + + static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, +diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c +index b9f509a..b673200 100644 +--- a/arch/powerpc/platforms/cell/iommu.c ++++ b/arch/powerpc/platforms/cell/iommu.c +@@ -552,8 +552,7 @@ static struct iommu_table *cell_get_iommu_table(struct device *dev) + iommu = cell_iommu_for_node(dev_to_node(dev)); + if (iommu == NULL || list_empty(&iommu->windows)) { + printk(KERN_ERR "iommu: missing iommu for %s (node %d)\n", +- dev->of_node ? dev->of_node->full_name : "?", +- dev_to_node(dev)); ++ of_node_full_name(dev->of_node), dev_to_node(dev)); + return NULL; + } + window = list_entry(iommu->windows.next, struct iommu_window, list); +diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c +index 2d311c0..6b58a39 100644 +--- a/arch/powerpc/platforms/pseries/iommu.c ++++ b/arch/powerpc/platforms/pseries/iommu.c +@@ -1051,7 +1051,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) + if (!pdn || !PCI_DN(pdn)) { + printk(KERN_WARNING "pci_dma_dev_setup_pSeriesLP: " + "no DMA window found for pci dev=%s dn=%s\n", +- pci_name(dev), dn? dn->full_name : "<null>"); ++ pci_name(dev), of_node_full_name(dn)); + return; + } + pr_debug(" parent is %s\n", pdn->full_name); +diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device_64.c +index 7a3be6f..7bbdc26 100644 +--- a/arch/sparc/kernel/of_device_64.c ++++ b/arch/sparc/kernel/of_device_64.c +@@ -580,7 +580,7 @@ static unsigned int __init build_one_device_irq(struct platform_device *op, + printk("%s: Apply [%s:%x] imap --> [%s:%x]\n", + op->dev.of_node->full_name, + pp->full_name, this_orig_irq, +- (iret ? iret->full_name : "NULL"), irq); ++ of_node_full_name(iret), irq); + + if (!iret) + break; +diff --git a/drivers/of/base.c b/drivers/of/base.c +index 5806449..6271c2e 100644 +--- a/drivers/of/base.c ++++ b/drivers/of/base.c +@@ -1173,7 +1173,7 @@ static void of_alias_add(struct alias_prop *ap, struct device_node *np, + ap->stem[stem_len] = 0; + list_add_tail(&ap->link, &aliases_lookup); + pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n", +- ap->alias, ap->stem, ap->id, np ? np->full_name : NULL); ++ ap->alias, ap->stem, ap->id, of_node_full_name(np)); + } + + /** +diff --git a/drivers/of/irq.c b/drivers/of/irq.c +index 9cf0060..ff8ab7b 100644 +--- a/drivers/of/irq.c ++++ b/drivers/of/irq.c +@@ -255,7 +255,7 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec, + + skiplevel: + /* Iterate again with new parent */ +- pr_debug(" -> new parent: %s\n", newpar ? newpar->full_name : "<>"); ++ pr_debug(" -> new parent: %s\n", of_node_full_name(newpar)); + of_node_put(ipar); + ipar = newpar; + newpar = NULL; +diff --git a/include/linux/of.h b/include/linux/of.h +index fa7fb1d..284d117 100644 +--- a/include/linux/of.h ++++ b/include/linux/of.h +@@ -163,6 +163,11 @@ static inline int of_node_to_nid(struct device_node *np) { return -1; } + #define of_node_to_nid of_node_to_nid + #endif + ++static inline const char* of_node_full_name(struct device_node *np) ++{ ++ return np ? np->full_name : "<no-node>"; ++} ++ + extern struct device_node *of_find_node_by_name(struct device_node *from, + const char *name); + #define for_each_node_by_name(dn, name) \ +@@ -261,6 +266,11 @@ extern void of_detach_node(struct device_node *); + #define of_match_ptr(_ptr) (_ptr) + #else /* CONFIG_OF */ + ++static inline const char* of_node_full_name(struct device_node *np) ++{ ++ return "<no-node>"; ++} ++ + static inline bool of_have_populated_dt(void) + { + return false; +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 41c1564..38c5eb8 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -448,7 +448,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain, + } + + pr_debug("irq %lu on domain %s mapped to virtual irq %u\n", +- hwirq, domain->of_node ? domain->of_node->full_name : "null", virq); ++ hwirq, of_node_full_name(domain->of_node), virq); + + return virq; + } +@@ -477,7 +477,7 @@ unsigned int irq_create_of_mapping(struct device_node *controller, + return intspec[0]; + #endif + pr_warning("no irq domain found for %s !\n", +- controller->full_name); ++ of_node_full_name(controller)); + return 0; + } + +@@ -725,8 +725,8 @@ static int virq_debug_show(struct seq_file *m, void *private) + data = irq_desc_get_chip_data(desc); + seq_printf(m, data ? "0x%p " : " %p ", data); + +- if (desc->irq_data.domain && desc->irq_data.domain->of_node) +- p = desc->irq_data.domain->of_node->full_name; ++ if (desc->irq_data.domain) ++ p = of_node_full_name(desc->irq_data.domain->of_node); + else + p = none; + seq_printf(m, "%s\n", p); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0017-irqdomain-Simple-NUMA-awareness.patch b/patches.marzen/0017-irqdomain-Simple-NUMA-awareness.patch new file mode 100644 index 0000000000000..099c368676248 --- /dev/null +++ b/patches.marzen/0017-irqdomain-Simple-NUMA-awareness.patch @@ -0,0 +1,132 @@ +From 249521995c6f0647ab54b64f89103ba3389edfea Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Sun, 3 Jun 2012 22:04:34 -0700 +Subject: irqdomain: Simple NUMA awareness. + +While common irqdesc allocation is node aware, the irqdomain code is not. + +Presently we observe a number of regressions/inconsistencies on +NUMA-capable platforms: + +- Platforms using irqdomains with legacy mappings, where the + irq_descs are allocated node-local and the irqdomain data + structure is not. + +- Drivers implementing irqdomains will lose node locality + regardless of the underlying struct device's node id. + +This plugs in NUMA node id proliferation across the various allocation +callsites by way of_node_to_nid() node lookup. While of_node_to_nid() +does the right thing for OF-capable platforms it doesn't presently handle +the non-DT case. This is trivially dealt with by simply wraping in to +numa_node_id() unconditionally. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: Rob Herring <rob.herring@calxeda.com> +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +(cherry picked from commit 5ca4db61e859526b2dbee3bcea3626d3de49a0b2) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/of.h | 15 ++++++++++----- + kernel/irq/irqdomain.c | 13 ++++++++----- + 2 files changed, 18 insertions(+), 10 deletions(-) + +diff --git a/include/linux/of.h b/include/linux/of.h +index 284d117..e24c5cc 100644 +--- a/include/linux/of.h ++++ b/include/linux/of.h +@@ -21,6 +21,7 @@ + #include <linux/kref.h> + #include <linux/mod_devicetable.h> + #include <linux/spinlock.h> ++#include <linux/topology.h> + + #include <asm/byteorder.h> + #include <asm/errno.h> +@@ -158,11 +159,6 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size) + + #define OF_BAD_ADDR ((u64)-1) + +-#ifndef of_node_to_nid +-static inline int of_node_to_nid(struct device_node *np) { return -1; } +-#define of_node_to_nid of_node_to_nid +-#endif +- + static inline const char* of_node_full_name(struct device_node *np) + { + return np ? np->full_name : "<no-node>"; +@@ -361,6 +357,15 @@ static inline int of_machine_is_compatible(const char *compat) + #define of_match_node(_matches, _node) NULL + #endif /* CONFIG_OF */ + ++#ifndef of_node_to_nid ++static inline int of_node_to_nid(struct device_node *np) ++{ ++ return numa_node_id(); ++} ++ ++#define of_node_to_nid of_node_to_nid ++#endif ++ + /** + * of_property_read_bool - Findfrom a property + * @np: device node from which the property value is to be read. +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 38c5eb8..79ae0eb 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -10,6 +10,7 @@ + #include <linux/mutex.h> + #include <linux/of.h> + #include <linux/of_address.h> ++#include <linux/topology.h> + #include <linux/seq_file.h> + #include <linux/slab.h> + #include <linux/smp.h> +@@ -45,7 +46,8 @@ static struct irq_domain *irq_domain_alloc(struct device_node *of_node, + { + struct irq_domain *domain; + +- domain = kzalloc(sizeof(*domain), GFP_KERNEL); ++ domain = kzalloc_node(sizeof(*domain), GFP_KERNEL, ++ of_node_to_nid(of_node)); + if (WARN_ON(!domain)) + return NULL; + +@@ -229,7 +231,8 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node, + struct irq_domain *domain; + unsigned int *revmap; + +- revmap = kzalloc(sizeof(*revmap) * size, GFP_KERNEL); ++ revmap = kzalloc_node(sizeof(*revmap) * size, GFP_KERNEL, ++ of_node_to_nid(of_node)); + if (WARN_ON(!revmap)) + return NULL; + +@@ -367,7 +370,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain) + BUG_ON(domain == NULL); + WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP); + +- virq = irq_alloc_desc_from(1, 0); ++ virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node)); + if (!virq) { + pr_debug("create_direct virq allocation failed\n"); + return 0; +@@ -433,9 +436,9 @@ unsigned int irq_create_mapping(struct irq_domain *domain, + hint = hwirq % nr_irqs; + if (hint == 0) + hint++; +- virq = irq_alloc_desc_from(hint, 0); ++ virq = irq_alloc_desc_from(hint, of_node_to_nid(domain->of_node)); + if (virq <= 0) +- virq = irq_alloc_desc_from(1, 0); ++ virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node)); + if (virq <= 0) { + pr_debug("-> virq allocation failed\n"); + return 0; +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0018-irqdomain-Remove-unnecessary-test-for-IRQ_DOMAIN_MAP.patch b/patches.marzen/0018-irqdomain-Remove-unnecessary-test-for-IRQ_DOMAIN_MAP.patch new file mode 100644 index 0000000000000..4e4191254c415 --- /dev/null +++ b/patches.marzen/0018-irqdomain-Remove-unnecessary-test-for-IRQ_DOMAIN_MAP.patch @@ -0,0 +1,39 @@ +From e023d517b8a6bdbb4083914ec6519fa6486d437d Mon Sep 17 00:00:00 2001 +From: Grant Likely <grant.likely@secretlab.ca> +Date: Sun, 3 Jun 2012 22:04:35 -0700 +Subject: irqdomain: Remove unnecessary test for IRQ_DOMAIN_MAP_LEGACY + +Where irq_domain_associate() is called in irq_create_mapping, there is +no need to test for IRQ_DOMAIN_MAP_LEGACY because it is already tested +for earlier in the routine. + +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +Cc: Paul Mundt <lethal@linux-sh.org> +Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: Rob Herring <rob.herring@calxeda.com> + +(cherry picked from commit 732557047128e5c200c3590efba39f10ac46bcb2) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + kernel/irq/irqdomain.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 79ae0eb..b1f774c 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -445,8 +445,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain, + } + + if (irq_setup_virq(domain, virq, hwirq)) { +- if (domain->revmap_type != IRQ_DOMAIN_MAP_LEGACY) +- irq_free_desc(virq); ++ irq_free_desc(virq); + return 0; + } + +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0019-irqdomain-Make-ops-map-hook-optional.patch b/patches.marzen/0019-irqdomain-Make-ops-map-hook-optional.patch new file mode 100644 index 0000000000000..6cb797bf1e7b1 --- /dev/null +++ b/patches.marzen/0019-irqdomain-Make-ops-map-hook-optional.patch @@ -0,0 +1,69 @@ +From 421754810bdf0283c6f75bffdc96a0795bdf340d Mon Sep 17 00:00:00 2001 +From: Grant Likely <grant.likely@secretlab.ca> +Date: Sun, 3 Jun 2012 22:04:39 -0700 +Subject: irqdomain: Make ops->map hook optional + +There isn't a really compelling reason to force ->map to be populated, +so allow it to be left unset. + +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> +Cc: Paul Mundt <lethal@linux-sh.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: Rob Herring <rob.herring@calxeda.com> +(cherry picked from commit aed98048bd1c83469d96932c1901e867d9ba519a) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + kernel/irq/irqdomain.c | 14 ++++---------- + 1 file changed, 4 insertions(+), 10 deletions(-) + +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index b1f774c..d3968e9 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -205,7 +205,8 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, + * one can then use irq_create_mapping() to + * explicitly change them + */ +- ops->map(domain, irq, hwirq); ++ if (ops->map) ++ ops->map(domain, irq, hwirq); + + /* Clear norequest flags */ + irq_clear_status_flags(irq, IRQ_NOREQUEST); +@@ -340,8 +341,8 @@ static int irq_setup_virq(struct irq_domain *domain, unsigned int virq, + + irq_data->hwirq = hwirq; + irq_data->domain = domain; +- if (domain->ops->map(domain, virq, hwirq)) { +- pr_debug("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq); ++ if (domain->ops->map && domain->ops->map(domain, virq, hwirq)) { ++ pr_err("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq); + irq_data->domain = NULL; + irq_data->hwirq = 0; + return -1; +@@ -763,12 +764,6 @@ static int __init irq_debugfs_init(void) + __initcall(irq_debugfs_init); + #endif /* CONFIG_IRQ_DOMAIN_DEBUG */ + +-static int irq_domain_simple_map(struct irq_domain *d, unsigned int irq, +- irq_hw_number_t hwirq) +-{ +- return 0; +-} +- + /** + * irq_domain_xlate_onecell() - Generic xlate for direct one cell bindings + * +@@ -831,7 +826,6 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d, + EXPORT_SYMBOL_GPL(irq_domain_xlate_onetwocell); + + const struct irq_domain_ops irq_domain_simple_ops = { +- .map = irq_domain_simple_map, + .xlate = irq_domain_xlate_onetwocell, + }; + EXPORT_SYMBOL_GPL(irq_domain_simple_ops); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0020-irq_domain-Standardise-legacy-linear-domain-selectio.patch b/patches.marzen/0020-irq_domain-Standardise-legacy-linear-domain-selectio.patch new file mode 100644 index 0000000000000..e395c3d4cf086 --- /dev/null +++ b/patches.marzen/0020-irq_domain-Standardise-legacy-linear-domain-selectio.patch @@ -0,0 +1,109 @@ +From c9055637ff0ca4029e5bf18053b65172b27f63b0 Mon Sep 17 00:00:00 2001 +From: Mark Brown <broonie@opensource.wolfsonmicro.com> +Date: Thu, 5 Jul 2012 12:19:19 +0100 +Subject: irq_domain: Standardise legacy/linear domain selection + +A large proportion of interrupt controllers that support legacy mappings +do so because non-DT systems need to use fixed IRQ numbers when registering +devices via buses but can otherwise use a linear mapping. The interrupt +controller itself typically is not affected by the mapping used and best +practice is to use a linear mapping where possible so drivers frequently +select at runtime depending on if a legacy range has been allocated to +them. + +Standardise this behaviour by providing irq_domain_register_simple() which +will allocate a linear mapping unless a positive first_irq is provided in +which case it will fall back to a legacy mapping. This helps make best +practice for irq_domain adoption clearer. + +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +(cherry picked from commit 781d0f46d81e2c26c70649903b503bcfe817efc8) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + Documentation/IRQ-domain.txt | 5 +++++ + include/linux/irqdomain.h | 5 +++++ + kernel/irq/irqdomain.c | 30 ++++++++++++++++++++++++++++++ + 3 files changed, 40 insertions(+) + +diff --git a/Documentation/IRQ-domain.txt b/Documentation/IRQ-domain.txt +index 27dcaab..1401cec 100644 +--- a/Documentation/IRQ-domain.txt ++++ b/Documentation/IRQ-domain.txt +@@ -93,6 +93,7 @@ Linux IRQ number into the hardware. + Most drivers cannot use this mapping. + + ==== Legacy ==== ++irq_domain_add_simple() + irq_domain_add_legacy() + irq_domain_add_legacy_isa() + +@@ -115,3 +116,7 @@ The legacy map should only be used if fixed IRQ mappings must be + supported. For example, ISA controllers would use the legacy map for + mapping Linux IRQs 0-15 so that existing ISA drivers get the correct IRQ + numbers. ++ ++Most users of legacy mappings should use irq_domain_add_simple() which ++will use a legacy domain only if an IRQ range is supplied by the ++system and will otherwise use a linear domain mapping. +diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h +index 5abb533..17b60be 100644 +--- a/include/linux/irqdomain.h ++++ b/include/linux/irqdomain.h +@@ -112,6 +112,11 @@ struct irq_domain { + }; + + #ifdef CONFIG_IRQ_DOMAIN ++struct irq_domain *irq_domain_add_simple(struct device_node *of_node, ++ unsigned int size, ++ unsigned int first_irq, ++ const struct irq_domain_ops *ops, ++ void *host_data); + struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, + unsigned int size, + unsigned int first_irq, +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index d3968e9..0c51958 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -140,6 +140,36 @@ static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain, + } + + /** ++ * irq_domain_add_simple() - Allocate and register a simple irq_domain. ++ * @of_node: pointer to interrupt controller's device tree node. ++ * @size: total number of irqs in mapping ++ * @first_irq: first number of irq block assigned to the domain ++ * @ops: map/unmap domain callbacks ++ * @host_data: Controller private data pointer ++ * ++ * Allocates a legacy irq_domain if irq_base is positive or a linear ++ * domain otherwise. ++ * ++ * This is intended to implement the expected behaviour for most ++ * interrupt controllers which is that a linear mapping should ++ * normally be used unless the system requires a legacy mapping in ++ * order to support supplying interrupt numbers during non-DT ++ * registration of devices. ++ */ ++struct irq_domain *irq_domain_add_simple(struct device_node *of_node, ++ unsigned int size, ++ unsigned int first_irq, ++ const struct irq_domain_ops *ops, ++ void *host_data) ++{ ++ if (first_irq > 0) ++ return irq_domain_add_legacy(of_node, size, first_irq, 0, ++ ops, host_data); ++ else ++ return irq_domain_add_linear(of_node, size, ops, host_data); ++} ++ ++/** + * irq_domain_add_legacy() - Allocate and register a legacy revmap irq_domain. + * @of_node: pointer to interrupt controller's device tree node. + * @size: total number of irqs in legacy mapping +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0021-irq_domain-correct-a-minor-wrong-comment-for-linear-.patch b/patches.marzen/0021-irq_domain-correct-a-minor-wrong-comment-for-linear-.patch new file mode 100644 index 0000000000000..fa0ed49f306f3 --- /dev/null +++ b/patches.marzen/0021-irq_domain-correct-a-minor-wrong-comment-for-linear-.patch @@ -0,0 +1,32 @@ +From 709c8d22171cc90cc30e4528312bcc0e31b870b2 Mon Sep 17 00:00:00 2001 +From: Dong Aisheng <dong.aisheng@linaro.org> +Date: Wed, 20 Jun 2012 17:00:30 +0800 +Subject: irq_domain: correct a minor wrong comment for linear revmap + +The revmap type should be linear for irq_domain_add_linear function. + +Signed-off-by: Dong Aisheng <dong.aisheng@linaro.org> +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +(cherry picked from commit 22076c7712be29a602de45b1c573f31adbd428a9) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + kernel/irq/irqdomain.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 0c51958..622fdf4 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -248,7 +248,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, + EXPORT_SYMBOL_GPL(irq_domain_add_legacy); + + /** +- * irq_domain_add_linear() - Allocate and register a legacy revmap irq_domain. ++ * irq_domain_add_linear() - Allocate and register a linear revmap irq_domain. + * @of_node: pointer to interrupt controller's device tree node. + * @size: Number of interrupts in the domain. + * @ops: map/unmap domain callbacks +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0022-irqdomain-Always-update-revmap-when-setting-up-a-vir.patch b/patches.marzen/0022-irqdomain-Always-update-revmap-when-setting-up-a-vir.patch new file mode 100644 index 0000000000000..639979c989882 --- /dev/null +++ b/patches.marzen/0022-irqdomain-Always-update-revmap-when-setting-up-a-vir.patch @@ -0,0 +1,63 @@ +From 077e92f0d6cc5991a052116eb8d66539dd49a995 Mon Sep 17 00:00:00 2001 +From: Grant Likely <grant.likely@secretlab.ca> +Date: Sun, 3 Jun 2012 22:04:36 -0700 +Subject: irqdomain: Always update revmap when setting up a virq + +At irq_setup_virq() time all of the data needed to update the reverse +map is available, but the current code ignores it and relies upon the +slow path to insert revmap records. This patch adds revmap updating +to the setup path so the slow path will no longer be necessary. + +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +Cc: Paul Mundt <lethal@linux-sh.org> +Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: Rob Herring <rob.herring@calxeda.com> +(cherry picked from commit 2a71a1a9da40dfbd5b23d4312aa1641385581f4a) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/powerpc/sysdev/xics/xics-common.c | 3 --- + kernel/irq/irqdomain.c | 12 ++++++++++++ + 2 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c +index cd1d18d..9049d9f 100644 +--- a/arch/powerpc/sysdev/xics/xics-common.c ++++ b/arch/powerpc/sysdev/xics/xics-common.c +@@ -329,9 +329,6 @@ static int xics_host_map(struct irq_domain *h, unsigned int virq, + + pr_devel("xics: map virq %d, hwirq 0x%lx\n", virq, hw); + +- /* Insert the interrupt mapping into the radix tree for fast lookup */ +- irq_radix_revmap_insert(xics_host, virq, hw); +- + /* They aren't all level sensitive but we just don't really know */ + irq_set_status_flags(virq, IRQ_LEVEL); + +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 622fdf4..648177c 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -378,6 +378,18 @@ static int irq_setup_virq(struct irq_domain *domain, unsigned int virq, + return -1; + } + ++ switch (domain->revmap_type) { ++ case IRQ_DOMAIN_MAP_LINEAR: ++ if (hwirq < domain->revmap_data.linear.size) ++ domain->revmap_data.linear.revmap[hwirq] = virq; ++ break; ++ case IRQ_DOMAIN_MAP_TREE: ++ mutex_lock(&revmap_trees_mutex); ++ irq_radix_revmap_insert(domain, virq, hwirq); ++ mutex_unlock(&revmap_trees_mutex); ++ break; ++ } ++ + irq_clear_status_flags(virq, IRQ_NOREQUEST); + + return 0; +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0023-irqdomain-Split-disassociating-code-into-separate-fu.patch b/patches.marzen/0023-irqdomain-Split-disassociating-code-into-separate-fu.patch new file mode 100644 index 0000000000000..e3a482d418298 --- /dev/null +++ b/patches.marzen/0023-irqdomain-Split-disassociating-code-into-separate-fu.patch @@ -0,0 +1,125 @@ +From d3a8f8cf4ad2e5416f53db8963f3ff153feec161 Mon Sep 17 00:00:00 2001 +From: Grant Likely <grant.likely@secretlab.ca> +Date: Sun, 3 Jun 2012 22:04:35 -0700 +Subject: irqdomain: Split disassociating code into separate function + +This patch moves the irq disassociation code out into a separate +function in preparation to extend irq_setup_virq to handle multiple +irqs and rename it for use by interrupt controller drivers. The new +function will be used by irq_setup_virq() in its error path. + +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> +Cc: Paul Mundt <lethal@linux-sh.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: Rob Herring <rob.herring@calxeda.com> +(cherry picked from commit 913af2070731bfc1bd39bb35c5cd2fd66f5eff12) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + kernel/irq/irqdomain.c | 75 +++++++++++++++++++++++++++++++------------------- + 1 file changed, 47 insertions(+), 28 deletions(-) + +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 648177c..091732c 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -364,6 +364,52 @@ void irq_set_default_host(struct irq_domain *domain) + } + EXPORT_SYMBOL_GPL(irq_set_default_host); + ++static void irq_domain_disassociate_many(struct irq_domain *domain, ++ unsigned int irq_base, int count) ++{ ++ /* ++ * disassociate in reverse order; ++ * not strictly necessary, but nice for unwinding ++ */ ++ while (count--) { ++ int irq = irq_base + count; ++ struct irq_data *irq_data = irq_get_irq_data(irq); ++ irq_hw_number_t hwirq = irq_data->hwirq; ++ ++ if (WARN_ON(!irq_data || irq_data->domain != domain)) ++ continue; ++ ++ irq_set_status_flags(irq, IRQ_NOREQUEST); ++ ++ /* remove chip and handler */ ++ irq_set_chip_and_handler(irq, NULL, NULL); ++ ++ /* Make sure it's completed */ ++ synchronize_irq(irq); ++ ++ /* Tell the PIC about it */ ++ if (domain->ops->unmap) ++ domain->ops->unmap(domain, irq); ++ smp_mb(); ++ ++ irq_data->domain = NULL; ++ irq_data->hwirq = 0; ++ ++ /* Clear reverse map */ ++ switch(domain->revmap_type) { ++ case IRQ_DOMAIN_MAP_LINEAR: ++ if (hwirq < domain->revmap_data.linear.size) ++ domain->revmap_data.linear.revmap[hwirq] = 0; ++ break; ++ case IRQ_DOMAIN_MAP_TREE: ++ mutex_lock(&revmap_trees_mutex); ++ radix_tree_delete(&domain->revmap_data.tree, hwirq); ++ mutex_unlock(&revmap_trees_mutex); ++ break; ++ } ++ } ++} ++ + static int irq_setup_virq(struct irq_domain *domain, unsigned int virq, + irq_hw_number_t hwirq) + { +@@ -556,7 +602,6 @@ void irq_dispose_mapping(unsigned int virq) + { + struct irq_data *irq_data = irq_get_irq_data(virq); + struct irq_domain *domain; +- irq_hw_number_t hwirq; + + if (!virq || !irq_data) + return; +@@ -569,33 +614,7 @@ void irq_dispose_mapping(unsigned int virq) + if (domain->revmap_type == IRQ_DOMAIN_MAP_LEGACY) + return; + +- irq_set_status_flags(virq, IRQ_NOREQUEST); +- +- /* remove chip and handler */ +- irq_set_chip_and_handler(virq, NULL, NULL); +- +- /* Make sure it's completed */ +- synchronize_irq(virq); +- +- /* Tell the PIC about it */ +- if (domain->ops->unmap) +- domain->ops->unmap(domain, virq); +- smp_mb(); +- +- /* Clear reverse map */ +- hwirq = irq_data->hwirq; +- switch(domain->revmap_type) { +- case IRQ_DOMAIN_MAP_LINEAR: +- if (hwirq < domain->revmap_data.linear.size) +- domain->revmap_data.linear.revmap[hwirq] = 0; +- break; +- case IRQ_DOMAIN_MAP_TREE: +- mutex_lock(&revmap_trees_mutex); +- radix_tree_delete(&domain->revmap_data.tree, hwirq); +- mutex_unlock(&revmap_trees_mutex); +- break; +- } +- ++ irq_domain_disassociate_many(domain, virq, 1); + irq_free_desc(virq); + } + EXPORT_SYMBOL_GPL(irq_dispose_mapping); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0024-irqdomain-Support-for-static-IRQ-mapping-and-associa.patch b/patches.marzen/0024-irqdomain-Support-for-static-IRQ-mapping-and-associa.patch new file mode 100644 index 0000000000000..f9f8697cbf9e5 --- /dev/null +++ b/patches.marzen/0024-irqdomain-Support-for-static-IRQ-mapping-and-associa.patch @@ -0,0 +1,239 @@ +From 5f4e2248df9a3128a3e81755f87b12dd211ead30 Mon Sep 17 00:00:00 2001 +From: Grant Likely <grant.likely@secretlab.ca> +Date: Sun, 17 Jun 2012 16:17:04 -0600 +Subject: irqdomain: Support for static IRQ mapping and association. + +This adds a new strict mapping API for supporting creation of linux IRQs +at existing positions within the domain. The new routines are as follows: + +For dynamic allocation and insertion to specified ranges: + + - irq_create_identity_mapping() + - irq_create_strict_mappings() + +These will allocate and associate a range of linux IRQs at the specified +location. This can be used by controllers that have their own static linux IRQ +definitions to map a hwirq range to, as well as for platforms that wish to +establish 1:1 identity mapping between linux and hwirq space. + +For insertion to specified ranges by platforms that do their own irq_desc +management: + + - irq_domain_associate() + - irq_domain_associate_many() + +These in turn call back in to the domain's ->map() routine, for further +processing by the platform. Disassociation of IRQs get handled through +irq_dispose_mapping() as normal. + +With these in place it should be possible to begin migration of legacy IRQ +domains to linear ones, without requiring special handling for static vs +dynamic IRQ definitions in DT vs non-DT paths. This also makes it possible +for domains with static mappings to adopt whichever tree model best fits +their needs, rather than simply restricting them to linear revmaps. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +[grant.likely: Reorganized irq_domain_associate{,_many} to have all logic in one place] +[grant.likely: Add error checking for unallocated irq_descs at associate time] +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: Rob Herring <rob.herring@calxeda.com>(cherry picked from commit 98aa468e045a0091a7c34d9f5205a629634fabf4) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/irqdomain.h | 19 ++++++++ + kernel/irq/irqdomain.c | 113 ++++++++++++++++++++++++++++++++++++---------- + 2 files changed, 107 insertions(+), 25 deletions(-) + +diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h +index 17b60be..eab8a0e 100644 +--- a/include/linux/irqdomain.h ++++ b/include/linux/irqdomain.h +@@ -149,12 +149,31 @@ static inline struct irq_domain *irq_domain_add_legacy_isa( + + extern void irq_domain_remove(struct irq_domain *host); + ++extern int irq_domain_associate_many(struct irq_domain *domain, ++ unsigned int irq_base, ++ irq_hw_number_t hwirq_base, int count); ++static inline int irq_domain_associate(struct irq_domain *domain, unsigned int irq, ++ irq_hw_number_t hwirq) ++{ ++ return irq_domain_associate_many(domain, irq, hwirq, 1); ++} ++ + extern unsigned int irq_create_mapping(struct irq_domain *host, + irq_hw_number_t hwirq); + extern void irq_dispose_mapping(unsigned int virq); + extern unsigned int irq_find_mapping(struct irq_domain *host, + irq_hw_number_t hwirq); + extern unsigned int irq_create_direct_mapping(struct irq_domain *host); ++extern int irq_create_strict_mappings(struct irq_domain *domain, ++ unsigned int irq_base, ++ irq_hw_number_t hwirq_base, int count); ++ ++static inline int irq_create_identity_mapping(struct irq_domain *host, ++ irq_hw_number_t hwirq) ++{ ++ return irq_create_strict_mappings(host, hwirq, hwirq, 1); ++} ++ + extern void irq_radix_revmap_insert(struct irq_domain *host, unsigned int virq, + irq_hw_number_t hwirq); + extern unsigned int irq_radix_revmap_lookup(struct irq_domain *host, +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 091732c..a07d924 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -410,36 +410,61 @@ static void irq_domain_disassociate_many(struct irq_domain *domain, + } + } + +-static int irq_setup_virq(struct irq_domain *domain, unsigned int virq, +- irq_hw_number_t hwirq) ++int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base, ++ irq_hw_number_t hwirq_base, int count) + { +- struct irq_data *irq_data = irq_get_irq_data(virq); ++ unsigned int virq = irq_base; ++ irq_hw_number_t hwirq = hwirq_base; ++ int i; + +- irq_data->hwirq = hwirq; +- irq_data->domain = domain; +- if (domain->ops->map && domain->ops->map(domain, virq, hwirq)) { +- pr_err("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq); +- irq_data->domain = NULL; +- irq_data->hwirq = 0; +- return -1; +- } ++ pr_debug("%s(%s, irqbase=%i, hwbase=%i, count=%i)\n", __func__, ++ of_node_full_name(domain->of_node), irq_base, (int)hwirq_base, count); + +- switch (domain->revmap_type) { +- case IRQ_DOMAIN_MAP_LINEAR: +- if (hwirq < domain->revmap_data.linear.size) +- domain->revmap_data.linear.revmap[hwirq] = virq; +- break; +- case IRQ_DOMAIN_MAP_TREE: +- mutex_lock(&revmap_trees_mutex); +- irq_radix_revmap_insert(domain, virq, hwirq); +- mutex_unlock(&revmap_trees_mutex); +- break; +- } ++ for (i = 0; i < count; i++) { ++ struct irq_data *irq_data = irq_get_irq_data(virq + i); ++ ++ if (WARN(!irq_data, "error: irq_desc not allocated; " ++ "irq=%i hwirq=0x%x\n", virq + i, (int)hwirq + i)) ++ return -EINVAL; ++ if (WARN(irq_data->domain, "error: irq_desc already associated; " ++ "irq=%i hwirq=0x%x\n", virq + i, (int)hwirq + i)) ++ return -EINVAL; ++ }; ++ ++ for (i = 0; i < count; i++, virq++, hwirq++) { ++ struct irq_data *irq_data = irq_get_irq_data(virq); ++ ++ irq_data->hwirq = hwirq; ++ irq_data->domain = domain; ++ if (domain->ops->map && domain->ops->map(domain, virq, hwirq)) { ++ pr_err("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq); ++ irq_data->domain = NULL; ++ irq_data->hwirq = 0; ++ goto err_unmap; ++ } ++ ++ switch (domain->revmap_type) { ++ case IRQ_DOMAIN_MAP_LINEAR: ++ if (hwirq < domain->revmap_data.linear.size) ++ domain->revmap_data.linear.revmap[hwirq] = virq; ++ break; ++ case IRQ_DOMAIN_MAP_TREE: ++ mutex_lock(&revmap_trees_mutex); ++ irq_radix_revmap_insert(domain, virq, hwirq); ++ mutex_unlock(&revmap_trees_mutex); ++ break; ++ } + +- irq_clear_status_flags(virq, IRQ_NOREQUEST); ++ irq_clear_status_flags(virq, IRQ_NOREQUEST); ++ } + + return 0; ++ ++ err_unmap: ++ irq_domain_disassociate_many(domain, irq_base, i); ++ return -EINVAL; + } ++EXPORT_SYMBOL_GPL(irq_domain_associate_many); + + /** + * irq_create_direct_mapping() - Allocate an irq for direct mapping +@@ -472,7 +497,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain) + } + pr_debug("create_direct obtained virq %d\n", virq); + +- if (irq_setup_virq(domain, virq, virq)) { ++ if (irq_domain_associate(domain, virq, virq)) { + irq_free_desc(virq); + return 0; + } +@@ -533,7 +558,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain, + return 0; + } + +- if (irq_setup_virq(domain, virq, hwirq)) { ++ if (irq_domain_associate(domain, virq, hwirq)) { + irq_free_desc(virq); + return 0; + } +@@ -545,6 +570,44 @@ unsigned int irq_create_mapping(struct irq_domain *domain, + } + EXPORT_SYMBOL_GPL(irq_create_mapping); + ++/** ++ * irq_create_strict_mappings() - Map a range of hw irqs to fixed linux irqs ++ * @domain: domain owning the interrupt range ++ * @irq_base: beginning of linux IRQ range ++ * @hwirq_base: beginning of hardware IRQ range ++ * @count: Number of interrupts to map ++ * ++ * This routine is used for allocating and mapping a range of hardware ++ * irqs to linux irqs where the linux irq numbers are at pre-defined ++ * locations. For use by controllers that already have static mappings ++ * to insert in to the domain. ++ * ++ * Non-linear users can use irq_create_identity_mapping() for IRQ-at-a-time ++ * domain insertion. ++ * ++ * 0 is returned upon success, while any failure to establish a static ++ * mapping is treated as an error. ++ */ ++int irq_create_strict_mappings(struct irq_domain *domain, unsigned int irq_base, ++ irq_hw_number_t hwirq_base, int count) ++{ ++ int ret; ++ ++ ret = irq_alloc_descs(irq_base, irq_base, count, ++ of_node_to_nid(domain->of_node)); ++ if (unlikely(ret < 0)) ++ return ret; ++ ++ ret = irq_domain_associate_many(domain, irq_base, hwirq_base, count); ++ if (unlikely(ret < 0)) { ++ irq_free_descs(irq_base, count); ++ return ret; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(irq_create_strict_mappings); ++ + unsigned int irq_create_of_mapping(struct device_node *controller, + const u32 *intspec, unsigned int intsize) + { +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0025-irqdomain-Eliminate-dedicated-radix-lookup-functions.patch b/patches.marzen/0025-irqdomain-Eliminate-dedicated-radix-lookup-functions.patch new file mode 100644 index 0000000000000..e4d1ae380517d --- /dev/null +++ b/patches.marzen/0025-irqdomain-Eliminate-dedicated-radix-lookup-functions.patch @@ -0,0 +1,146 @@ +From 5b89c7072aeb8b3f6f16a675fafb342c2dd3e1b6 Mon Sep 17 00:00:00 2001 +From: Grant Likely <grant.likely@secretlab.ca> +Date: Sun, 3 Jun 2012 22:04:37 -0700 +Subject: irqdomain: Eliminate dedicated radix lookup functions + +In preparation to remove the slow revmap path, eliminate the public +radix revmap lookup functions. This simplifies the code and makes the +slowpath removal patch a lot simpler. + +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +Cc: Paul Mundt <lethal@linux-sh.org> +Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: Rob Herring <rob.herring@calxeda.com> +(cherry picked from commit d6b0d1f7058f7cf818138cd7fd116dca3f3576d9) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/powerpc/sysdev/xics/icp-hv.c | 2 +- + arch/powerpc/sysdev/xics/icp-native.c | 2 +- + include/linux/irqdomain.h | 4 --- + kernel/irq/irqdomain.c | 60 +---------------------------------- + 4 files changed, 3 insertions(+), 65 deletions(-) + +diff --git a/arch/powerpc/sysdev/xics/icp-hv.c b/arch/powerpc/sysdev/xics/icp-hv.c +index 762c5ca..df0fc58 100644 +--- a/arch/powerpc/sysdev/xics/icp-hv.c ++++ b/arch/powerpc/sysdev/xics/icp-hv.c +@@ -115,7 +115,7 @@ static unsigned int icp_hv_get_irq(void) + if (vec == XICS_IRQ_SPURIOUS) + return NO_IRQ; + +- irq = irq_radix_revmap_lookup(xics_host, vec); ++ irq = irq_find_mapping(xics_host, vec); + if (likely(irq != NO_IRQ)) { + xics_push_cppr(vec); + return irq; +diff --git a/arch/powerpc/sysdev/xics/icp-native.c b/arch/powerpc/sysdev/xics/icp-native.c +index 4c79b6f..48861d3 100644 +--- a/arch/powerpc/sysdev/xics/icp-native.c ++++ b/arch/powerpc/sysdev/xics/icp-native.c +@@ -119,7 +119,7 @@ static unsigned int icp_native_get_irq(void) + if (vec == XICS_IRQ_SPURIOUS) + return NO_IRQ; + +- irq = irq_radix_revmap_lookup(xics_host, vec); ++ irq = irq_find_mapping(xics_host, vec); + if (likely(irq != NO_IRQ)) { + xics_push_cppr(vec); + return irq; +diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h +index eab8a0e..0d5b17b 100644 +--- a/include/linux/irqdomain.h ++++ b/include/linux/irqdomain.h +@@ -174,10 +174,6 @@ static inline int irq_create_identity_mapping(struct irq_domain *host, + return irq_create_strict_mappings(host, hwirq, hwirq, 1); + } + +-extern void irq_radix_revmap_insert(struct irq_domain *host, unsigned int virq, +- irq_hw_number_t hwirq); +-extern unsigned int irq_radix_revmap_lookup(struct irq_domain *host, +- irq_hw_number_t hwirq); + extern unsigned int irq_linear_revmap(struct irq_domain *host, + irq_hw_number_t hwirq); + +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index a07d924..f540bb1 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -450,7 +450,7 @@ int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base, + break; + case IRQ_DOMAIN_MAP_TREE: + mutex_lock(&revmap_trees_mutex); +- irq_radix_revmap_insert(domain, virq, hwirq); ++ radix_tree_insert(&domain->revmap_data.tree, hwirq, irq_data); + mutex_unlock(&revmap_trees_mutex); + break; + } +@@ -724,64 +724,6 @@ unsigned int irq_find_mapping(struct irq_domain *domain, + EXPORT_SYMBOL_GPL(irq_find_mapping); + + /** +- * irq_radix_revmap_lookup() - Find a linux irq from a hw irq number. +- * @domain: domain owning this hardware interrupt +- * @hwirq: hardware irq number in that domain space +- * +- * This is a fast path, for use by irq controller code that uses radix tree +- * revmaps +- */ +-unsigned int irq_radix_revmap_lookup(struct irq_domain *domain, +- irq_hw_number_t hwirq) +-{ +- struct irq_data *irq_data; +- +- if (WARN_ON_ONCE(domain->revmap_type != IRQ_DOMAIN_MAP_TREE)) +- return irq_find_mapping(domain, hwirq); +- +- /* +- * Freeing an irq can delete nodes along the path to +- * do the lookup via call_rcu. +- */ +- rcu_read_lock(); +- irq_data = radix_tree_lookup(&domain->revmap_data.tree, hwirq); +- rcu_read_unlock(); +- +- /* +- * If found in radix tree, then fine. +- * Else fallback to linear lookup - this should not happen in practice +- * as it means that we failed to insert the node in the radix tree. +- */ +- return irq_data ? irq_data->irq : irq_find_mapping(domain, hwirq); +-} +-EXPORT_SYMBOL_GPL(irq_radix_revmap_lookup); +- +-/** +- * irq_radix_revmap_insert() - Insert a hw irq to linux irq number mapping. +- * @domain: domain owning this hardware interrupt +- * @virq: linux irq number +- * @hwirq: hardware irq number in that domain space +- * +- * This is for use by irq controllers that use a radix tree reverse +- * mapping for fast lookup. +- */ +-void irq_radix_revmap_insert(struct irq_domain *domain, unsigned int virq, +- irq_hw_number_t hwirq) +-{ +- struct irq_data *irq_data = irq_get_irq_data(virq); +- +- if (WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_TREE)) +- return; +- +- if (virq) { +- mutex_lock(&revmap_trees_mutex); +- radix_tree_insert(&domain->revmap_data.tree, hwirq, irq_data); +- mutex_unlock(&revmap_trees_mutex); +- } +-} +-EXPORT_SYMBOL_GPL(irq_radix_revmap_insert); +- +-/** + * irq_linear_revmap() - Find a linux irq from a hw irq number. + * @domain: domain owning this hardware interrupt + * @hwirq: hardware irq number in that domain space +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0026-irqdomain-Fix-irq_create_direct_mapping-to-test-irq_.patch b/patches.marzen/0026-irqdomain-Fix-irq_create_direct_mapping-to-test-irq_.patch new file mode 100644 index 0000000000000..6aa1f06bf98f7 --- /dev/null +++ b/patches.marzen/0026-irqdomain-Fix-irq_create_direct_mapping-to-test-irq_.patch @@ -0,0 +1,39 @@ +From 669724cfa76709814c46bac8ba50f1a52d15ffd7 Mon Sep 17 00:00:00 2001 +From: Grant Likely <grant.likely@secretlab.ca> +Date: Sun, 3 Jun 2012 22:04:38 -0700 +Subject: irqdomain: Fix irq_create_direct_mapping() to test irq_domain type. + +irq_create_direct_mapping can only be used with the NOMAP type. Make +the function test to ensure it is passed the correct type of +irq_domain. + +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +Cc: Paul Mundt <lethal@linux-sh.org> +Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: Rob Herring <rob.herring@calxeda.com> +(cherry picked from commit 9844a5524ec532aee826c35e3031637c7fc8287b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + kernel/irq/irqdomain.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index f540bb1..c0e638b 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -481,8 +481,8 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain) + if (domain == NULL) + domain = irq_default_domain; + +- BUG_ON(domain == NULL); +- WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP); ++ if (WARN_ON(!domain || domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP)) ++ return 0; + + virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node)); + if (!virq) { +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0027-irqdomain-eliminate-slow-path-revmap-lookups.patch b/patches.marzen/0027-irqdomain-eliminate-slow-path-revmap-lookups.patch new file mode 100644 index 0000000000000..d416e80d713d4 --- /dev/null +++ b/patches.marzen/0027-irqdomain-eliminate-slow-path-revmap-lookups.patch @@ -0,0 +1,142 @@ +From 026250e1fad07349b34213260492cecee3b32eae Mon Sep 17 00:00:00 2001 +From: Grant Likely <grant.likely@secretlab.ca> +Date: Sun, 3 Jun 2012 22:04:39 -0700 +Subject: irqdomain: eliminate slow-path revmap lookups + +With the current state of irq_domain, the reverse map is always updated +when new IRQs get mapped. This means that the irq_find_mapping() function +can be simplified to execute the revmap lookup functions unconditionally + +This patch adds lookup functions for the revmaps that don't yet have one +and removes the slow path lookup code path. + +v8: Broke out unrelated changes into separate patches. Rebased on Paul's irq + association patches. +v7: Rebased to irqdomain/next for v3.4 and applied before the removal of 'hint' +v6: Remove the slow path entirely. The only place where the slow path + could get called is for a linear mapping if the hwirq number is larger + than the linear revmap size. There shouldn't be any interrupt + controllers that do that. +v5: rewrite to not use a ->revmap() callback. It is simpler, smaller, + safer and faster to open code each of the revmap lookups directly into + irq_find_mapping() via a switch statement. +v4: Fix build failure on incorrect variable reference. + +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: Milton Miller <miltonm@bga.com> +Cc: Paul Mundt <lethal@linux-sh.org> +Cc: Rob Herring <rob.herring@calxeda.com> +(cherry picked from commit 4c0946c47463defa681b83294383dc996d255bb7) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + kernel/irq/irqdomain.c | 65 +++++++++++++++++++------------------------------- + 1 file changed, 25 insertions(+), 40 deletions(-) + +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index c0e638b..170724a 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -686,16 +686,11 @@ EXPORT_SYMBOL_GPL(irq_dispose_mapping); + * irq_find_mapping() - Find a linux irq from an hw irq number. + * @domain: domain owning this hardware interrupt + * @hwirq: hardware irq number in that domain space +- * +- * This is a slow path, for use by generic code. It's expected that an +- * irq controller implementation directly calls the appropriate low level +- * mapping function. + */ + unsigned int irq_find_mapping(struct irq_domain *domain, + irq_hw_number_t hwirq) + { +- unsigned int i; +- unsigned int hint = hwirq % nr_irqs; ++ struct irq_data *data; + + /* Look for default domain if nececssary */ + if (domain == NULL) +@@ -703,22 +698,25 @@ unsigned int irq_find_mapping(struct irq_domain *domain, + if (domain == NULL) + return 0; + +- /* legacy -> bail early */ +- if (domain->revmap_type == IRQ_DOMAIN_MAP_LEGACY) ++ switch (domain->revmap_type) { ++ case IRQ_DOMAIN_MAP_LEGACY: + return irq_domain_legacy_revmap(domain, hwirq); +- +- /* Slow path does a linear search of the map */ +- if (hint == 0) +- hint = 1; +- i = hint; +- do { +- struct irq_data *data = irq_get_irq_data(i); ++ case IRQ_DOMAIN_MAP_LINEAR: ++ return irq_linear_revmap(domain, hwirq); ++ case IRQ_DOMAIN_MAP_TREE: ++ rcu_read_lock(); ++ data = radix_tree_lookup(&domain->revmap_data.tree, hwirq); ++ rcu_read_unlock(); ++ if (data) ++ return data->irq; ++ break; ++ case IRQ_DOMAIN_MAP_NOMAP: ++ data = irq_get_irq_data(hwirq); + if (data && (data->domain == domain) && (data->hwirq == hwirq)) +- return i; +- i++; +- if (i >= nr_irqs) +- i = 1; +- } while(i != hint); ++ return hwirq; ++ break; ++ } ++ + return 0; + } + EXPORT_SYMBOL_GPL(irq_find_mapping); +@@ -728,32 +726,19 @@ EXPORT_SYMBOL_GPL(irq_find_mapping); + * @domain: domain owning this hardware interrupt + * @hwirq: hardware irq number in that domain space + * +- * This is a fast path, for use by irq controller code that uses linear +- * revmaps. It does fallback to the slow path if the revmap doesn't exist +- * yet and will create the revmap entry with appropriate locking ++ * This is a fast path that can be called directly by irq controller code to ++ * save a handful of instructions. + */ + unsigned int irq_linear_revmap(struct irq_domain *domain, + irq_hw_number_t hwirq) + { +- unsigned int *revmap; ++ BUG_ON(domain->revmap_type != IRQ_DOMAIN_MAP_LINEAR); + +- if (WARN_ON_ONCE(domain->revmap_type != IRQ_DOMAIN_MAP_LINEAR)) +- return irq_find_mapping(domain, hwirq); +- +- /* Check revmap bounds */ +- if (unlikely(hwirq >= domain->revmap_data.linear.size)) +- return irq_find_mapping(domain, hwirq); +- +- /* Check if revmap was allocated */ +- revmap = domain->revmap_data.linear.revmap; +- if (unlikely(revmap == NULL)) +- return irq_find_mapping(domain, hwirq); +- +- /* Fill up revmap with slow path if no mapping found */ +- if (unlikely(!revmap[hwirq])) +- revmap[hwirq] = irq_find_mapping(domain, hwirq); ++ /* Check revmap bounds; complain if exceeded */ ++ if (WARN_ON(hwirq >= domain->revmap_data.linear.size)) ++ return 0; + +- return revmap[hwirq]; ++ return domain->revmap_data.linear.revmap[hwirq]; + } + EXPORT_SYMBOL_GPL(irq_linear_revmap); + +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0028-irqdomain-Improve-diagnostics-when-a-domain-mapping-.patch b/patches.marzen/0028-irqdomain-Improve-diagnostics-when-a-domain-mapping-.patch new file mode 100644 index 0000000000000..feaa1b5eae03d --- /dev/null +++ b/patches.marzen/0028-irqdomain-Improve-diagnostics-when-a-domain-mapping-.patch @@ -0,0 +1,56 @@ +From 6a3157b4d4a0df782066f610807c4288ed52ec43 Mon Sep 17 00:00:00 2001 +From: Mark Brown <broonie@opensource.wolfsonmicro.com> +Date: Fri, 20 Jul 2012 10:33:19 +0100 +Subject: irqdomain: Improve diagnostics when a domain mapping fails + +When the map operation fails log the error code we get and add a WARN_ON() +so we get a backtrace (which should help work out which interrupt is the +source of the issue). + +Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +Signed-off-by: Grant Likely <grant.likely@secretlab.ca> +(cherry picked from commit f5a1ad057e6da5d0fc9c5677ff44797d193d3e62) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + kernel/irq/irqdomain.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c +index 170724a..49a7772 100644 +--- a/kernel/irq/irqdomain.c ++++ b/kernel/irq/irqdomain.c +@@ -415,7 +415,7 @@ int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base, + { + unsigned int virq = irq_base; + irq_hw_number_t hwirq = hwirq_base; +- int i; ++ int i, ret; + + pr_debug("%s(%s, irqbase=%i, hwbase=%i, count=%i)\n", __func__, + of_node_full_name(domain->of_node), irq_base, (int)hwirq_base, count); +@@ -436,11 +436,16 @@ int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base, + + irq_data->hwirq = hwirq; + irq_data->domain = domain; +- if (domain->ops->map && domain->ops->map(domain, virq, hwirq)) { +- pr_err("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq); +- irq_data->domain = NULL; +- irq_data->hwirq = 0; +- goto err_unmap; ++ if (domain->ops->map) { ++ ret = domain->ops->map(domain, virq, hwirq); ++ if (ret != 0) { ++ pr_err("irq-%i==>hwirq-0x%lx mapping failed: %d\n", ++ virq, hwirq, ret); ++ WARN_ON(1); ++ irq_data->domain = NULL; ++ irq_data->hwirq = 0; ++ goto err_unmap; ++ } + } + + switch (domain->revmap_type) { +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0029-ARM-mach-shmobile-Introduce-INTC_IRQ_PINS_16H.patch b/patches.marzen/0029-ARM-mach-shmobile-Introduce-INTC_IRQ_PINS_16H.patch new file mode 100644 index 0000000000000..755bc2eb6b828 --- /dev/null +++ b/patches.marzen/0029-ARM-mach-shmobile-Introduce-INTC_IRQ_PINS_16H.patch @@ -0,0 +1,83 @@ +From f2f3cb0fe8263325798302e1b431e38cf4e153e8 Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Wed, 28 Mar 2012 19:22:46 +0900 +Subject: ARM: mach-shmobile: Introduce INTC_IRQ_PINS_16H + +Add INTC_IRQ_PINS_16H to allow broken out support of the +the high 16 external interrupt pins. On SoCs with 32 external +interrupt pins the interrupt vectors for the low 16 and the +high 16 interrupt pins are sparesly populated. The low 16 are +at 0x0200 and high 16 are at 0x3200 which with current macros +results in a separation of 384 linux interrupts. This sparse +population makes it unsuitable with a single IRQ domain to +cover the full IRQ range, so this macro breaks out the 32 pins +into two separate 16 bit controllers to allow two independent +INTC instances with two separate IRQ domains. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit d7e7e4ffc64f700e876a9f3b2727febaa2041221) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/include/mach/intc.h | 44 ++++++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + +diff --git a/arch/arm/mach-shmobile/include/mach/intc.h b/arch/arm/mach-shmobile/include/mach/intc.h +index 8b22258..a5603c7 100644 +--- a/arch/arm/mach-shmobile/include/mach/intc.h ++++ b/arch/arm/mach-shmobile/include/mach/intc.h +@@ -142,6 +142,50 @@ static struct intc_desc p ## _desc __initdata = { \ + p ## _sense_registers, p ## _ack_registers) \ + } + ++#define INTC_IRQ_PINS_16H(p, base, vect, str) \ ++ \ ++static struct resource p ## _resources[] __initdata = { \ ++ [0] = { \ ++ .start = base, \ ++ .end = base + 0x64, \ ++ .flags = IORESOURCE_MEM, \ ++ }, \ ++}; \ ++ \ ++enum { \ ++ p ## _UNUSED = 0, \ ++ INTC_IRQ_PINS_ENUM_16H(p), \ ++}; \ ++ \ ++static struct intc_vect p ## _vectors[] __initdata = { \ ++ INTC_IRQ_PINS_VECT_16H(p, vect), \ ++}; \ ++ \ ++static struct intc_mask_reg p ## _mask_registers[] __initdata = { \ ++ INTC_IRQ_PINS_MASK_16H(p, base), \ ++}; \ ++ \ ++static struct intc_prio_reg p ## _prio_registers[] __initdata = { \ ++ INTC_IRQ_PINS_PRIO_16H(p, base), \ ++}; \ ++ \ ++static struct intc_sense_reg p ## _sense_registers[] __initdata = { \ ++ INTC_IRQ_PINS_SENSE_16H(p, base), \ ++}; \ ++ \ ++static struct intc_mask_reg p ## _ack_registers[] __initdata = { \ ++ INTC_IRQ_PINS_ACK_16H(p, base), \ ++}; \ ++ \ ++static struct intc_desc p ## _desc __initdata = { \ ++ .name = str, \ ++ .resource = p ## _resources, \ ++ .num_resources = ARRAY_SIZE(p ## _resources), \ ++ .hw = INTC_HW_DESC(p ## _vectors, NULL, \ ++ p ## _mask_registers, p ## _prio_registers, \ ++ p ## _sense_registers, p ## _ack_registers) \ ++} ++ + #define INTC_IRQ_PINS_32(p, base, vect, str) \ + \ + static struct resource p ## _resources[] __initdata = { \ +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0030-sh-intc-Kill-off-special-reservation-interface.patch b/patches.marzen/0030-sh-intc-Kill-off-special-reservation-interface.patch new file mode 100644 index 0000000000000..9387903484eba --- /dev/null +++ b/patches.marzen/0030-sh-intc-Kill-off-special-reservation-interface.patch @@ -0,0 +1,72 @@ +From cba1bcc0a91c91fb5b503e6a718801a0eca41b3f Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Tue, 22 May 2012 19:07:55 +0900 +Subject: sh: intc: Kill off special reservation interface. + +At present reserving the IRLs in the IRQ bitmap in addition to the +dropping of the legacy IRQ pre-allocation prevent IRL IRQs from being +allocated for the x3proto board. + +The only reason to permit reservations was to lock down possible hardware +vectors prior to dynamic IRQ scanning, but this doesn't matter much given +that the hardware controller configuration is sorted before we get around +to doing any dynamic IRQ allocation anyways. Beyond that, all of the +tables are __init annotated, so quite a bit more work would need to be +done to support reconfiguring things like IRL controllers on the fly, +much more than would ever make it worth the hassle. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 5f19f14fed7786652b9617c633db101d26a42251) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/sh/kernel/cpu/sh4a/setup-shx3.c | 3 --- + drivers/sh/intc/dynamic.c | 8 -------- + include/linux/sh_intc.h | 1 - + 3 files changed, 12 deletions(-) + +diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c +index bb20880..674531e 100644 +--- a/arch/sh/kernel/cpu/sh4a/setup-shx3.c ++++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c +@@ -484,9 +484,6 @@ void __init plat_irq_setup_pins(int mode) + + void __init plat_irq_setup(void) + { +- reserve_intc_vectors(vectors_irq, ARRAY_SIZE(vectors_irq)); +- reserve_intc_vectors(vectors_irl, ARRAY_SIZE(vectors_irl)); +- + register_intc_controller(&intc_desc); + } + +diff --git a/drivers/sh/intc/dynamic.c b/drivers/sh/intc/dynamic.c +index 5fea1ee..14eb01e 100644 +--- a/drivers/sh/intc/dynamic.c ++++ b/drivers/sh/intc/dynamic.c +@@ -55,11 +55,3 @@ void destroy_irq(unsigned int irq) + { + irq_free_desc(irq); + } +- +-void reserve_intc_vectors(struct intc_vect *vectors, unsigned int nr_vecs) +-{ +- int i; +- +- for (i = 0; i < nr_vecs; i++) +- irq_reserve_irq(evt2irq(vectors[i].vect)); +-} +diff --git a/include/linux/sh_intc.h b/include/linux/sh_intc.h +index 6aed080..3238328 100644 +--- a/include/linux/sh_intc.h ++++ b/include/linux/sh_intc.h +@@ -133,7 +133,6 @@ struct intc_desc symbol __initdata = { \ + } + + int register_intc_controller(struct intc_desc *desc); +-void reserve_intc_vectors(struct intc_vect *vectors, unsigned int nr_vecs); + int intc_set_priority(unsigned int irq, unsigned int prio); + int intc_irq_lookup(const char *chipname, intc_enum enum_id); + void intc_finalize(void); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0031-sh-intc-Allocate-subgroup-virq-backing-desc-directly.patch b/patches.marzen/0031-sh-intc-Allocate-subgroup-virq-backing-desc-directly.patch new file mode 100644 index 0000000000000..55c10a8e5d1b4 --- /dev/null +++ b/patches.marzen/0031-sh-intc-Allocate-subgroup-virq-backing-desc-directly.patch @@ -0,0 +1,41 @@ +From 42251498a3ddced1d93aae4fc44936663d7079a5 Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Thu, 24 May 2012 19:24:18 +0900 +Subject: sh: intc: Allocate subgroup virq backing desc directly. + +This switches to using irq_alloc_desc() directly for subgroup IRQs. +We still need to call activate_irq() on these in order to make them +requestable, at least up until these get moved in to their own irq +domain.. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 123df01e8e046d6065089e1bff29aa3fc48d4420) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/sh/intc/virq.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/sh/intc/virq.c b/drivers/sh/intc/virq.c +index 93cec21..f30ac93 100644 +--- a/drivers/sh/intc/virq.c ++++ b/drivers/sh/intc/virq.c +@@ -219,12 +219,14 @@ restart: + if (radix_tree_deref_retry(entry)) + goto restart; + +- irq = create_irq(); ++ irq = irq_alloc_desc(numa_node_id()); + if (unlikely(irq < 0)) { + pr_err("no more free IRQs, bailing..\n"); + break; + } + ++ activate_irq(irq); ++ + pr_info("Setting up a chained VIRQ from %d -> %d\n", + irq, entry->pirq); + +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0032-sh-intc-initial-irqdomain-support.patch b/patches.marzen/0032-sh-intc-initial-irqdomain-support.patch new file mode 100644 index 0000000000000..be492d9dee3c5 --- /dev/null +++ b/patches.marzen/0032-sh-intc-initial-irqdomain-support.patch @@ -0,0 +1,195 @@ +From 53b1c0647bb113f4c1edfdfc8c40b7bf8f258628 Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Wed, 1 Aug 2012 17:13:46 +0900 +Subject: sh: intc: initial irqdomain support. + +Trivial support for irq domains, using either a linear map or radix tree +depending on the vector layout. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 1d6a21b0a672fb29b01ccf397d478e0541e17716) + +Conflicts: + drivers/sh/intc/Makefile + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/sh/intc/Kconfig | 4 +++ + drivers/sh/intc/Makefile | 2 +- + drivers/sh/intc/core.c | 11 +++++--- + drivers/sh/intc/internals.h | 5 ++++ + drivers/sh/intc/irqdomain.c | 68 +++++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 85 insertions(+), 5 deletions(-) + create mode 100644 drivers/sh/intc/irqdomain.c + +diff --git a/drivers/sh/intc/Kconfig b/drivers/sh/intc/Kconfig +index c88cbcc..a305731 100644 +--- a/drivers/sh/intc/Kconfig ++++ b/drivers/sh/intc/Kconfig +@@ -1,3 +1,7 @@ ++config SH_INTC ++ def_bool y ++ select IRQ_DOMAIN ++ + comment "Interrupt controller options" + + config INTC_USERIMASK +diff --git a/drivers/sh/intc/Makefile b/drivers/sh/intc/Makefile +index bb5df86..44cf2cd 100644 +--- a/drivers/sh/intc/Makefile ++++ b/drivers/sh/intc/Makefile +@@ -1,4 +1,4 @@ +-obj-y := access.o chip.o core.o dynamic.o handle.o virq.o ++obj-y := access.o chip.o core.o dynamic.o handle.o irqdomain.o virq.o + + obj-$(CONFIG_INTC_BALANCING) += balancing.o + obj-$(CONFIG_INTC_USERIMASK) += userimask.o +diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c +index 7e562cc..2374468 100644 +--- a/drivers/sh/intc/core.c ++++ b/drivers/sh/intc/core.c +@@ -25,6 +25,7 @@ + #include <linux/stat.h> + #include <linux/interrupt.h> + #include <linux/sh_intc.h> ++#include <linux/irqdomain.h> + #include <linux/device.h> + #include <linux/syscore_ops.h> + #include <linux/list.h> +@@ -310,6 +311,8 @@ int __init register_intc_controller(struct intc_desc *desc) + + BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ + ++ intc_irq_domain_init(d, hw); ++ + /* register the vectors one by one */ + for (i = 0; i < hw->nr_vectors; i++) { + struct intc_vect *vect = hw->vectors + i; +@@ -319,8 +322,8 @@ int __init register_intc_controller(struct intc_desc *desc) + if (!vect->enum_id) + continue; + +- res = irq_alloc_desc_at(irq, numa_node_id()); +- if (res != irq && res != -EEXIST) { ++ res = irq_create_identity_mapping(d->domain, irq); ++ if (unlikely(res)) { + pr_err("can't get irq_desc for %d\n", irq); + continue; + } +@@ -340,8 +343,8 @@ int __init register_intc_controller(struct intc_desc *desc) + * IRQ support, each vector still needs to have + * its own backing irq_desc. + */ +- res = irq_alloc_desc_at(irq2, numa_node_id()); +- if (res != irq2 && res != -EEXIST) { ++ res = irq_create_identity_mapping(d->domain, irq2); ++ if (unlikely(res)) { + pr_err("can't get irq_desc for %d\n", irq2); + continue; + } +diff --git a/drivers/sh/intc/internals.h b/drivers/sh/intc/internals.h +index f034a97..7dff08e 100644 +--- a/drivers/sh/intc/internals.h ++++ b/drivers/sh/intc/internals.h +@@ -1,5 +1,6 @@ + #include <linux/sh_intc.h> + #include <linux/irq.h> ++#include <linux/irqdomain.h> + #include <linux/list.h> + #include <linux/kernel.h> + #include <linux/types.h> +@@ -66,6 +67,7 @@ struct intc_desc_int { + unsigned int nr_sense; + struct intc_window *window; + unsigned int nr_windows; ++ struct irq_domain *domain; + struct irq_chip chip; + bool skip_suspend; + }; +@@ -187,6 +189,9 @@ unsigned long intc_get_ack_handle(unsigned int irq); + void intc_enable_disable_enum(struct intc_desc *desc, struct intc_desc_int *d, + intc_enum enum_id, int enable); + ++/* irqdomain.c */ ++void intc_irq_domain_init(struct intc_desc_int *d, struct intc_hw_desc *hw); ++ + /* virq.c */ + void intc_subgroup_init(struct intc_desc *desc, struct intc_desc_int *d); + void intc_irq_xlate_set(unsigned int irq, intc_enum id, struct intc_desc_int *d); +diff --git a/drivers/sh/intc/irqdomain.c b/drivers/sh/intc/irqdomain.c +new file mode 100644 +index 0000000..3968f1c +--- /dev/null ++++ b/drivers/sh/intc/irqdomain.c +@@ -0,0 +1,68 @@ ++/* ++ * IRQ domain support for SH INTC subsystem ++ * ++ * Copyright (C) 2012 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) "intc: " fmt ++ ++#include <linux/irqdomain.h> ++#include <linux/sh_intc.h> ++#include <linux/export.h> ++#include "internals.h" ++ ++/** ++ * intc_irq_domain_evt_xlate() - Generic xlate for vectored IRQs. ++ * ++ * This takes care of exception vector to hwirq translation through ++ * by way of evt2irq() translation. ++ * ++ * Note: For platforms that use a flat vector space without INTEVT this ++ * basically just mimics irq_domain_xlate_onecell() by way of a nopped ++ * out evt2irq() implementation. ++ */ ++static int intc_evt_xlate(struct irq_domain *d, struct device_node *ctrlr, ++ const u32 *intspec, unsigned int intsize, ++ unsigned long *out_hwirq, unsigned int *out_type) ++{ ++ if (WARN_ON(intsize < 1)) ++ return -EINVAL; ++ ++ *out_hwirq = evt2irq(intspec[0]); ++ *out_type = IRQ_TYPE_NONE; ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops intc_evt_ops = { ++ .xlate = intc_evt_xlate, ++}; ++ ++void __init intc_irq_domain_init(struct intc_desc_int *d, ++ struct intc_hw_desc *hw) ++{ ++ unsigned int irq_base, irq_end; ++ ++ /* ++ * Quick linear revmap check ++ */ ++ irq_base = evt2irq(hw->vectors[0].vect); ++ irq_end = evt2irq(hw->vectors[hw->nr_vectors - 1].vect); ++ ++ /* ++ * Linear domains have a hard-wired assertion that IRQs start at ++ * 0 in order to make some performance optimizations. Lamely ++ * restrict the linear case to these conditions here, taking the ++ * tree penalty for linear cases with non-zero hwirq bases. ++ */ ++ if (irq_base == 0 && irq_end == (irq_base + hw->nr_vectors - 1)) ++ d->domain = irq_domain_add_linear(NULL, hw->nr_vectors, ++ &intc_evt_ops, NULL); ++ else ++ d->domain = irq_domain_add_tree(NULL, &intc_evt_ops, NULL); ++ ++ BUG_ON(!d->domain); ++} +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0033-sh-intc-Handle-domain-association-for-sparseirq-pre-.patch b/patches.marzen/0033-sh-intc-Handle-domain-association-for-sparseirq-pre-.patch new file mode 100644 index 0000000000000..9a4f4614299c1 --- /dev/null +++ b/patches.marzen/0033-sh-intc-Handle-domain-association-for-sparseirq-pre-.patch @@ -0,0 +1,76 @@ +From f4c7cdd9100a1141390e3cea9c3ef8a104c420ae Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Thu, 9 Aug 2012 12:59:40 +0900 +Subject: sh: intc: Handle domain association for sparseirq pre-allocated + vectors. + +Presently it's assumed that the irqdomain code handles the irq_desc +allocation for us, but this isn't necessarily the case when we've +pre-allocated IRQs via sparseirq. Previously we had a -EEXIST check in +the code that attempted to trap these cases and simply update them +in-place, but this behaviour was inadvertently lost in the transition to +irqdomains. + +This simply restores the previous behaviour, first attempting to let the +irqdomain core fetch the allocation for us, and falling back to an +in-place domain association in the extant IRQ case. Fixes up regressions +on platforms that pre-allocate legacy IRQs (specifically ARM-based +SH-Mobile platforms, as SH stopped pre-allocating vectors some time ago). + +Reported-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 1026023705b0baa2b37df2a0d1da0022fc7b985e) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/sh/intc/core.c | 27 +++++++++++++++++++++++---- + 1 file changed, 23 insertions(+), 4 deletions(-) + +diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c +index 2374468..32c26d7 100644 +--- a/drivers/sh/intc/core.c ++++ b/drivers/sh/intc/core.c +@@ -324,8 +324,16 @@ int __init register_intc_controller(struct intc_desc *desc) + + res = irq_create_identity_mapping(d->domain, irq); + if (unlikely(res)) { +- pr_err("can't get irq_desc for %d\n", irq); +- continue; ++ if (res == -EEXIST) { ++ res = irq_domain_associate(d->domain, irq, irq); ++ if (unlikely(res)) { ++ pr_err("domain association failure\n"); ++ continue; ++ } ++ } else { ++ pr_err("can't identity map IRQ %d\n", irq); ++ continue; ++ } + } + + intc_irq_xlate_set(irq, vect->enum_id, d); +@@ -345,8 +353,19 @@ int __init register_intc_controller(struct intc_desc *desc) + */ + res = irq_create_identity_mapping(d->domain, irq2); + if (unlikely(res)) { +- pr_err("can't get irq_desc for %d\n", irq2); +- continue; ++ if (res == -EEXIST) { ++ res = irq_domain_associate(d->domain, ++ irq, irq); ++ if (unlikely(res)) { ++ pr_err("domain association " ++ "failure\n"); ++ continue; ++ } ++ } else { ++ pr_err("can't identity map IRQ %d\n", ++ irq); ++ continue; ++ } + } + + vect2->enum_id = 0; +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0034-sh-intc-Fix-up-multi-evt-irq-association.patch b/patches.marzen/0034-sh-intc-Fix-up-multi-evt-irq-association.patch new file mode 100644 index 0000000000000..adc6c6ebf22a3 --- /dev/null +++ b/patches.marzen/0034-sh-intc-Fix-up-multi-evt-irq-association.patch @@ -0,0 +1,32 @@ +From e36191f0adc5ef8bafb24f3612367b5648ee279a Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Mon, 20 Aug 2012 14:51:50 +0900 +Subject: sh: intc: Fix up multi-evt irq association. + +In the multi-evt case we were accidentally associating the parent IRQ, +fix this up. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit d4b7c5db429fbfd3c79120b27ccf66d583606b57) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/sh/intc/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c +index 32c26d7..8f32a13 100644 +--- a/drivers/sh/intc/core.c ++++ b/drivers/sh/intc/core.c +@@ -355,7 +355,7 @@ int __init register_intc_controller(struct intc_desc *desc) + if (unlikely(res)) { + if (res == -EEXIST) { + res = irq_domain_associate(d->domain, +- irq, irq); ++ irq2, irq2); + if (unlikely(res)) { + pr_err("domain association " + "failure\n"); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0035-ARM-mach-shmobile-Introduce-shmobile_setup_delay.patch b/patches.marzen/0035-ARM-mach-shmobile-Introduce-shmobile_setup_delay.patch new file mode 100644 index 0000000000000..3ab427317247c --- /dev/null +++ b/patches.marzen/0035-ARM-mach-shmobile-Introduce-shmobile_setup_delay.patch @@ -0,0 +1,70 @@ +From faa2b6a185dbc63fb27624543fb4e6dc3498eb90 Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Wed, 28 Mar 2012 19:22:30 +0900 +Subject: ARM: mach-shmobile: Introduce shmobile_setup_delay() + +Add the function shmobile_setup_delay() to let platforms +configure their maximum loops per jiffy delay. With this +jiffies calculation done the dependency on early timer +is removed. + +In the future this allows us to assign timers +using the regular driver model via the device tree. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 0f2c9f20e4e339de30cfd5613dfa9505e7b9c58b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/include/mach/common.h | 2 ++ + arch/arm/mach-shmobile/timer.c | 17 +++++++++++++++++ + 2 files changed, 19 insertions(+) + +diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h +index c85e6ec..ff5f12f 100644 +--- a/arch/arm/mach-shmobile/include/mach/common.h ++++ b/arch/arm/mach-shmobile/include/mach/common.h +@@ -3,6 +3,8 @@ + + extern void shmobile_earlytimer_init(void); + extern struct sys_timer shmobile_timer; ++extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz, ++ unsigned int mult, unsigned int div); + struct twd_local_timer; + extern void shmobile_setup_console(void); + extern void shmobile_secondary_vector(void); +diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c +index 8b79e79..cba39d8 100644 +--- a/arch/arm/mach-shmobile/timer.c ++++ b/arch/arm/mach-shmobile/timer.c +@@ -19,9 +19,26 @@ + * + */ + #include <linux/platform_device.h> ++#include <linux/delay.h> + #include <asm/mach/time.h> + #include <asm/smp_twd.h> + ++void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz, ++ unsigned int mult, unsigned int div) ++{ ++ /* calculate a worst-case loops-per-jiffy value ++ * based on maximum cpu core mhz setting and the ++ * __delay() implementation in arch/arm/lib/delay.S ++ * ++ * this will result in a longer delay than expected ++ * when the cpu core runs on lower frequencies. ++ */ ++ ++ unsigned int value = (1000000 * mult) / (HZ * div); ++ ++ lpj_fine = max_cpu_core_mhz * value; ++} ++ + static void __init shmobile_late_time_init(void) + { + /* +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0036-ARM-mach-shmobile-Use-0x3400-as-INTCS-vector-offset.patch b/patches.marzen/0036-ARM-mach-shmobile-Use-0x3400-as-INTCS-vector-offset.patch new file mode 100644 index 0000000000000..f2a1a78228e31 --- /dev/null +++ b/patches.marzen/0036-ARM-mach-shmobile-Use-0x3400-as-INTCS-vector-offset.patch @@ -0,0 +1,43 @@ +From 08bdac8dff053868074871b3bc6318d6d95d476e Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Wed, 28 Mar 2012 19:22:54 +0900 +Subject: ARM: mach-shmobile: Use 0x3400 as INTCS vector offset + +Update mach-shmobile to use 0x3400 as INTCS_VECT_BASE. + +Since the ARM architecture a little while back added support +for 10 bit irqs we can now undo the previously merged commit +9b7c23adb350a108737a993c9c781463c1439dc6 and use 0x3400 as +INTCS vector base. + +This change is necessary to avoid overlapping of interrupt +ranges so separate IRQ domains can be used for different INTC +instances. Without this fix the vectors used by various INTC +instances are overlapping on for instance sh7372 which works +at the moment but breaks upcoming IRQ domain support. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 1ee8299a9ec1ce5137a044c7768293007b9a3267) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/include/mach/irqs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/include/mach/irqs.h b/arch/arm/mach-shmobile/include/mach/irqs.h +index 4e686cc2..06a5da3 100644 +--- a/arch/arm/mach-shmobile/include/mach/irqs.h ++++ b/arch/arm/mach-shmobile/include/mach/irqs.h +@@ -7,7 +7,7 @@ + #define gic_spi(nr) ((nr) + 32) + + /* INTCS */ +-#define INTCS_VECT_BASE 0x2200 ++#define INTCS_VECT_BASE 0x3400 + #define INTCS_VECT(n, vect) INTC_VECT((n), INTCS_VECT_BASE + (vect)) + #define intcs_evt2irq(evt) evt2irq(INTCS_VECT_BASE + (evt)) + +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0037-ARM-provide-a-late_initcall-hook-for-platform-initia.patch b/patches.marzen/0037-ARM-provide-a-late_initcall-hook-for-platform-initia.patch new file mode 100644 index 0000000000000..5ced9d5e5efe3 --- /dev/null +++ b/patches.marzen/0037-ARM-provide-a-late_initcall-hook-for-platform-initia.patch @@ -0,0 +1,55 @@ +From 8635adab79f5f8e8287e93cc19442556cab55d06 Mon Sep 17 00:00:00 2001 +From: Shawn Guo <shawn.guo@linaro.org> +Date: Wed, 25 Apr 2012 22:24:44 +0800 +Subject: ARM: provide a late_initcall hook for platform initialization + +This allows platforms to set up things that need to be done at +late_initcall time. + +Signed-off-by: Shawn Guo <shawn.guo@linaro.org> +Tested-by: Robert Lee <rob.lee@linaro.org> +Tested-by: Stephen Warren <swarren@wwwdotorg.org> +Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com> +Acked-by: Russell King <rmk+kernel@arm.linux.org.uk> +(cherry picked from commit 90de41375ccf8373c0a39d04547f3e3c65d90ec0) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/include/asm/mach/arch.h | 1 + + arch/arm/kernel/setup.c | 8 ++++++++ + 2 files changed, 9 insertions(+) + +diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h +index d7692ca..0b1c94b 100644 +--- a/arch/arm/include/asm/mach/arch.h ++++ b/arch/arm/include/asm/mach/arch.h +@@ -43,6 +43,7 @@ struct machine_desc { + void (*init_irq)(void); + struct sys_timer *timer; /* system tick timer */ + void (*init_machine)(void); ++ void (*init_late)(void); + #ifdef CONFIG_MULTI_IRQ_HANDLER + void (*handle_irq)(struct pt_regs *); + #endif +diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c +index ebfac78..549f036 100644 +--- a/arch/arm/kernel/setup.c ++++ b/arch/arm/kernel/setup.c +@@ -800,6 +800,14 @@ static int __init customize_machine(void) + } + arch_initcall(customize_machine); + ++static int __init init_machine_late(void) ++{ ++ if (machine_desc->init_late) ++ machine_desc->init_late(); ++ return 0; ++} ++late_initcall(init_machine_late); ++ + #ifdef CONFIG_KEXEC + static inline unsigned long long get_total_mem(void) + { +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0038-ARM-shmobile-use-machine-specific-hook-for-late-init.patch b/patches.marzen/0038-ARM-shmobile-use-machine-specific-hook-for-late-init.patch new file mode 100644 index 0000000000000..695b5f9187bdf --- /dev/null +++ b/patches.marzen/0038-ARM-shmobile-use-machine-specific-hook-for-late-init.patch @@ -0,0 +1,219 @@ +From 7f963c76f63cde6c48ce88a3b6a964b316e6d8ed Mon Sep 17 00:00:00 2001 +From: Shawn Guo <shawn.guo@linaro.org> +Date: Thu, 26 Apr 2012 21:58:41 +0800 +Subject: ARM: shmobile: use machine specific hook for late init + +Cc: Paul Mundt <lethal@linux-sh.org> +Signed-off-by: Shawn Guo <shawn.guo@linaro.org> +Acked-by: Magnus Damm <damm@opensource.se> +Acked-by: "Rafael J. Wysocki" <rjw@sisk.pl> +(cherry picked from commit 21cc1b7ede3cf456cf1d51f8a906093261f7c111) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/Makefile | 2 +- + arch/arm/mach-shmobile/board-ag5evm.c | 1 + + arch/arm/mach-shmobile/board-ap4evb.c | 1 + + arch/arm/mach-shmobile/board-bonito.c | 1 + + arch/arm/mach-shmobile/board-g3evm.c | 1 + + arch/arm/mach-shmobile/board-g4evm.c | 1 + + arch/arm/mach-shmobile/board-kota2.c | 1 + + arch/arm/mach-shmobile/board-mackerel.c | 1 + + arch/arm/mach-shmobile/board-marzen.c | 1 + + arch/arm/mach-shmobile/common.c | 24 ++++++++++++++++++++++++ + arch/arm/mach-shmobile/cpuidle.c | 3 +-- + arch/arm/mach-shmobile/include/mach/common.h | 14 ++++++++++++++ + arch/arm/mach-shmobile/suspend.c | 3 +-- + 13 files changed, 49 insertions(+), 5 deletions(-) + create mode 100644 arch/arm/mach-shmobile/common.c + +diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile +index e7c2590..93d62fb 100644 +--- a/arch/arm/mach-shmobile/Makefile ++++ b/arch/arm/mach-shmobile/Makefile +@@ -3,7 +3,7 @@ + # + + # Common objects +-obj-y := timer.o console.o clock.o ++obj-y := timer.o console.o clock.o common.o + + # CPU objects + obj-$(CONFIG_ARCH_SH7367) += setup-sh7367.o clock-sh7367.o intc-sh7367.o +diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c +index 0891ec6..5a6f22f 100644 +--- a/arch/arm/mach-shmobile/board-ag5evm.c ++++ b/arch/arm/mach-shmobile/board-ag5evm.c +@@ -580,5 +580,6 @@ MACHINE_START(AG5EVM, "ag5evm") + .init_irq = sh73a0_init_irq, + .handle_irq = gic_handle_irq, + .init_machine = ag5evm_init, ++ .init_late = shmobile_init_late, + .timer = &shmobile_timer, + MACHINE_END +diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c +index b56dde2..522866d 100644 +--- a/arch/arm/mach-shmobile/board-ap4evb.c ++++ b/arch/arm/mach-shmobile/board-ap4evb.c +@@ -1440,5 +1440,6 @@ MACHINE_START(AP4EVB, "ap4evb") + .init_irq = sh7372_init_irq, + .handle_irq = shmobile_handle_irq_intc, + .init_machine = ap4evb_init, ++ .init_late = shmobile_init_late, + .timer = &shmobile_timer, + MACHINE_END +diff --git a/arch/arm/mach-shmobile/board-bonito.c b/arch/arm/mach-shmobile/board-bonito.c +index 81fd95f..e6b1fd3 100644 +--- a/arch/arm/mach-shmobile/board-bonito.c ++++ b/arch/arm/mach-shmobile/board-bonito.c +@@ -500,5 +500,6 @@ MACHINE_START(BONITO, "bonito") + .init_irq = r8a7740_init_irq, + .handle_irq = shmobile_handle_irq_intc, + .init_machine = bonito_init, ++ .init_late = shmobile_init_late, + .timer = &shmobile_timer, + MACHINE_END +diff --git a/arch/arm/mach-shmobile/board-g3evm.c b/arch/arm/mach-shmobile/board-g3evm.c +index 39b6cf8..796fa00 100644 +--- a/arch/arm/mach-shmobile/board-g3evm.c ++++ b/arch/arm/mach-shmobile/board-g3evm.c +@@ -338,5 +338,6 @@ MACHINE_START(G3EVM, "g3evm") + .init_irq = sh7367_init_irq, + .handle_irq = shmobile_handle_irq_intc, + .init_machine = g3evm_init, ++ .init_late = shmobile_init_late, + .timer = &shmobile_timer, + MACHINE_END +diff --git a/arch/arm/mach-shmobile/board-g4evm.c b/arch/arm/mach-shmobile/board-g4evm.c +index 0e5a39c..f125732 100644 +--- a/arch/arm/mach-shmobile/board-g4evm.c ++++ b/arch/arm/mach-shmobile/board-g4evm.c +@@ -381,5 +381,6 @@ MACHINE_START(G4EVM, "g4evm") + .init_irq = sh7377_init_irq, + .handle_irq = shmobile_handle_irq_intc, + .init_machine = g4evm_init, ++ .init_late = shmobile_init_late, + .timer = &shmobile_timer, + MACHINE_END +diff --git a/arch/arm/mach-shmobile/board-kota2.c b/arch/arm/mach-shmobile/board-kota2.c +index 200dcd4..f60f1b2 100644 +--- a/arch/arm/mach-shmobile/board-kota2.c ++++ b/arch/arm/mach-shmobile/board-kota2.c +@@ -521,5 +521,6 @@ MACHINE_START(KOTA2, "kota2") + .init_irq = sh73a0_init_irq, + .handle_irq = gic_handle_irq, + .init_machine = kota2_init, ++ .init_late = shmobile_init_late, + .timer = &shmobile_timer, + MACHINE_END +diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c +index 8c6202b..656d351 100644 +--- a/arch/arm/mach-shmobile/board-mackerel.c ++++ b/arch/arm/mach-shmobile/board-mackerel.c +@@ -1605,5 +1605,6 @@ MACHINE_START(MACKEREL, "mackerel") + .init_irq = sh7372_init_irq, + .handle_irq = shmobile_handle_irq_intc, + .init_machine = mackerel_init, ++ .init_late = shmobile_init_late, + .timer = &shmobile_timer, + MACHINE_END +diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c +index ef0e13b..14de378 100644 +--- a/arch/arm/mach-shmobile/board-marzen.c ++++ b/arch/arm/mach-shmobile/board-marzen.c +@@ -98,5 +98,6 @@ MACHINE_START(MARZEN, "marzen") + .init_irq = r8a7779_init_irq, + .handle_irq = gic_handle_irq, + .init_machine = marzen_init, ++ .init_late = shmobile_init_late, + .timer = &shmobile_timer, + MACHINE_END +diff --git a/arch/arm/mach-shmobile/common.c b/arch/arm/mach-shmobile/common.c +new file mode 100644 +index 0000000..608aba9 +--- /dev/null ++++ b/arch/arm/mach-shmobile/common.c +@@ -0,0 +1,24 @@ ++/* ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <mach/common.h> ++ ++void __init shmobile_init_late(void) ++{ ++ shmobile_suspend_init(); ++ shmobile_cpuidle_init(); ++} +diff --git a/arch/arm/mach-shmobile/cpuidle.c b/arch/arm/mach-shmobile/cpuidle.c +index 7e65591..7b541e9 100644 +--- a/arch/arm/mach-shmobile/cpuidle.c ++++ b/arch/arm/mach-shmobile/cpuidle.c +@@ -46,7 +46,7 @@ static struct cpuidle_driver shmobile_cpuidle_driver = { + + void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv); + +-static int shmobile_cpuidle_init(void) ++int shmobile_cpuidle_init(void) + { + struct cpuidle_device *dev = &shmobile_cpuidle_dev; + struct cpuidle_driver *drv = &shmobile_cpuidle_driver; +@@ -65,4 +65,3 @@ static int shmobile_cpuidle_init(void) + + return 0; + } +-late_initcall(shmobile_cpuidle_init); +diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h +index ff5f12f..01e2bc0 100644 +--- a/arch/arm/mach-shmobile/include/mach/common.h ++++ b/arch/arm/mach-shmobile/include/mach/common.h +@@ -85,4 +85,18 @@ extern int r8a7779_boot_secondary(unsigned int cpu); + extern void r8a7779_smp_prepare_cpus(void); + extern void r8a7779_register_twd(void); + ++extern void shmobile_init_late(void); ++ ++#ifdef CONFIG_SUSPEND ++int shmobile_suspend_init(void); ++#else ++static inline int shmobile_suspend_init(void) { return 0; } ++#endif ++ ++#ifdef CONFIG_CPU_IDLE ++int shmobile_cpuidle_init(void); ++#else ++static inline int shmobile_cpuidle_init(void) { return 0; } ++#endif ++ + #endif /* __ARCH_MACH_COMMON_H */ +diff --git a/arch/arm/mach-shmobile/suspend.c b/arch/arm/mach-shmobile/suspend.c +index 4d1b86a..47d83f7 100644 +--- a/arch/arm/mach-shmobile/suspend.c ++++ b/arch/arm/mach-shmobile/suspend.c +@@ -39,9 +39,8 @@ struct platform_suspend_ops shmobile_suspend_ops = { + .valid = suspend_valid_only_mem, + }; + +-static int __init shmobile_suspend_init(void) ++int __init shmobile_suspend_init(void) + { + suspend_set_ops(&shmobile_suspend_ops); + return 0; + } +-late_initcall(shmobile_suspend_init); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0039-ARM-mach-shmobile-Use-preset_lpj-with-calibrate_dela.patch b/patches.marzen/0039-ARM-mach-shmobile-Use-preset_lpj-with-calibrate_dela.patch new file mode 100644 index 0000000000000..0bd9433030594 --- /dev/null +++ b/patches.marzen/0039-ARM-mach-shmobile-Use-preset_lpj-with-calibrate_dela.patch @@ -0,0 +1,46 @@ +From d85b38a67ee3f87c9ac4d814d091f6bacd77745a Mon Sep 17 00:00:00 2001 +From: Magnus Damm <damm@opensource.se> +Date: Thu, 10 May 2012 00:37:48 +0200 +Subject: ARM / mach-shmobile: Use preset_lpj with calibrate_delay() + +Update the mach-shmobile shared delay calibration code for late +timers. All existing in-tree non-DT socs are however using early +timers today and they are unaffected by this change. + +The patch modifies shmobile_setup_delay() from using lpj_fine +to preset_lpj. This change allows us to preset the worst case +loops-per-jiffy value to all CPU cores on the system. + +The old code which made use of lpj_fine did not affect the +secondary CPU cores which made it impossible to boot on SMP +without early timers. + +Needed for SMP SoCs using late timers like EMEV2 or any other +mach-shmobile SMP SoC that makes use of late timers via DT. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 173bf69a7af142e0325fa514954f6eeb2d20cc1d) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/timer.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c +index cba39d8..a689197 100644 +--- a/arch/arm/mach-shmobile/timer.c ++++ b/arch/arm/mach-shmobile/timer.c +@@ -36,7 +36,8 @@ void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz, + + unsigned int value = (1000000 * mult) / (HZ * div); + +- lpj_fine = max_cpu_core_mhz * value; ++ if (!preset_lpj) ++ preset_lpj = max_cpu_core_mhz * value; + } + + static void __init shmobile_late_time_init(void) +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0040-ARM-shmobile-r8a7740-add-MERAM-work-around.patch b/patches.marzen/0040-ARM-shmobile-r8a7740-add-MERAM-work-around.patch new file mode 100644 index 0000000000000..9ccc16d68c336 --- /dev/null +++ b/patches.marzen/0040-ARM-shmobile-r8a7740-add-MERAM-work-around.patch @@ -0,0 +1,72 @@ +From 357b31146983e768c408a833731f6b5c614286df Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Tue, 12 Jun 2012 02:36:21 -0700 +Subject: ARM: shmobile: r8a7740: add MERAM work-around + +r8a7740 chip has lasting errata on MERAM buffer, and this patch adds +its work-around on setup-r8a7740.c +It solved CEU/VIO6C/2D-DMAC/VCP1/VPU5F/JPU/DISP memroy access error. + +But MERAM driver can't control this issue, +since this work-around requires access to non-MERAM register address. +So, This it will be called as board specific code at this point. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit d49679e5928709bce8937dce396458b139c4b34d) + +Conflicts: + arch/arm/mach-shmobile/board-armadillo800eva.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/include/mach/common.h | 1 + + arch/arm/mach-shmobile/setup-r8a7740.c | 18 ++++++++++++++++++ + 2 files changed, 19 insertions(+) + +diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h +index 01e2bc0..45e61da 100644 +--- a/arch/arm/mach-shmobile/include/mach/common.h ++++ b/arch/arm/mach-shmobile/include/mach/common.h +@@ -77,6 +77,7 @@ extern void r8a7779_add_standard_devices(void); + extern void r8a7779_clock_init(void); + extern void r8a7779_pinmux_init(void); + extern void r8a7779_pm_init(void); ++extern void r8a7740_meram_workaround(void); + + extern unsigned int r8a7779_get_core_count(void); + extern int r8a7779_platform_cpu_kill(unsigned int cpu); +diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c +index 14edb5c..4ba8721 100644 +--- a/arch/arm/mach-shmobile/setup-r8a7740.c ++++ b/arch/arm/mach-shmobile/setup-r8a7740.c +@@ -317,6 +317,24 @@ static struct platform_device *r8a7740_late_devices[] __initdata = { + &i2c1_device, + }; + ++/* ++ * r8a7740 chip has lasting errata on MERAM buffer. ++ * this is work-around for it. ++ * see ++ * "Media RAM (MERAM)" on r8a7740 documentation ++ */ ++#define MEBUFCNTR 0xFE950098 ++void r8a7740_meram_workaround(void) ++{ ++ void __iomem *reg; ++ ++ reg = ioremap_nocache(MEBUFCNTR, 4); ++ if (reg) { ++ iowrite32(0x01600164, reg); ++ iounmap(reg); ++ } ++} ++ + #define ICCR 0x0004 + #define ICSTART 0x0070 + +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0041-ARM-shmobile-add-common-extra-gpio-functions.patch b/patches.marzen/0041-ARM-shmobile-add-common-extra-gpio-functions.patch new file mode 100644 index 0000000000000..3c63f44308a0d --- /dev/null +++ b/patches.marzen/0041-ARM-shmobile-add-common-extra-gpio-functions.patch @@ -0,0 +1,73 @@ +From 2a3e278e5c92a6143bc2a57f5c2d5093e26f4208 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Mon, 25 Jun 2012 03:41:09 -0700 +Subject: ARM: shmobile: add common extra gpio functions + +Current gpio frame work doesn't have the method to control +just pull up/down/free, but some SH-ARM boards need such kind of operation. +This patch adds common extra gpio functions for SH-ARM. + +But these functions should be replaced by correct +gpio function in the future. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 4f3d7f65e9d541566c87de2af2d3b066bae78116) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/include/mach/gpio.h | 32 ++++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +diff --git a/arch/arm/mach-shmobile/include/mach/gpio.h b/arch/arm/mach-shmobile/include/mach/gpio.h +index de795b4..844507d 100644 +--- a/arch/arm/mach-shmobile/include/mach/gpio.h ++++ b/arch/arm/mach-shmobile/include/mach/gpio.h +@@ -13,6 +13,7 @@ + #include <linux/kernel.h> + #include <linux/errno.h> + #include <linux/sh_pfc.h> ++#include <linux/io.h> + + #ifdef CONFIG_GPIOLIB + +@@ -27,4 +28,35 @@ static inline int irq_to_gpio(unsigned int irq) + + #endif /* CONFIG_GPIOLIB */ + ++/* ++ * FIXME !! ++ * ++ * current gpio frame work doesn't have ++ * the method to control only pull up/down/free. ++ * this function should be replaced by correct gpio function ++ */ ++static inline void __init gpio_direction_none(u32 addr) ++{ ++ __raw_writeb(0x00, addr); ++} ++ ++static inline void __init gpio_request_pullup(u32 addr) ++{ ++ u8 data = __raw_readb(addr); ++ ++ data &= 0x0F; ++ data |= 0xC0; ++ __raw_writeb(data, addr); ++} ++ ++static inline void __init gpio_request_pulldown(u32 addr) ++{ ++ u8 data = __raw_readb(addr); ++ ++ data &= 0x0F; ++ data |= 0xA0; ++ ++ __raw_writeb(data, addr); ++} ++ + #endif /* __ASM_ARCH_GPIO_H */ +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0042-ARM-mach-shmobile-add-fixed-voltage-regulators-to-ma.patch b/patches.marzen/0042-ARM-mach-shmobile-add-fixed-voltage-regulators-to-ma.patch new file mode 100644 index 0000000000000..161d66af12daf --- /dev/null +++ b/patches.marzen/0042-ARM-mach-shmobile-add-fixed-voltage-regulators-to-ma.patch @@ -0,0 +1,55 @@ +From 585b51f2c85ca9c6523a2fca74cc9c6beae3a00a Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 27 Jun 2012 00:32:32 +0200 +Subject: ARM: mach-shmobile: add fixed voltage regulators to marzen + +On marzen provide a dummy regulator for the smsc911x driver. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit b354e2272ac6fddd19cfd5732bda23974f7b4ee6) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-marzen.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c +index 14de378..3a528cf 100644 +--- a/arch/arm/mach-shmobile/board-marzen.c ++++ b/arch/arm/mach-shmobile/board-marzen.c +@@ -27,6 +27,8 @@ + #include <linux/io.h> + #include <linux/gpio.h> + #include <linux/dma-mapping.h> ++#include <linux/regulator/fixed.h> ++#include <linux/regulator/machine.h> + #include <linux/smsc911x.h> + #include <mach/hardware.h> + #include <mach/r8a7779.h> +@@ -37,6 +39,12 @@ + #include <asm/hardware/gic.h> + #include <asm/traps.h> + ++/* Dummy supplies, where voltage doesn't matter */ ++static struct regulator_consumer_supply dummy_supplies[] = { ++ REGULATOR_SUPPLY("vddvario", "smsc911x"), ++ REGULATOR_SUPPLY("vdd33a", "smsc911x"), ++}; ++ + /* SMSC LAN89218 */ + static struct resource smsc911x_resources[] = { + [0] = { +@@ -73,6 +81,8 @@ static struct platform_device *marzen_devices[] __initdata = { + + static void __init marzen_init(void) + { ++ regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); ++ + r8a7779_pinmux_init(); + + /* SCIF2 (CN18: DEBUG0) */ +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0043-ARM-shmobile-marzen-fixup-smsc911x-id-for-regulator.patch b/patches.marzen/0043-ARM-shmobile-marzen-fixup-smsc911x-id-for-regulator.patch new file mode 100644 index 0000000000000..ceb74d7f9ef76 --- /dev/null +++ b/patches.marzen/0043-ARM-shmobile-marzen-fixup-smsc911x-id-for-regulator.patch @@ -0,0 +1,33 @@ +From b7bf36d36b723ef18c515a031fb762d72ce06c38 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Wed, 29 Aug 2012 18:58:01 -0700 +Subject: ARM: shmobile: marzen: fixup smsc911x id for regulator + +dummy_supplies for smsc911x are registered as "smsc911x". +smsc911x driver needs id = -1 + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Simon Horman <horms@verge.net.au> +(cherry picked from commit 497dcf6fc355f0734faf851662b6957386715d24) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/board-marzen.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c +index 3a528cf..fcf5a47 100644 +--- a/arch/arm/mach-shmobile/board-marzen.c ++++ b/arch/arm/mach-shmobile/board-marzen.c +@@ -67,7 +67,7 @@ static struct smsc911x_platform_config smsc911x_platdata = { + + static struct platform_device eth_device = { + .name = "smsc911x", +- .id = 0, ++ .id = -1, + .dev = { + .platform_data = &smsc911x_platdata, + }, +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0044-ARM-shmobile-r8a7779-Route-all-interrupts-to-ARM.patch b/patches.marzen/0044-ARM-shmobile-r8a7779-Route-all-interrupts-to-ARM.patch new file mode 100644 index 0000000000000..5cfb75432ad99 --- /dev/null +++ b/patches.marzen/0044-ARM-shmobile-r8a7779-Route-all-interrupts-to-ARM.patch @@ -0,0 +1,46 @@ +From d84794f3aa3f4214afb08fa52df3ad592965ddba Mon Sep 17 00:00:00 2001 +From: Phil Edworthy <phil.edworthy@renesas.com> +Date: Sat, 23 Jun 2012 01:12:09 +0200 +Subject: ARM: shmobile: r8a7779: Route all interrupts to ARM + +Without this, the interrupts for I2C, VIN, GPIO, SDHC, HSCIF and +HPB-DMAC are sent to the SH processor. + +Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 86f887c105b909a2cea7b06f2136d66b3438b038) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + arch/arm/mach-shmobile/intc-r8a7779.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/arm/mach-shmobile/intc-r8a7779.c b/arch/arm/mach-shmobile/intc-r8a7779.c +index 550b23d..f04fad4 100644 +--- a/arch/arm/mach-shmobile/intc-r8a7779.c ++++ b/arch/arm/mach-shmobile/intc-r8a7779.c +@@ -35,6 +35,9 @@ + #define INT2SMSKCR3 0xfe7822ac + #define INT2SMSKCR4 0xfe7822b0 + ++#define INT2NTSR0 0xfe700060 ++#define INT2NTSR1 0xfe700064 ++ + static int r8a7779_set_wake(struct irq_data *data, unsigned int on) + { + return 0; /* always allow wakeup */ +@@ -49,6 +52,10 @@ void __init r8a7779_init_irq(void) + gic_init(0, 29, gic_dist_base, gic_cpu_base); + gic_arch_extn.irq_set_wake = r8a7779_set_wake; + ++ /* route all interrupts to ARM */ ++ __raw_writel(0xffffffff, INT2NTSR0); ++ __raw_writel(0x3fffffff, INT2NTSR1); ++ + /* unmask all known interrupts in INTCS2 */ + __raw_writel(0xfffffff0, INT2SMSKCR0); + __raw_writel(0xfff7ffff, INT2SMSKCR1); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0045-dmaengine-Fixup-dmaengine_prep_slave_single-to-be-ac.patch b/patches.marzen/0045-dmaengine-Fixup-dmaengine_prep_slave_single-to-be-ac.patch new file mode 100644 index 0000000000000..ec873b00fe72b --- /dev/null +++ b/patches.marzen/0045-dmaengine-Fixup-dmaengine_prep_slave_single-to-be-ac.patch @@ -0,0 +1,52 @@ +From 35d53ddd33da54b2ac40aa2b73e93832f9f72c28 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Wed, 25 Apr 2012 20:50:53 +0200 +Subject: dmaengine: Fixup dmaengine_prep_slave_single() to be actually useful + +dmaengine_prep_slave_single() is a helper function which is supposed to be used +to prepare a transfer of a single contingous buffer. Currently the function +takes a pointer to such a buffer from which it builds a scatterlist and passes +it on to device_prep_slave_sg. The dmaengine framework requires that any +scatterlist that is passed to device_prep_slave_sg is mapped and it may not be +unmapped until the DMA operation has completed. This is not the here and any use +of dmaengine_prep_slave_single() will lead to undefined behaviour (Most likely a +system crash). + +This patch changes dmaengine_prep_slave_single() to take a dma_addr_t instead of +a pointer to a buffer and moves the responsibility of mapping and unmapping the +buffer up to the caller. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> +Acked-by: Linus Walleij <linus.walleij@linaro.org> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit 922ee08baad2052d0759f100e026d49798c51fef) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/dmaengine.h | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index f9a2e5e..d3fec58 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -615,11 +615,13 @@ static inline int dmaengine_slave_config(struct dma_chan *chan, + } + + static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( +- struct dma_chan *chan, void *buf, size_t len, ++ struct dma_chan *chan, dma_addr_t buf, size_t len, + enum dma_transfer_direction dir, unsigned long flags) + { + struct scatterlist sg; +- sg_init_one(&sg, buf, len); ++ sg_init_table(&sg, 1); ++ sg_dma_address(&sg) = buf; ++ sg_dma_len(&sg) = len; + + return chan->device->device_prep_slave_sg(chan, &sg, 1, + dir, flags, NULL); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0046-dma-dmaengine-add-slave-req-id-in-slave_config.patch b/patches.marzen/0046-dma-dmaengine-add-slave-req-id-in-slave_config.patch new file mode 100644 index 0000000000000..ce43120a6e234 --- /dev/null +++ b/patches.marzen/0046-dma-dmaengine-add-slave-req-id-in-slave_config.patch @@ -0,0 +1,47 @@ +From a41ee881d86159d8d44d481f10c3288bdbc38a47 Mon Sep 17 00:00:00 2001 +From: Laxman Dewangan <ldewangan@nvidia.com> +Date: Wed, 6 Jun 2012 10:55:26 +0530 +Subject: dma: dmaengine: add slave req id in slave_config + +The DMA controller like Nvidia's Tegra Dma controller +supports the different slave requestor id from different slave. +This need to be configure in dma controller to handle the request +properly. + +Adding the slave-id in the slave configuration so that information +can be passed from client when configuring for slave. + +Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit 4fd1e324b7b5f80bd521b58593ada74ef89e80c4) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/dmaengine.h | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index d3fec58..2fad917 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -338,6 +338,9 @@ enum dma_slave_buswidth { + * @device_fc: Flow Controller Settings. Only valid for slave channels. Fill + * with 'true' if peripheral should be flow controller. Direction will be + * selected at Runtime. ++ * @slave_id: Slave requester id. Only valid for slave channels. The dma ++ * slave peripheral will have unique id as dma requester which need to be ++ * pass as slave config. + * + * This struct is passed in as configuration data to a DMA engine + * in order to set up a certain channel for DMA transport at runtime. +@@ -365,6 +368,7 @@ struct dma_slave_config { + u32 src_maxburst; + u32 dst_maxburst; + bool device_fc; ++ unsigned int slave_id; + }; + + static inline const char *dma_chan_name(struct dma_chan *chan) +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0047-dmaengine-Add-wrapper-for-device_tx_status-callback.patch b/patches.marzen/0047-dmaengine-Add-wrapper-for-device_tx_status-callback.patch new file mode 100644 index 0000000000000..aaf2660cd86a1 --- /dev/null +++ b/patches.marzen/0047-dmaengine-Add-wrapper-for-device_tx_status-callback.patch @@ -0,0 +1,42 @@ +From c5e667d5b33e041c7dff155e548083c2a176c31a Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen <lars@metafoo.de> +Date: Mon, 11 Jun 2012 20:11:40 +0200 +Subject: dmaengine: Add wrapper for device_tx_status callback + +This patch adds a small inline wrapper for the devivce_tx_status callback of a +dma device. This makes the source code of users of this function a bit more +compact and a bit more legible. + +E.g.: +-status = chan->device->device_tx_status(chan, cookie, &state) ++status = dmaengine_tx_status(chan, cookie, &state) + +Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit 3052cc2c92f11875d111d5b7b9b3ad535b3128b9) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/dmaengine.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index 2fad917..d1d6ef2 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -662,6 +662,12 @@ static inline int dmaengine_resume(struct dma_chan *chan) + return dmaengine_device_control(chan, DMA_RESUME, 0); + } + ++static inline enum dma_status dmaengine_tx_status(struct dma_chan *chan, ++ dma_cookie_t cookie, struct dma_tx_state *state) ++{ ++ return chan->device->device_tx_status(chan, cookie, state); ++} ++ + static inline dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc) + { + return desc->tx_submit(desc); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0048-dma-move-shdma-driver-to-an-own-directory.patch b/patches.marzen/0048-dma-move-shdma-driver-to-an-own-directory.patch new file mode 100644 index 0000000000000..062ec15e5d17f --- /dev/null +++ b/patches.marzen/0048-dma-move-shdma-driver-to-an-own-directory.patch @@ -0,0 +1,66 @@ +From 35a2e575d9dbacd1fdd88ca6c032d9c87de43622 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Mon, 2 Jul 2012 22:30:53 +0200 +Subject: dma: move shdma driver to an own directory + +The shdma driver is going to be split into multiple files. To make this more +convenient move it to an own directory. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit e95be94b8c25220aca09ed78c176f9b55a1482c8) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/dma/Makefile | 2 +- + drivers/dma/sh/Makefile | 1 + + drivers/dma/{ => sh}/shdma.c | 2 +- + drivers/dma/{ => sh}/shdma.h | 0 + 4 files changed, 3 insertions(+), 2 deletions(-) + create mode 100644 drivers/dma/sh/Makefile + rename drivers/dma/{ => sh}/shdma.c (99%) + rename drivers/dma/{ => sh}/shdma.h (100%) + +diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile +index 86b795b..59c10e5 100644 +--- a/drivers/dma/Makefile ++++ b/drivers/dma/Makefile +@@ -14,7 +14,7 @@ obj-$(CONFIG_DW_DMAC) += dw_dmac.o + obj-$(CONFIG_AT_HDMAC) += at_hdmac.o + obj-$(CONFIG_MX3_IPU) += ipu/ + obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o +-obj-$(CONFIG_SH_DMAE) += shdma.o ++obj-$(CONFIG_SH_DMAE) += sh/ + obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o + obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/ + obj-$(CONFIG_IMX_SDMA) += imx-sdma.o +diff --git a/drivers/dma/sh/Makefile b/drivers/dma/sh/Makefile +new file mode 100644 +index 0000000..ad4981a +--- /dev/null ++++ b/drivers/dma/sh/Makefile +@@ -0,0 +1 @@ ++obj-$(CONFIG_SH_DMAE) += shdma.o +diff --git a/drivers/dma/shdma.c b/drivers/dma/sh/shdma.c +similarity index 99% +rename from drivers/dma/shdma.c +rename to drivers/dma/sh/shdma.c +index 19d7a8d..8ab4a1f 100644 +--- a/drivers/dma/shdma.c ++++ b/drivers/dma/sh/shdma.c +@@ -31,7 +31,7 @@ + #include <linux/spinlock.h> + #include <linux/rculist.h> + +-#include "dmaengine.h" ++#include "../dmaengine.h" + #include "shdma.h" + + /* DMA descriptor control */ +diff --git a/drivers/dma/shdma.h b/drivers/dma/sh/shdma.h +similarity index 100% +rename from drivers/dma/shdma.h +rename to drivers/dma/sh/shdma.h +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0049-dmaengine-add-an-shdma-base-library.patch b/patches.marzen/0049-dmaengine-add-an-shdma-base-library.patch new file mode 100644 index 0000000000000..9907b4f9a9519 --- /dev/null +++ b/patches.marzen/0049-dmaengine-add-an-shdma-base-library.patch @@ -0,0 +1,1036 @@ +From cb331142a15a186173bb23463c591780e82f0a67 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 9 May 2012 17:09:13 +0200 +Subject: dmaengine: add an shdma-base library + +This patch extracts code from shdma.c, that does not directly deal with +hardware implementation details and can be re-used with diverse DMA +controller variants, found on SH-based SoCs. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Cc: Sascha Hauer <s.hauer@pengutronix.de> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit 9a7b8e002e331d0599127f16613c32f425a14f2c) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/dma/sh/Makefile | 1 + + drivers/dma/sh/shdma-base.c | 868 ++++++++++++++++++++++++++++++++++++++++++++ + include/linux/shdma-base.h | 123 +++++++ + 3 files changed, 992 insertions(+) + create mode 100644 drivers/dma/sh/shdma-base.c + create mode 100644 include/linux/shdma-base.h + +diff --git a/drivers/dma/sh/Makefile b/drivers/dma/sh/Makefile +index ad4981a..54ae957 100644 +--- a/drivers/dma/sh/Makefile ++++ b/drivers/dma/sh/Makefile +@@ -1 +1,2 @@ ++obj-$(CONFIG_SH_DMAE) += shdma-base.o + obj-$(CONFIG_SH_DMAE) += shdma.o +diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c +new file mode 100644 +index 0000000..ff060d0 +--- /dev/null ++++ b/drivers/dma/sh/shdma-base.c +@@ -0,0 +1,868 @@ ++/* ++ * Dmaengine driver base library for DMA controllers, found on SH-based SoCs ++ * ++ * extracted from shdma.c ++ * ++ * Copyright (C) 2011-2012 Guennadi Liakhovetski <g.liakhovetski@gmx.de> ++ * Copyright (C) 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com> ++ * Copyright (C) 2009 Renesas Solutions, Inc. All rights reserved. ++ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved. ++ * ++ * This is free software; you can redistribute it and/or modify ++ * it under the terms of version 2 of the GNU General Public License as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/delay.h> ++#include <linux/shdma-base.h> ++#include <linux/dmaengine.h> ++#include <linux/init.h> ++#include <linux/interrupt.h> ++#include <linux/module.h> ++#include <linux/pm_runtime.h> ++#include <linux/slab.h> ++#include <linux/spinlock.h> ++ ++#include "../dmaengine.h" ++ ++/* DMA descriptor control */ ++enum shdma_desc_status { ++ DESC_IDLE, ++ DESC_PREPARED, ++ DESC_SUBMITTED, ++ DESC_COMPLETED, /* completed, have to call callback */ ++ DESC_WAITING, /* callback called, waiting for ack / re-submit */ ++}; ++ ++#define NR_DESCS_PER_CHANNEL 32 ++ ++#define to_shdma_chan(c) container_of(c, struct shdma_chan, dma_chan) ++#define to_shdma_dev(d) container_of(d, struct shdma_dev, dma_dev) ++ ++/* ++ * For slave DMA we assume, that there is a finite number of DMA slaves in the ++ * system, and that each such slave can only use a finite number of channels. ++ * We use slave channel IDs to make sure, that no such slave channel ID is ++ * allocated more than once. ++ */ ++static unsigned int slave_num = 256; ++module_param(slave_num, uint, 0444); ++ ++/* A bitmask with slave_num bits */ ++static unsigned long *shdma_slave_used; ++ ++/* Called under spin_lock_irq(&schan->chan_lock") */ ++static void shdma_chan_xfer_ld_queue(struct shdma_chan *schan) ++{ ++ struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device); ++ const struct shdma_ops *ops = sdev->ops; ++ struct shdma_desc *sdesc; ++ ++ /* DMA work check */ ++ if (ops->channel_busy(schan)) ++ return; ++ ++ /* Find the first not transferred descriptor */ ++ list_for_each_entry(sdesc, &schan->ld_queue, node) ++ if (sdesc->mark == DESC_SUBMITTED) { ++ ops->start_xfer(schan, sdesc); ++ break; ++ } ++} ++ ++static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx) ++{ ++ struct shdma_desc *chunk, *c, *desc = ++ container_of(tx, struct shdma_desc, async_tx), ++ *last = desc; ++ struct shdma_chan *schan = to_shdma_chan(tx->chan); ++ struct shdma_slave *slave = tx->chan->private; ++ dma_async_tx_callback callback = tx->callback; ++ dma_cookie_t cookie; ++ bool power_up; ++ ++ spin_lock_irq(&schan->chan_lock); ++ ++ power_up = list_empty(&schan->ld_queue); ++ ++ cookie = dma_cookie_assign(tx); ++ ++ /* Mark all chunks of this descriptor as submitted, move to the queue */ ++ list_for_each_entry_safe(chunk, c, desc->node.prev, node) { ++ /* ++ * All chunks are on the global ld_free, so, we have to find ++ * the end of the chain ourselves ++ */ ++ if (chunk != desc && (chunk->mark == DESC_IDLE || ++ chunk->async_tx.cookie > 0 || ++ chunk->async_tx.cookie == -EBUSY || ++ &chunk->node == &schan->ld_free)) ++ break; ++ chunk->mark = DESC_SUBMITTED; ++ /* Callback goes to the last chunk */ ++ chunk->async_tx.callback = NULL; ++ chunk->cookie = cookie; ++ list_move_tail(&chunk->node, &schan->ld_queue); ++ last = chunk; ++ ++ dev_dbg(schan->dev, "submit #%d@%p on %d\n", ++ tx->cookie, &last->async_tx, schan->id); ++ } ++ ++ last->async_tx.callback = callback; ++ last->async_tx.callback_param = tx->callback_param; ++ ++ if (power_up) { ++ int ret; ++ schan->pm_state = SHDMA_PM_BUSY; ++ ++ ret = pm_runtime_get(schan->dev); ++ ++ spin_unlock_irq(&schan->chan_lock); ++ if (ret < 0) ++ dev_err(schan->dev, "%s(): GET = %d\n", __func__, ret); ++ ++ pm_runtime_barrier(schan->dev); ++ ++ spin_lock_irq(&schan->chan_lock); ++ ++ /* Have we been reset, while waiting? */ ++ if (schan->pm_state != SHDMA_PM_ESTABLISHED) { ++ struct shdma_dev *sdev = ++ to_shdma_dev(schan->dma_chan.device); ++ const struct shdma_ops *ops = sdev->ops; ++ dev_dbg(schan->dev, "Bring up channel %d\n", ++ schan->id); ++ /* ++ * TODO: .xfer_setup() might fail on some platforms. ++ * Make it int then, on error remove chunks from the ++ * queue again ++ */ ++ ops->setup_xfer(schan, slave); ++ ++ if (schan->pm_state == SHDMA_PM_PENDING) ++ shdma_chan_xfer_ld_queue(schan); ++ schan->pm_state = SHDMA_PM_ESTABLISHED; ++ } ++ } else { ++ /* ++ * Tell .device_issue_pending() not to run the queue, interrupts ++ * will do it anyway ++ */ ++ schan->pm_state = SHDMA_PM_PENDING; ++ } ++ ++ spin_unlock_irq(&schan->chan_lock); ++ ++ return cookie; ++} ++ ++/* Called with desc_lock held */ ++static struct shdma_desc *shdma_get_desc(struct shdma_chan *schan) ++{ ++ struct shdma_desc *sdesc; ++ ++ list_for_each_entry(sdesc, &schan->ld_free, node) ++ if (sdesc->mark != DESC_PREPARED) { ++ BUG_ON(sdesc->mark != DESC_IDLE); ++ list_del(&sdesc->node); ++ return sdesc; ++ } ++ ++ return NULL; ++} ++ ++static int shdma_alloc_chan_resources(struct dma_chan *chan) ++{ ++ struct shdma_chan *schan = to_shdma_chan(chan); ++ struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device); ++ const struct shdma_ops *ops = sdev->ops; ++ struct shdma_desc *desc; ++ struct shdma_slave *slave = chan->private; ++ int ret, i; ++ ++ /* ++ * This relies on the guarantee from dmaengine that alloc_chan_resources ++ * never runs concurrently with itself or free_chan_resources. ++ */ ++ if (slave) { ++ if (slave->slave_id >= slave_num) { ++ ret = -EINVAL; ++ goto evalid; ++ } ++ ++ if (test_and_set_bit(slave->slave_id, shdma_slave_used)) { ++ ret = -EBUSY; ++ goto etestused; ++ } ++ ++ ret = ops->set_slave(schan, slave); ++ if (ret < 0) ++ goto esetslave; ++ } ++ ++ schan->desc = kcalloc(NR_DESCS_PER_CHANNEL, ++ sdev->desc_size, GFP_KERNEL); ++ if (!schan->desc) { ++ ret = -ENOMEM; ++ goto edescalloc; ++ } ++ schan->desc_num = NR_DESCS_PER_CHANNEL; ++ ++ for (i = 0; i < NR_DESCS_PER_CHANNEL; i++) { ++ desc = ops->embedded_desc(schan->desc, i); ++ dma_async_tx_descriptor_init(&desc->async_tx, ++ &schan->dma_chan); ++ desc->async_tx.tx_submit = shdma_tx_submit; ++ desc->mark = DESC_IDLE; ++ ++ list_add(&desc->node, &schan->ld_free); ++ } ++ ++ return NR_DESCS_PER_CHANNEL; ++ ++edescalloc: ++ if (slave) ++esetslave: ++ clear_bit(slave->slave_id, shdma_slave_used); ++etestused: ++evalid: ++ chan->private = NULL; ++ return ret; ++} ++ ++static dma_async_tx_callback __ld_cleanup(struct shdma_chan *schan, bool all) ++{ ++ struct shdma_desc *desc, *_desc; ++ /* Is the "exposed" head of a chain acked? */ ++ bool head_acked = false; ++ dma_cookie_t cookie = 0; ++ dma_async_tx_callback callback = NULL; ++ void *param = NULL; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&schan->chan_lock, flags); ++ list_for_each_entry_safe(desc, _desc, &schan->ld_queue, node) { ++ struct dma_async_tx_descriptor *tx = &desc->async_tx; ++ ++ BUG_ON(tx->cookie > 0 && tx->cookie != desc->cookie); ++ BUG_ON(desc->mark != DESC_SUBMITTED && ++ desc->mark != DESC_COMPLETED && ++ desc->mark != DESC_WAITING); ++ ++ /* ++ * queue is ordered, and we use this loop to (1) clean up all ++ * completed descriptors, and to (2) update descriptor flags of ++ * any chunks in a (partially) completed chain ++ */ ++ if (!all && desc->mark == DESC_SUBMITTED && ++ desc->cookie != cookie) ++ break; ++ ++ if (tx->cookie > 0) ++ cookie = tx->cookie; ++ ++ if (desc->mark == DESC_COMPLETED && desc->chunks == 1) { ++ if (schan->dma_chan.completed_cookie != desc->cookie - 1) ++ dev_dbg(schan->dev, ++ "Completing cookie %d, expected %d\n", ++ desc->cookie, ++ schan->dma_chan.completed_cookie + 1); ++ schan->dma_chan.completed_cookie = desc->cookie; ++ } ++ ++ /* Call callback on the last chunk */ ++ if (desc->mark == DESC_COMPLETED && tx->callback) { ++ desc->mark = DESC_WAITING; ++ callback = tx->callback; ++ param = tx->callback_param; ++ dev_dbg(schan->dev, "descriptor #%d@%p on %d callback\n", ++ tx->cookie, tx, schan->id); ++ BUG_ON(desc->chunks != 1); ++ break; ++ } ++ ++ if (tx->cookie > 0 || tx->cookie == -EBUSY) { ++ if (desc->mark == DESC_COMPLETED) { ++ BUG_ON(tx->cookie < 0); ++ desc->mark = DESC_WAITING; ++ } ++ head_acked = async_tx_test_ack(tx); ++ } else { ++ switch (desc->mark) { ++ case DESC_COMPLETED: ++ desc->mark = DESC_WAITING; ++ /* Fall through */ ++ case DESC_WAITING: ++ if (head_acked) ++ async_tx_ack(&desc->async_tx); ++ } ++ } ++ ++ dev_dbg(schan->dev, "descriptor %p #%d completed.\n", ++ tx, tx->cookie); ++ ++ if (((desc->mark == DESC_COMPLETED || ++ desc->mark == DESC_WAITING) && ++ async_tx_test_ack(&desc->async_tx)) || all) { ++ /* Remove from ld_queue list */ ++ desc->mark = DESC_IDLE; ++ ++ list_move(&desc->node, &schan->ld_free); ++ ++ if (list_empty(&schan->ld_queue)) { ++ dev_dbg(schan->dev, "Bring down channel %d\n", schan->id); ++ pm_runtime_put(schan->dev); ++ schan->pm_state = SHDMA_PM_ESTABLISHED; ++ } ++ } ++ } ++ ++ if (all && !callback) ++ /* ++ * Terminating and the loop completed normally: forgive ++ * uncompleted cookies ++ */ ++ schan->dma_chan.completed_cookie = schan->dma_chan.cookie; ++ ++ spin_unlock_irqrestore(&schan->chan_lock, flags); ++ ++ if (callback) ++ callback(param); ++ ++ return callback; ++} ++ ++/* ++ * shdma_chan_ld_cleanup - Clean up link descriptors ++ * ++ * Clean up the ld_queue of DMA channel. ++ */ ++static void shdma_chan_ld_cleanup(struct shdma_chan *schan, bool all) ++{ ++ while (__ld_cleanup(schan, all)) ++ ; ++} ++ ++/* ++ * shdma_free_chan_resources - Free all resources of the channel. ++ */ ++static void shdma_free_chan_resources(struct dma_chan *chan) ++{ ++ struct shdma_chan *schan = to_shdma_chan(chan); ++ struct shdma_dev *sdev = to_shdma_dev(chan->device); ++ const struct shdma_ops *ops = sdev->ops; ++ LIST_HEAD(list); ++ ++ /* Protect against ISR */ ++ spin_lock_irq(&schan->chan_lock); ++ ops->halt_channel(schan); ++ spin_unlock_irq(&schan->chan_lock); ++ ++ /* Now no new interrupts will occur */ ++ ++ /* Prepared and not submitted descriptors can still be on the queue */ ++ if (!list_empty(&schan->ld_queue)) ++ shdma_chan_ld_cleanup(schan, true); ++ ++ if (chan->private) { ++ /* The caller is holding dma_list_mutex */ ++ struct shdma_slave *slave = chan->private; ++ clear_bit(slave->slave_id, shdma_slave_used); ++ chan->private = NULL; ++ } ++ ++ spin_lock_irq(&schan->chan_lock); ++ ++ list_splice_init(&schan->ld_free, &list); ++ schan->desc_num = 0; ++ ++ spin_unlock_irq(&schan->chan_lock); ++ ++ kfree(schan->desc); ++} ++ ++/** ++ * shdma_add_desc - get, set up and return one transfer descriptor ++ * @schan: DMA channel ++ * @flags: DMA transfer flags ++ * @dst: destination DMA address, incremented when direction equals ++ * DMA_DEV_TO_MEM or DMA_MEM_TO_MEM ++ * @src: source DMA address, incremented when direction equals ++ * DMA_MEM_TO_DEV or DMA_MEM_TO_MEM ++ * @len: DMA transfer length ++ * @first: if NULL, set to the current descriptor and cookie set to -EBUSY ++ * @direction: needed for slave DMA to decide which address to keep constant, ++ * equals DMA_MEM_TO_MEM for MEMCPY ++ * Returns 0 or an error ++ * Locks: called with desc_lock held ++ */ ++static struct shdma_desc *shdma_add_desc(struct shdma_chan *schan, ++ unsigned long flags, dma_addr_t *dst, dma_addr_t *src, size_t *len, ++ struct shdma_desc **first, enum dma_transfer_direction direction) ++{ ++ struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device); ++ const struct shdma_ops *ops = sdev->ops; ++ struct shdma_desc *new; ++ size_t copy_size = *len; ++ ++ if (!copy_size) ++ return NULL; ++ ++ /* Allocate the link descriptor from the free list */ ++ new = shdma_get_desc(schan); ++ if (!new) { ++ dev_err(schan->dev, "No free link descriptor available\n"); ++ return NULL; ++ } ++ ++ ops->desc_setup(schan, new, *src, *dst, ©_size); ++ ++ if (!*first) { ++ /* First desc */ ++ new->async_tx.cookie = -EBUSY; ++ *first = new; ++ } else { ++ /* Other desc - invisible to the user */ ++ new->async_tx.cookie = -EINVAL; ++ } ++ ++ dev_dbg(schan->dev, ++ "chaining (%u/%u)@%x -> %x with %p, cookie %d\n", ++ copy_size, *len, *src, *dst, &new->async_tx, ++ new->async_tx.cookie); ++ ++ new->mark = DESC_PREPARED; ++ new->async_tx.flags = flags; ++ new->direction = direction; ++ ++ *len -= copy_size; ++ if (direction == DMA_MEM_TO_MEM || direction == DMA_MEM_TO_DEV) ++ *src += copy_size; ++ if (direction == DMA_MEM_TO_MEM || direction == DMA_DEV_TO_MEM) ++ *dst += copy_size; ++ ++ return new; ++} ++ ++/* ++ * shdma_prep_sg - prepare transfer descriptors from an SG list ++ * ++ * Common routine for public (MEMCPY) and slave DMA. The MEMCPY case is also ++ * converted to scatter-gather to guarantee consistent locking and a correct ++ * list manipulation. For slave DMA direction carries the usual meaning, and, ++ * logically, the SG list is RAM and the addr variable contains slave address, ++ * e.g., the FIFO I/O register. For MEMCPY direction equals DMA_MEM_TO_MEM ++ * and the SG list contains only one element and points at the source buffer. ++ */ ++static struct dma_async_tx_descriptor *shdma_prep_sg(struct shdma_chan *schan, ++ struct scatterlist *sgl, unsigned int sg_len, dma_addr_t *addr, ++ enum dma_transfer_direction direction, unsigned long flags) ++{ ++ struct scatterlist *sg; ++ struct shdma_desc *first = NULL, *new = NULL /* compiler... */; ++ LIST_HEAD(tx_list); ++ int chunks = 0; ++ unsigned long irq_flags; ++ int i; ++ ++ for_each_sg(sgl, sg, sg_len, i) ++ chunks += DIV_ROUND_UP(sg_dma_len(sg), schan->max_xfer_len); ++ ++ /* Have to lock the whole loop to protect against concurrent release */ ++ spin_lock_irqsave(&schan->chan_lock, irq_flags); ++ ++ /* ++ * Chaining: ++ * first descriptor is what user is dealing with in all API calls, its ++ * cookie is at first set to -EBUSY, at tx-submit to a positive ++ * number ++ * if more than one chunk is needed further chunks have cookie = -EINVAL ++ * the last chunk, if not equal to the first, has cookie = -ENOSPC ++ * all chunks are linked onto the tx_list head with their .node heads ++ * only during this function, then they are immediately spliced ++ * back onto the free list in form of a chain ++ */ ++ for_each_sg(sgl, sg, sg_len, i) { ++ dma_addr_t sg_addr = sg_dma_address(sg); ++ size_t len = sg_dma_len(sg); ++ ++ if (!len) ++ goto err_get_desc; ++ ++ do { ++ dev_dbg(schan->dev, "Add SG #%d@%p[%d], dma %llx\n", ++ i, sg, len, (unsigned long long)sg_addr); ++ ++ if (direction == DMA_DEV_TO_MEM) ++ new = shdma_add_desc(schan, flags, ++ &sg_addr, addr, &len, &first, ++ direction); ++ else ++ new = shdma_add_desc(schan, flags, ++ addr, &sg_addr, &len, &first, ++ direction); ++ if (!new) ++ goto err_get_desc; ++ ++ new->chunks = chunks--; ++ list_add_tail(&new->node, &tx_list); ++ } while (len); ++ } ++ ++ if (new != first) ++ new->async_tx.cookie = -ENOSPC; ++ ++ /* Put them back on the free list, so, they don't get lost */ ++ list_splice_tail(&tx_list, &schan->ld_free); ++ ++ spin_unlock_irqrestore(&schan->chan_lock, irq_flags); ++ ++ return &first->async_tx; ++ ++err_get_desc: ++ list_for_each_entry(new, &tx_list, node) ++ new->mark = DESC_IDLE; ++ list_splice(&tx_list, &schan->ld_free); ++ ++ spin_unlock_irqrestore(&schan->chan_lock, irq_flags); ++ ++ return NULL; ++} ++ ++static struct dma_async_tx_descriptor *shdma_prep_memcpy( ++ struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src, ++ size_t len, unsigned long flags) ++{ ++ struct shdma_chan *schan = to_shdma_chan(chan); ++ struct scatterlist sg; ++ ++ if (!chan || !len) ++ return NULL; ++ ++ BUG_ON(!schan->desc_num); ++ ++ sg_init_table(&sg, 1); ++ sg_set_page(&sg, pfn_to_page(PFN_DOWN(dma_src)), len, ++ offset_in_page(dma_src)); ++ sg_dma_address(&sg) = dma_src; ++ sg_dma_len(&sg) = len; ++ ++ return shdma_prep_sg(schan, &sg, 1, &dma_dest, DMA_MEM_TO_MEM, flags); ++} ++ ++static struct dma_async_tx_descriptor *shdma_prep_slave_sg( ++ struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, ++ enum dma_transfer_direction direction, unsigned long flags, void *context) ++{ ++ struct shdma_chan *schan = to_shdma_chan(chan); ++ struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device); ++ const struct shdma_ops *ops = sdev->ops; ++ struct shdma_slave *slave = chan->private; ++ dma_addr_t slave_addr; ++ ++ if (!chan) ++ return NULL; ++ ++ BUG_ON(!schan->desc_num); ++ ++ /* Someone calling slave DMA on a generic channel? */ ++ if (!slave || !sg_len) { ++ dev_warn(schan->dev, "%s: bad parameter: %p, %d, %d\n", ++ __func__, slave, sg_len, slave ? slave->slave_id : -1); ++ return NULL; ++ } ++ ++ slave_addr = ops->slave_addr(schan); ++ ++ return shdma_prep_sg(schan, sgl, sg_len, &slave_addr, ++ direction, flags); ++} ++ ++static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, ++ unsigned long arg) ++{ ++ struct shdma_chan *schan = to_shdma_chan(chan); ++ struct shdma_dev *sdev = to_shdma_dev(chan->device); ++ const struct shdma_ops *ops = sdev->ops; ++ unsigned long flags; ++ ++ /* Only supports DMA_TERMINATE_ALL */ ++ if (cmd != DMA_TERMINATE_ALL) ++ return -ENXIO; ++ ++ if (!chan) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&schan->chan_lock, flags); ++ ++ ops->halt_channel(schan); ++ ++ spin_unlock_irqrestore(&schan->chan_lock, flags); ++ ++ shdma_chan_ld_cleanup(schan, true); ++ ++ return 0; ++} ++ ++static void shdma_issue_pending(struct dma_chan *chan) ++{ ++ struct shdma_chan *schan = to_shdma_chan(chan); ++ ++ spin_lock_irq(&schan->chan_lock); ++ if (schan->pm_state == SHDMA_PM_ESTABLISHED) ++ shdma_chan_xfer_ld_queue(schan); ++ else ++ schan->pm_state = SHDMA_PM_PENDING; ++ spin_unlock_irq(&schan->chan_lock); ++} ++ ++static enum dma_status shdma_tx_status(struct dma_chan *chan, ++ dma_cookie_t cookie, ++ struct dma_tx_state *txstate) ++{ ++ struct shdma_chan *schan = to_shdma_chan(chan); ++ enum dma_status status; ++ unsigned long flags; ++ ++ shdma_chan_ld_cleanup(schan, false); ++ ++ spin_lock_irqsave(&schan->chan_lock, flags); ++ ++ status = dma_cookie_status(chan, cookie, txstate); ++ ++ /* ++ * If we don't find cookie on the queue, it has been aborted and we have ++ * to report error ++ */ ++ if (status != DMA_SUCCESS) { ++ struct shdma_desc *sdesc; ++ status = DMA_ERROR; ++ list_for_each_entry(sdesc, &schan->ld_queue, node) ++ if (sdesc->cookie == cookie) { ++ status = DMA_IN_PROGRESS; ++ break; ++ } ++ } ++ ++ spin_unlock_irqrestore(&schan->chan_lock, flags); ++ ++ return status; ++} ++ ++/* Called from error IRQ or NMI */ ++bool shdma_reset(struct shdma_dev *sdev) ++{ ++ const struct shdma_ops *ops = sdev->ops; ++ struct shdma_chan *schan; ++ unsigned int handled = 0; ++ int i; ++ ++ /* Reset all channels */ ++ shdma_for_each_chan(schan, sdev, i) { ++ struct shdma_desc *sdesc; ++ LIST_HEAD(dl); ++ ++ if (!schan) ++ continue; ++ ++ spin_lock(&schan->chan_lock); ++ ++ /* Stop the channel */ ++ ops->halt_channel(schan); ++ ++ list_splice_init(&schan->ld_queue, &dl); ++ ++ if (!list_empty(&dl)) { ++ dev_dbg(schan->dev, "Bring down channel %d\n", schan->id); ++ pm_runtime_put(schan->dev); ++ } ++ schan->pm_state = SHDMA_PM_ESTABLISHED; ++ ++ spin_unlock(&schan->chan_lock); ++ ++ /* Complete all */ ++ list_for_each_entry(sdesc, &dl, node) { ++ struct dma_async_tx_descriptor *tx = &sdesc->async_tx; ++ sdesc->mark = DESC_IDLE; ++ if (tx->callback) ++ tx->callback(tx->callback_param); ++ } ++ ++ spin_lock(&schan->chan_lock); ++ list_splice(&dl, &schan->ld_free); ++ spin_unlock(&schan->chan_lock); ++ ++ handled++; ++ } ++ ++ return !!handled; ++} ++EXPORT_SYMBOL(shdma_reset); ++ ++static irqreturn_t chan_irq(int irq, void *dev) ++{ ++ struct shdma_chan *schan = dev; ++ const struct shdma_ops *ops = ++ to_shdma_dev(schan->dma_chan.device)->ops; ++ irqreturn_t ret; ++ ++ spin_lock(&schan->chan_lock); ++ ++ ret = ops->chan_irq(schan, irq) ? IRQ_WAKE_THREAD : IRQ_NONE; ++ ++ spin_unlock(&schan->chan_lock); ++ ++ return ret; ++} ++ ++static irqreturn_t chan_irqt(int irq, void *dev) ++{ ++ struct shdma_chan *schan = dev; ++ const struct shdma_ops *ops = ++ to_shdma_dev(schan->dma_chan.device)->ops; ++ struct shdma_desc *sdesc; ++ ++ spin_lock_irq(&schan->chan_lock); ++ list_for_each_entry(sdesc, &schan->ld_queue, node) { ++ if (sdesc->mark == DESC_SUBMITTED && ++ ops->desc_completed(schan, sdesc)) { ++ dev_dbg(schan->dev, "done #%d@%p\n", ++ sdesc->async_tx.cookie, &sdesc->async_tx); ++ sdesc->mark = DESC_COMPLETED; ++ break; ++ } ++ } ++ /* Next desc */ ++ shdma_chan_xfer_ld_queue(schan); ++ spin_unlock_irq(&schan->chan_lock); ++ ++ shdma_chan_ld_cleanup(schan, false); ++ ++ return IRQ_HANDLED; ++} ++ ++int shdma_request_irq(struct shdma_chan *schan, int irq, ++ unsigned long flags, const char *name) ++{ ++ int ret = request_threaded_irq(irq, chan_irq, chan_irqt, ++ flags, name, schan); ++ ++ schan->irq = ret < 0 ? ret : irq; ++ ++ return ret; ++} ++EXPORT_SYMBOL(shdma_request_irq); ++ ++void shdma_free_irq(struct shdma_chan *schan) ++{ ++ if (schan->irq >= 0) ++ free_irq(schan->irq, schan); ++} ++EXPORT_SYMBOL(shdma_free_irq); ++ ++void shdma_chan_probe(struct shdma_dev *sdev, ++ struct shdma_chan *schan, int id) ++{ ++ schan->pm_state = SHDMA_PM_ESTABLISHED; ++ ++ /* reference struct dma_device */ ++ schan->dma_chan.device = &sdev->dma_dev; ++ dma_cookie_init(&schan->dma_chan); ++ ++ schan->dev = sdev->dma_dev.dev; ++ schan->id = id; ++ ++ if (!schan->max_xfer_len) ++ schan->max_xfer_len = PAGE_SIZE; ++ ++ spin_lock_init(&schan->chan_lock); ++ ++ /* Init descripter manage list */ ++ INIT_LIST_HEAD(&schan->ld_queue); ++ INIT_LIST_HEAD(&schan->ld_free); ++ ++ /* Add the channel to DMA device channel list */ ++ list_add_tail(&schan->dma_chan.device_node, ++ &sdev->dma_dev.channels); ++ sdev->schan[sdev->dma_dev.chancnt++] = schan; ++} ++EXPORT_SYMBOL(shdma_chan_probe); ++ ++void shdma_chan_remove(struct shdma_chan *schan) ++{ ++ list_del(&schan->dma_chan.device_node); ++} ++EXPORT_SYMBOL(shdma_chan_remove); ++ ++int shdma_init(struct device *dev, struct shdma_dev *sdev, ++ int chan_num) ++{ ++ struct dma_device *dma_dev = &sdev->dma_dev; ++ ++ /* ++ * Require all call-backs for now, they can trivially be made optional ++ * later as required ++ */ ++ if (!sdev->ops || ++ !sdev->desc_size || ++ !sdev->ops->embedded_desc || ++ !sdev->ops->start_xfer || ++ !sdev->ops->setup_xfer || ++ !sdev->ops->set_slave || ++ !sdev->ops->desc_setup || ++ !sdev->ops->slave_addr || ++ !sdev->ops->channel_busy || ++ !sdev->ops->halt_channel || ++ !sdev->ops->desc_completed) ++ return -EINVAL; ++ ++ sdev->schan = kcalloc(chan_num, sizeof(*sdev->schan), GFP_KERNEL); ++ if (!sdev->schan) ++ return -ENOMEM; ++ ++ INIT_LIST_HEAD(&dma_dev->channels); ++ ++ /* Common and MEMCPY operations */ ++ dma_dev->device_alloc_chan_resources ++ = shdma_alloc_chan_resources; ++ dma_dev->device_free_chan_resources = shdma_free_chan_resources; ++ dma_dev->device_prep_dma_memcpy = shdma_prep_memcpy; ++ dma_dev->device_tx_status = shdma_tx_status; ++ dma_dev->device_issue_pending = shdma_issue_pending; ++ ++ /* Compulsory for DMA_SLAVE fields */ ++ dma_dev->device_prep_slave_sg = shdma_prep_slave_sg; ++ dma_dev->device_control = shdma_control; ++ ++ dma_dev->dev = dev; ++ ++ return 0; ++} ++EXPORT_SYMBOL(shdma_init); ++ ++void shdma_cleanup(struct shdma_dev *sdev) ++{ ++ kfree(sdev->schan); ++} ++EXPORT_SYMBOL(shdma_cleanup); ++ ++static int __init shdma_enter(void) ++{ ++ shdma_slave_used = kzalloc(DIV_ROUND_UP(slave_num, BITS_PER_LONG) * ++ sizeof(long), GFP_KERNEL); ++ if (!shdma_slave_used) ++ return -ENOMEM; ++ return 0; ++} ++module_init(shdma_enter); ++ ++static void __exit shdma_exit(void) ++{ ++ kfree(shdma_slave_used); ++} ++module_exit(shdma_exit); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("SH-DMA driver base library"); ++MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); +diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h +new file mode 100644 +index 0000000..83efd13 +--- /dev/null ++++ b/include/linux/shdma-base.h +@@ -0,0 +1,123 @@ ++/* ++ * Dmaengine driver base library for DMA controllers, found on SH-based SoCs ++ * ++ * extracted from shdma.c and headers ++ * ++ * Copyright (C) 2011-2012 Guennadi Liakhovetski <g.liakhovetski@gmx.de> ++ * Copyright (C) 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com> ++ * Copyright (C) 2009 Renesas Solutions, Inc. All rights reserved. ++ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved. ++ * ++ * This is free software; you can redistribute it and/or modify ++ * it under the terms of version 2 of the GNU General Public License as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef SHDMA_BASE_H ++#define SHDMA_BASE_H ++ ++#include <linux/dmaengine.h> ++#include <linux/interrupt.h> ++#include <linux/list.h> ++#include <linux/types.h> ++ ++/** ++ * shdma_pm_state - DMA channel PM state ++ * SHDMA_PM_ESTABLISHED: either idle or during data transfer ++ * SHDMA_PM_BUSY: during the transfer preparation, when we have to ++ * drop the lock temporarily ++ * SHDMA_PM_PENDING: transfers pending ++ */ ++enum shdma_pm_state { ++ SHDMA_PM_ESTABLISHED, ++ SHDMA_PM_BUSY, ++ SHDMA_PM_PENDING, ++}; ++ ++struct device; ++ ++/* ++ * Drivers, using this library are expected to embed struct shdma_dev, ++ * struct shdma_chan, struct shdma_desc, and struct shdma_slave ++ * in their respective device, channel, descriptor and slave objects. ++ */ ++ ++struct shdma_slave { ++ unsigned int slave_id; ++}; ++ ++struct shdma_desc { ++ struct list_head node; ++ struct dma_async_tx_descriptor async_tx; ++ enum dma_transfer_direction direction; ++ dma_cookie_t cookie; ++ int chunks; ++ int mark; ++}; ++ ++struct shdma_chan { ++ spinlock_t chan_lock; /* Channel operation lock */ ++ struct list_head ld_queue; /* Link descriptors queue */ ++ struct list_head ld_free; /* Free link descriptors */ ++ struct dma_chan dma_chan; /* DMA channel */ ++ struct device *dev; /* Channel device */ ++ void *desc; /* buffer for descriptor array */ ++ int desc_num; /* desc count */ ++ size_t max_xfer_len; /* max transfer length */ ++ int id; /* Raw id of this channel */ ++ int irq; /* Channel IRQ */ ++ enum shdma_pm_state pm_state; ++}; ++ ++/** ++ * struct shdma_ops - simple DMA driver operations ++ * desc_completed: return true, if this is the descriptor, that just has ++ * completed (atomic) ++ * halt_channel: stop DMA channel operation (atomic) ++ * channel_busy: return true, if the channel is busy (atomic) ++ * slave_addr: return slave DMA address ++ * desc_setup: set up the hardware specific descriptor portion (atomic) ++ * set_slave: bind channel to a slave ++ * setup_xfer: configure channel hardware for operation (atomic) ++ * start_xfer: start the DMA transfer (atomic) ++ * embedded_desc: return Nth struct shdma_desc pointer from the ++ * descriptor array ++ * chan_irq: process channel IRQ, return true if a transfer has ++ * completed (atomic) ++ */ ++struct shdma_ops { ++ bool (*desc_completed)(struct shdma_chan *, struct shdma_desc *); ++ void (*halt_channel)(struct shdma_chan *); ++ bool (*channel_busy)(struct shdma_chan *); ++ dma_addr_t (*slave_addr)(struct shdma_chan *); ++ int (*desc_setup)(struct shdma_chan *, struct shdma_desc *, ++ dma_addr_t, dma_addr_t, size_t *); ++ int (*set_slave)(struct shdma_chan *, struct shdma_slave *); ++ void (*setup_xfer)(struct shdma_chan *, struct shdma_slave *); ++ void (*start_xfer)(struct shdma_chan *, struct shdma_desc *); ++ struct shdma_desc *(*embedded_desc)(void *, int); ++ bool (*chan_irq)(struct shdma_chan *, int); ++}; ++ ++struct shdma_dev { ++ struct dma_device dma_dev; ++ struct shdma_chan **schan; ++ const struct shdma_ops *ops; ++ size_t desc_size; ++}; ++ ++#define shdma_for_each_chan(c, d, i) for (i = 0, c = (d)->schan[0]; \ ++ i < (d)->dma_dev.chancnt; c = (d)->schan[++i]) ++ ++int shdma_request_irq(struct shdma_chan *, int, ++ unsigned long, const char *); ++void shdma_free_irq(struct shdma_chan *); ++bool shdma_reset(struct shdma_dev *sdev); ++void shdma_chan_probe(struct shdma_dev *sdev, ++ struct shdma_chan *schan, int id); ++void shdma_chan_remove(struct shdma_chan *schan); ++int shdma_init(struct device *dev, struct shdma_dev *sdev, ++ int chan_num); ++void shdma_cleanup(struct shdma_dev *sdev); ++ ++#endif +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0050-dma-shdma-prepare-for-conversion-to-the-shdma-base-l.patch b/patches.marzen/0050-dma-shdma-prepare-for-conversion-to-the-shdma-base-l.patch new file mode 100644 index 0000000000000..c035e948cf9cf --- /dev/null +++ b/patches.marzen/0050-dma-shdma-prepare-for-conversion-to-the-shdma-base-l.patch @@ -0,0 +1,44 @@ +From ede599a5d672322a39cf12cc4fdb59fe67898908 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 9 May 2012 17:09:14 +0200 +Subject: dma: shdma: prepare for conversion to the shdma base library + +By placing an anonymous union at the top of struct sh_dmae_slave we can +transparently prepare all device and client drivers for the upcoming +shdma-base conversion. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit 5902c9a7a2a9c2520af54af1ba7a9c7831664a17) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/sh_dma.h | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h +index 425450b..e081e8e 100644 +--- a/include/linux/sh_dma.h ++++ b/include/linux/sh_dma.h +@@ -10,12 +10,16 @@ + #ifndef SH_DMA_H + #define SH_DMA_H + +-#include <linux/list.h> + #include <linux/dmaengine.h> ++#include <linux/list.h> ++#include <linux/shdma-base.h> + + /* Used by slave DMA clients to request DMA to/from a specific peripheral */ + struct sh_dmae_slave { +- unsigned int slave_id; /* Set by the platform */ ++ union { ++ unsigned int slave_id; /* Set by the platform */ ++ struct shdma_slave shdma_slave; ++ }; + struct device *dma_dev; /* Set by the platform */ + const struct sh_dmae_slave_config *config; /* Set by the driver */ + }; +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0051-ASoC-fsi-prepare-for-conversion-to-the-shdma-base-li.patch b/patches.marzen/0051-ASoC-fsi-prepare-for-conversion-to-the-shdma-base-li.patch new file mode 100644 index 0000000000000..bba8d95b89fca --- /dev/null +++ b/patches.marzen/0051-ASoC-fsi-prepare-for-conversion-to-the-shdma-base-li.patch @@ -0,0 +1,30 @@ +From 6381d33c361574132c3152d0cfa56278a67d40f7 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 9 May 2012 17:09:20 +0200 +Subject: ASoC: fsi: prepare for conversion to the shdma base library + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Cc: Liam Girdwood <lrg@ti.com> +Cc: Mark Brown <broonie@opensource.wolfsonmicro.com> +Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit b8373147ed3ca01a968d81f22688f2836a9aeb6b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + sound/soc/sh/fsi.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -1533,8 +1533,8 @@ static void fsi_handler_init(struct fsi_ + fsi->capture.priv = fsi; + + if (fsi->info->tx_id) { +- fsi->playback.slave.slave_id = fsi->info->tx_id; +- fsi->playback.handler = &fsi_dma_push_handler; ++ fsi->playback.slave.shdma_slave.slave_id = fsi->info->tx_id; ++ fsi->playback.handler = &fsi_dma_push_handler; + } + } + diff --git a/patches.marzen/0052-usb-renesas_usbhs-prepare-for-conversion-to-the-shdm.patch b/patches.marzen/0052-usb-renesas_usbhs-prepare-for-conversion-to-the-shdm.patch new file mode 100644 index 0000000000000..4a3b49df3679c --- /dev/null +++ b/patches.marzen/0052-usb-renesas_usbhs-prepare-for-conversion-to-the-shdm.patch @@ -0,0 +1,55 @@ +From a840c360c6d890060307ee970d8630f9bf812af1 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 9 May 2012 17:09:19 +0200 +Subject: usb: renesas_usbhs: prepare for conversion to the shdma base library + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit f19b7e0db7744dd1ed6052cc58a90b74a29772b8) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/usb/renesas_usbhs/fifo.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c +index 6ec7f83..fc597a4 100644 +--- a/drivers/usb/renesas_usbhs/fifo.c ++++ b/drivers/usb/renesas_usbhs/fifo.c +@@ -994,7 +994,7 @@ static bool usbhsf_dma_filter(struct dma_chan *chan, void *param) + * + * usbhs doesn't recognize id = 0 as valid DMA + */ +- if (0 == slave->slave_id) ++ if (0 == slave->shdma_slave.slave_id) + return false; + + chan->private = slave; +@@ -1173,8 +1173,8 @@ int usbhs_fifo_probe(struct usbhs_priv *priv) + fifo->port = D0FIFO; + fifo->sel = D0FIFOSEL; + fifo->ctr = D0FIFOCTR; +- fifo->tx_slave.slave_id = usbhs_get_dparam(priv, d0_tx_id); +- fifo->rx_slave.slave_id = usbhs_get_dparam(priv, d0_rx_id); ++ fifo->tx_slave.shdma_slave.slave_id = usbhs_get_dparam(priv, d0_tx_id); ++ fifo->rx_slave.shdma_slave.slave_id = usbhs_get_dparam(priv, d0_rx_id); + + /* D1FIFO */ + fifo = usbhsf_get_d1fifo(priv); +@@ -1182,8 +1182,8 @@ int usbhs_fifo_probe(struct usbhs_priv *priv) + fifo->port = D1FIFO; + fifo->sel = D1FIFOSEL; + fifo->ctr = D1FIFOCTR; +- fifo->tx_slave.slave_id = usbhs_get_dparam(priv, d1_tx_id); +- fifo->rx_slave.slave_id = usbhs_get_dparam(priv, d1_rx_id); ++ fifo->tx_slave.shdma_slave.slave_id = usbhs_get_dparam(priv, d1_tx_id); ++ fifo->rx_slave.shdma_slave.slave_id = usbhs_get_dparam(priv, d1_rx_id); + + return 0; + } +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0053-dma-shdma-convert-to-the-shdma-base-library.patch b/patches.marzen/0053-dma-shdma-convert-to-the-shdma-base-library.patch new file mode 100644 index 0000000000000..674d5484dc134 --- /dev/null +++ b/patches.marzen/0053-dma-shdma-convert-to-the-shdma-base-library.patch @@ -0,0 +1,1561 @@ +From 67976cd109fc26028e9fbcede6badbf236d865e8 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 9 May 2012 17:09:21 +0200 +Subject: dma: shdma: convert to the shdma base library + +The shdma base library has originally been extracted from the shdma driver, +which now can be converted to actually use it. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit ce3a1ab74264b860450709e4bd0dcfc2d0bfc7f8) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/dma/sh/shdma.c | 1122 ++++++++++++------------------------------------ + drivers/dma/sh/shdma.h | 44 +- + include/linux/sh_dma.h | 33 +- + 3 files changed, 302 insertions(+), 897 deletions(-) + +diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c +index 8ab4a1f..c393b35 100644 +--- a/drivers/dma/sh/shdma.c ++++ b/drivers/dma/sh/shdma.c +@@ -3,6 +3,7 @@ + * + * base is drivers/dma/flsdma.c + * ++ * Copyright (C) 2011-2012 Guennadi Liakhovetski <g.liakhovetski@gmx.de> + * Copyright (C) 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com> + * Copyright (C) 2009 Renesas Solutions, Inc. All rights reserved. + * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved. +@@ -34,18 +35,12 @@ + #include "../dmaengine.h" + #include "shdma.h" + +-/* DMA descriptor control */ +-enum sh_dmae_desc_status { +- DESC_IDLE, +- DESC_PREPARED, +- DESC_SUBMITTED, +- DESC_COMPLETED, /* completed, have to call callback */ +- DESC_WAITING, /* callback called, waiting for ack / re-submit */ +-}; ++#define SH_DMAE_DRV_NAME "sh-dma-engine" + +-#define NR_DESCS_PER_CHANNEL 32 + /* Default MEMCPY transfer size = 2^2 = 4 bytes */ + #define LOG2_DEFAULT_XFER_SIZE 2 ++#define SH_DMA_SLAVE_NUMBER 256 ++#define SH_DMA_TCR_MAX (16 * 1024 * 1024 - 1) + + /* + * Used for write-side mutual exclusion for the global device list, +@@ -54,18 +49,12 @@ enum sh_dmae_desc_status { + static DEFINE_SPINLOCK(sh_dmae_lock); + static LIST_HEAD(sh_dmae_devices); + +-/* A bitmask with bits enough for enum sh_dmae_slave_chan_id */ +-static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SH_DMA_SLAVE_NUMBER)]; +- +-static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all); +-static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan); +- + static void chclr_write(struct sh_dmae_chan *sh_dc, u32 data) + { + struct sh_dmae_device *shdev = to_sh_dev(sh_dc); + + __raw_writel(data, shdev->chan_reg + +- shdev->pdata->channel[sh_dc->id].chclr_offset); ++ shdev->pdata->channel[sh_dc->shdma_chan.id].chclr_offset); + } + + static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg) +@@ -155,11 +144,11 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev) + spin_unlock_irqrestore(&sh_dmae_lock, flags); + + if (dmaor & (DMAOR_AE | DMAOR_NMIF)) { +- dev_warn(shdev->common.dev, "Can't initialize DMAOR.\n"); ++ dev_warn(shdev->shdma_dev.dma_dev.dev, "Can't initialize DMAOR.\n"); + return -EIO; + } + if (shdev->pdata->dmaor_init & ~dmaor) +- dev_warn(shdev->common.dev, ++ dev_warn(shdev->shdma_dev.dma_dev.dev, + "DMAOR=0x%x hasn't latched the initial value 0x%x.\n", + dmaor, shdev->pdata->dmaor_init); + return 0; +@@ -224,15 +213,6 @@ static void dmae_start(struct sh_dmae_chan *sh_chan) + chcr_write(sh_chan, chcr & ~CHCR_TE); + } + +-static void dmae_halt(struct sh_dmae_chan *sh_chan) +-{ +- struct sh_dmae_device *shdev = to_sh_dev(sh_chan); +- u32 chcr = chcr_read(sh_chan); +- +- chcr &= ~(CHCR_DE | CHCR_TE | shdev->chcr_ie_bit); +- chcr_write(sh_chan, chcr); +-} +- + static void dmae_init(struct sh_dmae_chan *sh_chan) + { + /* +@@ -261,7 +241,7 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val) + { + struct sh_dmae_device *shdev = to_sh_dev(sh_chan); + struct sh_dmae_pdata *pdata = shdev->pdata; +- const struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id]; ++ const struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->shdma_chan.id]; + u16 __iomem *addr = shdev->dmars; + unsigned int shift = chan_pdata->dmars_bit; + +@@ -282,706 +262,142 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val) + return 0; + } + +-static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx) ++static void sh_dmae_start_xfer(struct shdma_chan *schan, ++ struct shdma_desc *sdesc) + { +- struct sh_desc *desc = tx_to_sh_desc(tx), *chunk, *last = desc, *c; +- struct sh_dmae_chan *sh_chan = to_sh_chan(tx->chan); +- struct sh_dmae_slave *param = tx->chan->private; +- dma_async_tx_callback callback = tx->callback; +- dma_cookie_t cookie; +- bool power_up; +- +- spin_lock_irq(&sh_chan->desc_lock); +- +- if (list_empty(&sh_chan->ld_queue)) +- power_up = true; +- else +- power_up = false; +- +- cookie = dma_cookie_assign(tx); +- +- /* Mark all chunks of this descriptor as submitted, move to the queue */ +- list_for_each_entry_safe(chunk, c, desc->node.prev, node) { +- /* +- * All chunks are on the global ld_free, so, we have to find +- * the end of the chain ourselves +- */ +- if (chunk != desc && (chunk->mark == DESC_IDLE || +- chunk->async_tx.cookie > 0 || +- chunk->async_tx.cookie == -EBUSY || +- &chunk->node == &sh_chan->ld_free)) +- break; +- chunk->mark = DESC_SUBMITTED; +- /* Callback goes to the last chunk */ +- chunk->async_tx.callback = NULL; +- chunk->cookie = cookie; +- list_move_tail(&chunk->node, &sh_chan->ld_queue); +- last = chunk; +- } +- +- last->async_tx.callback = callback; +- last->async_tx.callback_param = tx->callback_param; +- +- dev_dbg(sh_chan->dev, "submit #%d@%p on %d: %x[%d] -> %x\n", +- tx->cookie, &last->async_tx, sh_chan->id, +- desc->hw.sar, desc->hw.tcr, desc->hw.dar); +- +- if (power_up) { +- sh_chan->pm_state = DMAE_PM_BUSY; +- +- pm_runtime_get(sh_chan->dev); +- +- spin_unlock_irq(&sh_chan->desc_lock); +- +- pm_runtime_barrier(sh_chan->dev); +- +- spin_lock_irq(&sh_chan->desc_lock); +- +- /* Have we been reset, while waiting? */ +- if (sh_chan->pm_state != DMAE_PM_ESTABLISHED) { +- dev_dbg(sh_chan->dev, "Bring up channel %d\n", +- sh_chan->id); +- if (param) { +- const struct sh_dmae_slave_config *cfg = +- param->config; +- +- dmae_set_dmars(sh_chan, cfg->mid_rid); +- dmae_set_chcr(sh_chan, cfg->chcr); +- } else { +- dmae_init(sh_chan); +- } +- +- if (sh_chan->pm_state == DMAE_PM_PENDING) +- sh_chan_xfer_ld_queue(sh_chan); +- sh_chan->pm_state = DMAE_PM_ESTABLISHED; +- } +- } else { +- sh_chan->pm_state = DMAE_PM_PENDING; +- } +- +- spin_unlock_irq(&sh_chan->desc_lock); +- +- return cookie; ++ struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan, ++ shdma_chan); ++ struct sh_dmae_desc *sh_desc = container_of(sdesc, ++ struct sh_dmae_desc, shdma_desc); ++ dev_dbg(sh_chan->shdma_chan.dev, "Queue #%d to %d: %u@%x -> %x\n", ++ sdesc->async_tx.cookie, sh_chan->shdma_chan.id, ++ sh_desc->hw.tcr, sh_desc->hw.sar, sh_desc->hw.dar); ++ /* Get the ld start address from ld_queue */ ++ dmae_set_reg(sh_chan, &sh_desc->hw); ++ dmae_start(sh_chan); + } + +-/* Called with desc_lock held */ +-static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan) ++static bool sh_dmae_channel_busy(struct shdma_chan *schan) + { +- struct sh_desc *desc; +- +- list_for_each_entry(desc, &sh_chan->ld_free, node) +- if (desc->mark != DESC_PREPARED) { +- BUG_ON(desc->mark != DESC_IDLE); +- list_del(&desc->node); +- return desc; +- } +- +- return NULL; ++ struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan, ++ shdma_chan); ++ return dmae_is_busy(sh_chan); + } + +-static const struct sh_dmae_slave_config *sh_dmae_find_slave( +- struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *param) ++static void sh_dmae_setup_xfer(struct shdma_chan *schan, ++ struct shdma_slave *sslave) + { +- struct sh_dmae_device *shdev = to_sh_dev(sh_chan); +- struct sh_dmae_pdata *pdata = shdev->pdata; +- int i; ++ struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan, ++ shdma_chan); + +- if (param->slave_id >= SH_DMA_SLAVE_NUMBER) +- return NULL; +- +- for (i = 0; i < pdata->slave_num; i++) +- if (pdata->slave[i].slave_id == param->slave_id) +- return pdata->slave + i; +- +- return NULL; +-} +- +-static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) +-{ +- struct sh_dmae_chan *sh_chan = to_sh_chan(chan); +- struct sh_desc *desc; +- struct sh_dmae_slave *param = chan->private; +- int ret; ++ if (sslave) { ++ struct sh_dmae_slave *slave = container_of(sslave, ++ struct sh_dmae_slave, shdma_slave); ++ const struct sh_dmae_slave_config *cfg = ++ slave->config; + +- /* +- * This relies on the guarantee from dmaengine that alloc_chan_resources +- * never runs concurrently with itself or free_chan_resources. +- */ +- if (param) { +- const struct sh_dmae_slave_config *cfg; +- +- cfg = sh_dmae_find_slave(sh_chan, param); +- if (!cfg) { +- ret = -EINVAL; +- goto efindslave; +- } +- +- if (test_and_set_bit(param->slave_id, sh_dmae_slave_used)) { +- ret = -EBUSY; +- goto etestused; +- } +- +- param->config = cfg; +- } +- +- while (sh_chan->descs_allocated < NR_DESCS_PER_CHANNEL) { +- desc = kzalloc(sizeof(struct sh_desc), GFP_KERNEL); +- if (!desc) +- break; +- dma_async_tx_descriptor_init(&desc->async_tx, +- &sh_chan->common); +- desc->async_tx.tx_submit = sh_dmae_tx_submit; +- desc->mark = DESC_IDLE; +- +- list_add(&desc->node, &sh_chan->ld_free); +- sh_chan->descs_allocated++; +- } +- +- if (!sh_chan->descs_allocated) { +- ret = -ENOMEM; +- goto edescalloc; +- } +- +- return sh_chan->descs_allocated; +- +-edescalloc: +- if (param) +- clear_bit(param->slave_id, sh_dmae_slave_used); +-etestused: +-efindslave: +- chan->private = NULL; +- return ret; +-} +- +-/* +- * sh_dma_free_chan_resources - Free all resources of the channel. +- */ +-static void sh_dmae_free_chan_resources(struct dma_chan *chan) +-{ +- struct sh_dmae_chan *sh_chan = to_sh_chan(chan); +- struct sh_desc *desc, *_desc; +- LIST_HEAD(list); +- +- /* Protect against ISR */ +- spin_lock_irq(&sh_chan->desc_lock); +- dmae_halt(sh_chan); +- spin_unlock_irq(&sh_chan->desc_lock); +- +- /* Now no new interrupts will occur */ +- +- /* Prepared and not submitted descriptors can still be on the queue */ +- if (!list_empty(&sh_chan->ld_queue)) +- sh_dmae_chan_ld_cleanup(sh_chan, true); +- +- if (chan->private) { +- /* The caller is holding dma_list_mutex */ +- struct sh_dmae_slave *param = chan->private; +- clear_bit(param->slave_id, sh_dmae_slave_used); +- chan->private = NULL; +- } +- +- spin_lock_irq(&sh_chan->desc_lock); +- +- list_splice_init(&sh_chan->ld_free, &list); +- sh_chan->descs_allocated = 0; +- +- spin_unlock_irq(&sh_chan->desc_lock); +- +- list_for_each_entry_safe(desc, _desc, &list, node) +- kfree(desc); +-} +- +-/** +- * sh_dmae_add_desc - get, set up and return one transfer descriptor +- * @sh_chan: DMA channel +- * @flags: DMA transfer flags +- * @dest: destination DMA address, incremented when direction equals +- * DMA_DEV_TO_MEM +- * @src: source DMA address, incremented when direction equals +- * DMA_MEM_TO_DEV +- * @len: DMA transfer length +- * @first: if NULL, set to the current descriptor and cookie set to -EBUSY +- * @direction: needed for slave DMA to decide which address to keep constant, +- * equals DMA_MEM_TO_MEM for MEMCPY +- * Returns 0 or an error +- * Locks: called with desc_lock held +- */ +-static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan, +- unsigned long flags, dma_addr_t *dest, dma_addr_t *src, size_t *len, +- struct sh_desc **first, enum dma_transfer_direction direction) +-{ +- struct sh_desc *new; +- size_t copy_size; +- +- if (!*len) +- return NULL; +- +- /* Allocate the link descriptor from the free list */ +- new = sh_dmae_get_desc(sh_chan); +- if (!new) { +- dev_err(sh_chan->dev, "No free link descriptor available\n"); +- return NULL; +- } +- +- copy_size = min(*len, (size_t)SH_DMA_TCR_MAX + 1); +- +- new->hw.sar = *src; +- new->hw.dar = *dest; +- new->hw.tcr = copy_size; +- +- if (!*first) { +- /* First desc */ +- new->async_tx.cookie = -EBUSY; +- *first = new; ++ dmae_set_dmars(sh_chan, cfg->mid_rid); ++ dmae_set_chcr(sh_chan, cfg->chcr); + } else { +- /* Other desc - invisible to the user */ +- new->async_tx.cookie = -EINVAL; ++ dmae_init(sh_chan); + } +- +- dev_dbg(sh_chan->dev, +- "chaining (%u/%u)@%x -> %x with %p, cookie %d, shift %d\n", +- copy_size, *len, *src, *dest, &new->async_tx, +- new->async_tx.cookie, sh_chan->xmit_shift); +- +- new->mark = DESC_PREPARED; +- new->async_tx.flags = flags; +- new->direction = direction; +- +- *len -= copy_size; +- if (direction == DMA_MEM_TO_MEM || direction == DMA_MEM_TO_DEV) +- *src += copy_size; +- if (direction == DMA_MEM_TO_MEM || direction == DMA_DEV_TO_MEM) +- *dest += copy_size; +- +- return new; + } + +-/* +- * sh_dmae_prep_sg - prepare transfer descriptors from an SG list +- * +- * Common routine for public (MEMCPY) and slave DMA. The MEMCPY case is also +- * converted to scatter-gather to guarantee consistent locking and a correct +- * list manipulation. For slave DMA direction carries the usual meaning, and, +- * logically, the SG list is RAM and the addr variable contains slave address, +- * e.g., the FIFO I/O register. For MEMCPY direction equals DMA_MEM_TO_MEM +- * and the SG list contains only one element and points at the source buffer. +- */ +-static struct dma_async_tx_descriptor *sh_dmae_prep_sg(struct sh_dmae_chan *sh_chan, +- struct scatterlist *sgl, unsigned int sg_len, dma_addr_t *addr, +- enum dma_transfer_direction direction, unsigned long flags) ++static const struct sh_dmae_slave_config *dmae_find_slave( ++ struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *slave) + { +- struct scatterlist *sg; +- struct sh_desc *first = NULL, *new = NULL /* compiler... */; +- LIST_HEAD(tx_list); +- int chunks = 0; +- unsigned long irq_flags; ++ struct sh_dmae_device *shdev = to_sh_dev(sh_chan); ++ struct sh_dmae_pdata *pdata = shdev->pdata; ++ const struct sh_dmae_slave_config *cfg; + int i; + +- if (!sg_len) ++ if (slave->shdma_slave.slave_id >= SH_DMA_SLAVE_NUMBER) + return NULL; + +- for_each_sg(sgl, sg, sg_len, i) +- chunks += (sg_dma_len(sg) + SH_DMA_TCR_MAX) / +- (SH_DMA_TCR_MAX + 1); +- +- /* Have to lock the whole loop to protect against concurrent release */ +- spin_lock_irqsave(&sh_chan->desc_lock, irq_flags); +- +- /* +- * Chaining: +- * first descriptor is what user is dealing with in all API calls, its +- * cookie is at first set to -EBUSY, at tx-submit to a positive +- * number +- * if more than one chunk is needed further chunks have cookie = -EINVAL +- * the last chunk, if not equal to the first, has cookie = -ENOSPC +- * all chunks are linked onto the tx_list head with their .node heads +- * only during this function, then they are immediately spliced +- * back onto the free list in form of a chain +- */ +- for_each_sg(sgl, sg, sg_len, i) { +- dma_addr_t sg_addr = sg_dma_address(sg); +- size_t len = sg_dma_len(sg); +- +- if (!len) +- goto err_get_desc; +- +- do { +- dev_dbg(sh_chan->dev, "Add SG #%d@%p[%d], dma %llx\n", +- i, sg, len, (unsigned long long)sg_addr); +- +- if (direction == DMA_DEV_TO_MEM) +- new = sh_dmae_add_desc(sh_chan, flags, +- &sg_addr, addr, &len, &first, +- direction); +- else +- new = sh_dmae_add_desc(sh_chan, flags, +- addr, &sg_addr, &len, &first, +- direction); +- if (!new) +- goto err_get_desc; +- +- new->chunks = chunks--; +- list_add_tail(&new->node, &tx_list); +- } while (len); +- } +- +- if (new != first) +- new->async_tx.cookie = -ENOSPC; +- +- /* Put them back on the free list, so, they don't get lost */ +- list_splice_tail(&tx_list, &sh_chan->ld_free); +- +- spin_unlock_irqrestore(&sh_chan->desc_lock, irq_flags); +- +- return &first->async_tx; +- +-err_get_desc: +- list_for_each_entry(new, &tx_list, node) +- new->mark = DESC_IDLE; +- list_splice(&tx_list, &sh_chan->ld_free); +- +- spin_unlock_irqrestore(&sh_chan->desc_lock, irq_flags); ++ for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++) ++ if (cfg->slave_id == slave->shdma_slave.slave_id) ++ return cfg; + + return NULL; + } + +-static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy( +- struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src, +- size_t len, unsigned long flags) ++static int sh_dmae_set_slave(struct shdma_chan *schan, ++ struct shdma_slave *sslave) + { +- struct sh_dmae_chan *sh_chan; +- struct scatterlist sg; +- +- if (!chan || !len) +- return NULL; +- +- sh_chan = to_sh_chan(chan); +- +- sg_init_table(&sg, 1); +- sg_set_page(&sg, pfn_to_page(PFN_DOWN(dma_src)), len, +- offset_in_page(dma_src)); +- sg_dma_address(&sg) = dma_src; +- sg_dma_len(&sg) = len; +- +- return sh_dmae_prep_sg(sh_chan, &sg, 1, &dma_dest, DMA_MEM_TO_MEM, +- flags); +-} +- +-static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg( +- struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, +- enum dma_transfer_direction direction, unsigned long flags, +- void *context) +-{ +- struct sh_dmae_slave *param; +- struct sh_dmae_chan *sh_chan; +- dma_addr_t slave_addr; +- +- if (!chan) +- return NULL; +- +- sh_chan = to_sh_chan(chan); +- param = chan->private; +- +- /* Someone calling slave DMA on a public channel? */ +- if (!param || !sg_len) { +- dev_warn(sh_chan->dev, "%s: bad parameter: %p, %d, %d\n", +- __func__, param, sg_len, param ? param->slave_id : -1); +- return NULL; +- } +- +- slave_addr = param->config->addr; +- +- /* +- * if (param != NULL), this is a successfully requested slave channel, +- * therefore param->config != NULL too. +- */ +- return sh_dmae_prep_sg(sh_chan, sgl, sg_len, &slave_addr, +- direction, flags); +-} +- +-static int sh_dmae_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, +- unsigned long arg) +-{ +- struct sh_dmae_chan *sh_chan = to_sh_chan(chan); +- unsigned long flags; +- +- /* Only supports DMA_TERMINATE_ALL */ +- if (cmd != DMA_TERMINATE_ALL) +- return -ENXIO; +- +- if (!chan) +- return -EINVAL; +- +- spin_lock_irqsave(&sh_chan->desc_lock, flags); +- dmae_halt(sh_chan); +- +- if (!list_empty(&sh_chan->ld_queue)) { +- /* Record partial transfer */ +- struct sh_desc *desc = list_entry(sh_chan->ld_queue.next, +- struct sh_desc, node); +- desc->partial = (desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) << +- sh_chan->xmit_shift; +- } +- spin_unlock_irqrestore(&sh_chan->desc_lock, flags); ++ struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan, ++ shdma_chan); ++ struct sh_dmae_slave *slave = container_of(sslave, struct sh_dmae_slave, ++ shdma_slave); ++ const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, slave); ++ if (!cfg) ++ return -ENODEV; + +- sh_dmae_chan_ld_cleanup(sh_chan, true); ++ slave->config = cfg; + + return 0; + } + +-static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all) ++static void dmae_halt(struct sh_dmae_chan *sh_chan) + { +- struct sh_desc *desc, *_desc; +- /* Is the "exposed" head of a chain acked? */ +- bool head_acked = false; +- dma_cookie_t cookie = 0; +- dma_async_tx_callback callback = NULL; +- void *param = NULL; +- unsigned long flags; +- +- spin_lock_irqsave(&sh_chan->desc_lock, flags); +- list_for_each_entry_safe(desc, _desc, &sh_chan->ld_queue, node) { +- struct dma_async_tx_descriptor *tx = &desc->async_tx; +- +- BUG_ON(tx->cookie > 0 && tx->cookie != desc->cookie); +- BUG_ON(desc->mark != DESC_SUBMITTED && +- desc->mark != DESC_COMPLETED && +- desc->mark != DESC_WAITING); +- +- /* +- * queue is ordered, and we use this loop to (1) clean up all +- * completed descriptors, and to (2) update descriptor flags of +- * any chunks in a (partially) completed chain +- */ +- if (!all && desc->mark == DESC_SUBMITTED && +- desc->cookie != cookie) +- break; +- +- if (tx->cookie > 0) +- cookie = tx->cookie; +- +- if (desc->mark == DESC_COMPLETED && desc->chunks == 1) { +- if (sh_chan->common.completed_cookie != desc->cookie - 1) +- dev_dbg(sh_chan->dev, +- "Completing cookie %d, expected %d\n", +- desc->cookie, +- sh_chan->common.completed_cookie + 1); +- sh_chan->common.completed_cookie = desc->cookie; +- } +- +- /* Call callback on the last chunk */ +- if (desc->mark == DESC_COMPLETED && tx->callback) { +- desc->mark = DESC_WAITING; +- callback = tx->callback; +- param = tx->callback_param; +- dev_dbg(sh_chan->dev, "descriptor #%d@%p on %d callback\n", +- tx->cookie, tx, sh_chan->id); +- BUG_ON(desc->chunks != 1); +- break; +- } +- +- if (tx->cookie > 0 || tx->cookie == -EBUSY) { +- if (desc->mark == DESC_COMPLETED) { +- BUG_ON(tx->cookie < 0); +- desc->mark = DESC_WAITING; +- } +- head_acked = async_tx_test_ack(tx); +- } else { +- switch (desc->mark) { +- case DESC_COMPLETED: +- desc->mark = DESC_WAITING; +- /* Fall through */ +- case DESC_WAITING: +- if (head_acked) +- async_tx_ack(&desc->async_tx); +- } +- } +- +- dev_dbg(sh_chan->dev, "descriptor %p #%d completed.\n", +- tx, tx->cookie); +- +- if (((desc->mark == DESC_COMPLETED || +- desc->mark == DESC_WAITING) && +- async_tx_test_ack(&desc->async_tx)) || all) { +- /* Remove from ld_queue list */ +- desc->mark = DESC_IDLE; +- +- list_move(&desc->node, &sh_chan->ld_free); +- +- if (list_empty(&sh_chan->ld_queue)) { +- dev_dbg(sh_chan->dev, "Bring down channel %d\n", sh_chan->id); +- pm_runtime_put(sh_chan->dev); +- } +- } +- } +- +- if (all && !callback) +- /* +- * Terminating and the loop completed normally: forgive +- * uncompleted cookies +- */ +- sh_chan->common.completed_cookie = sh_chan->common.cookie; +- +- spin_unlock_irqrestore(&sh_chan->desc_lock, flags); +- +- if (callback) +- callback(param); ++ struct sh_dmae_device *shdev = to_sh_dev(sh_chan); ++ u32 chcr = chcr_read(sh_chan); + +- return callback; ++ chcr &= ~(CHCR_DE | CHCR_TE | shdev->chcr_ie_bit); ++ chcr_write(sh_chan, chcr); + } + +-/* +- * sh_chan_ld_cleanup - Clean up link descriptors +- * +- * This function cleans up the ld_queue of DMA channel. +- */ +-static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all) ++static int sh_dmae_desc_setup(struct shdma_chan *schan, ++ struct shdma_desc *sdesc, ++ dma_addr_t src, dma_addr_t dst, size_t *len) + { +- while (__ld_cleanup(sh_chan, all)) +- ; +-} ++ struct sh_dmae_desc *sh_desc = container_of(sdesc, ++ struct sh_dmae_desc, shdma_desc); + +-/* Called under spin_lock_irq(&sh_chan->desc_lock) */ +-static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan) +-{ +- struct sh_desc *desc; ++ if (*len > schan->max_xfer_len) ++ *len = schan->max_xfer_len; + +- /* DMA work check */ +- if (dmae_is_busy(sh_chan)) +- return; +- +- /* Find the first not transferred descriptor */ +- list_for_each_entry(desc, &sh_chan->ld_queue, node) +- if (desc->mark == DESC_SUBMITTED) { +- dev_dbg(sh_chan->dev, "Queue #%d to %d: %u@%x -> %x\n", +- desc->async_tx.cookie, sh_chan->id, +- desc->hw.tcr, desc->hw.sar, desc->hw.dar); +- /* Get the ld start address from ld_queue */ +- dmae_set_reg(sh_chan, &desc->hw); +- dmae_start(sh_chan); +- break; +- } +-} ++ sh_desc->hw.sar = src; ++ sh_desc->hw.dar = dst; ++ sh_desc->hw.tcr = *len; + +-static void sh_dmae_memcpy_issue_pending(struct dma_chan *chan) +-{ +- struct sh_dmae_chan *sh_chan = to_sh_chan(chan); +- +- spin_lock_irq(&sh_chan->desc_lock); +- if (sh_chan->pm_state == DMAE_PM_ESTABLISHED) +- sh_chan_xfer_ld_queue(sh_chan); +- else +- sh_chan->pm_state = DMAE_PM_PENDING; +- spin_unlock_irq(&sh_chan->desc_lock); ++ return 0; + } + +-static enum dma_status sh_dmae_tx_status(struct dma_chan *chan, +- dma_cookie_t cookie, +- struct dma_tx_state *txstate) ++static void sh_dmae_halt(struct shdma_chan *schan) + { +- struct sh_dmae_chan *sh_chan = to_sh_chan(chan); +- enum dma_status status; +- unsigned long flags; +- +- sh_dmae_chan_ld_cleanup(sh_chan, false); +- +- spin_lock_irqsave(&sh_chan->desc_lock, flags); +- +- status = dma_cookie_status(chan, cookie, txstate); +- +- /* +- * If we don't find cookie on the queue, it has been aborted and we have +- * to report error +- */ +- if (status != DMA_SUCCESS) { +- struct sh_desc *desc; +- status = DMA_ERROR; +- list_for_each_entry(desc, &sh_chan->ld_queue, node) +- if (desc->cookie == cookie) { +- status = DMA_IN_PROGRESS; +- break; +- } +- } +- +- spin_unlock_irqrestore(&sh_chan->desc_lock, flags); +- +- return status; ++ struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan, ++ shdma_chan); ++ dmae_halt(sh_chan); + } + +-static irqreturn_t sh_dmae_interrupt(int irq, void *data) ++static bool sh_dmae_chan_irq(struct shdma_chan *schan, int irq) + { +- irqreturn_t ret = IRQ_NONE; +- struct sh_dmae_chan *sh_chan = data; +- u32 chcr; +- +- spin_lock(&sh_chan->desc_lock); +- +- chcr = chcr_read(sh_chan); ++ struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan, ++ shdma_chan); + +- if (chcr & CHCR_TE) { +- /* DMA stop */ +- dmae_halt(sh_chan); +- +- ret = IRQ_HANDLED; +- tasklet_schedule(&sh_chan->tasklet); +- } ++ if (!(chcr_read(sh_chan) & CHCR_TE)) ++ return false; + +- spin_unlock(&sh_chan->desc_lock); ++ /* DMA stop */ ++ dmae_halt(sh_chan); + +- return ret; ++ return true; + } + + /* Called from error IRQ or NMI */ + static bool sh_dmae_reset(struct sh_dmae_device *shdev) + { +- unsigned int handled = 0; +- int i; ++ bool ret; + + /* halt the dma controller */ + sh_dmae_ctl_stop(shdev); + + /* We cannot detect, which channel caused the error, have to reset all */ +- for (i = 0; i < SH_DMAC_MAX_CHANNELS; i++) { +- struct sh_dmae_chan *sh_chan = shdev->chan[i]; +- struct sh_desc *desc; +- LIST_HEAD(dl); +- +- if (!sh_chan) +- continue; +- +- spin_lock(&sh_chan->desc_lock); +- +- /* Stop the channel */ +- dmae_halt(sh_chan); +- +- list_splice_init(&sh_chan->ld_queue, &dl); +- +- if (!list_empty(&dl)) { +- dev_dbg(sh_chan->dev, "Bring down channel %d\n", sh_chan->id); +- pm_runtime_put(sh_chan->dev); +- } +- sh_chan->pm_state = DMAE_PM_ESTABLISHED; +- +- spin_unlock(&sh_chan->desc_lock); +- +- /* Complete all */ +- list_for_each_entry(desc, &dl, node) { +- struct dma_async_tx_descriptor *tx = &desc->async_tx; +- desc->mark = DESC_IDLE; +- if (tx->callback) +- tx->callback(tx->callback_param); +- } +- +- spin_lock(&sh_chan->desc_lock); +- list_splice(&dl, &sh_chan->ld_free); +- spin_unlock(&sh_chan->desc_lock); +- +- handled++; +- } ++ ret = shdma_reset(&shdev->shdma_dev); + + sh_dmae_rst(shdev); + +- return !!handled; ++ return ret; + } + + static irqreturn_t sh_dmae_err(int irq, void *data) +@@ -991,35 +407,24 @@ static irqreturn_t sh_dmae_err(int irq, void *data) + if (!(dmaor_read(shdev) & DMAOR_AE)) + return IRQ_NONE; + +- sh_dmae_reset(data); ++ sh_dmae_reset(shdev); + return IRQ_HANDLED; + } + +-static void dmae_do_tasklet(unsigned long data) ++static bool sh_dmae_desc_completed(struct shdma_chan *schan, ++ struct shdma_desc *sdesc) + { +- struct sh_dmae_chan *sh_chan = (struct sh_dmae_chan *)data; +- struct sh_desc *desc; ++ struct sh_dmae_chan *sh_chan = container_of(schan, ++ struct sh_dmae_chan, shdma_chan); ++ struct sh_dmae_desc *sh_desc = container_of(sdesc, ++ struct sh_dmae_desc, shdma_desc); + u32 sar_buf = sh_dmae_readl(sh_chan, SAR); + u32 dar_buf = sh_dmae_readl(sh_chan, DAR); + +- spin_lock_irq(&sh_chan->desc_lock); +- list_for_each_entry(desc, &sh_chan->ld_queue, node) { +- if (desc->mark == DESC_SUBMITTED && +- ((desc->direction == DMA_DEV_TO_MEM && +- (desc->hw.dar + desc->hw.tcr) == dar_buf) || +- (desc->hw.sar + desc->hw.tcr) == sar_buf)) { +- dev_dbg(sh_chan->dev, "done #%d@%p dst %u\n", +- desc->async_tx.cookie, &desc->async_tx, +- desc->hw.dar); +- desc->mark = DESC_COMPLETED; +- break; +- } +- } +- /* Next desc */ +- sh_chan_xfer_ld_queue(sh_chan); +- spin_unlock_irq(&sh_chan->desc_lock); +- +- sh_dmae_chan_ld_cleanup(sh_chan, false); ++ return (sdesc->direction == DMA_DEV_TO_MEM && ++ (sh_desc->hw.dar + sh_desc->hw.tcr) == dar_buf) || ++ (sdesc->direction != DMA_DEV_TO_MEM && ++ (sh_desc->hw.sar + sh_desc->hw.tcr) == sar_buf); + } + + static bool sh_dmae_nmi_notify(struct sh_dmae_device *shdev) +@@ -1073,97 +478,174 @@ static struct notifier_block sh_dmae_nmi_notifier __read_mostly = { + static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id, + int irq, unsigned long flags) + { +- int err; + const struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id]; +- struct platform_device *pdev = to_platform_device(shdev->common.dev); +- struct sh_dmae_chan *new_sh_chan; ++ struct shdma_dev *sdev = &shdev->shdma_dev; ++ struct platform_device *pdev = to_platform_device(sdev->dma_dev.dev); ++ struct sh_dmae_chan *sh_chan; ++ struct shdma_chan *schan; ++ int err; + +- /* alloc channel */ +- new_sh_chan = kzalloc(sizeof(struct sh_dmae_chan), GFP_KERNEL); +- if (!new_sh_chan) { +- dev_err(shdev->common.dev, ++ sh_chan = kzalloc(sizeof(struct sh_dmae_chan), GFP_KERNEL); ++ if (!sh_chan) { ++ dev_err(sdev->dma_dev.dev, + "No free memory for allocating dma channels!\n"); + return -ENOMEM; + } + +- new_sh_chan->pm_state = DMAE_PM_ESTABLISHED; +- +- /* reference struct dma_device */ +- new_sh_chan->common.device = &shdev->common; +- dma_cookie_init(&new_sh_chan->common); ++ schan = &sh_chan->shdma_chan; ++ schan->max_xfer_len = SH_DMA_TCR_MAX + 1; + +- new_sh_chan->dev = shdev->common.dev; +- new_sh_chan->id = id; +- new_sh_chan->irq = irq; +- new_sh_chan->base = shdev->chan_reg + chan_pdata->offset / sizeof(u32); ++ shdma_chan_probe(sdev, schan, id); + +- /* Init DMA tasklet */ +- tasklet_init(&new_sh_chan->tasklet, dmae_do_tasklet, +- (unsigned long)new_sh_chan); +- +- spin_lock_init(&new_sh_chan->desc_lock); +- +- /* Init descripter manage list */ +- INIT_LIST_HEAD(&new_sh_chan->ld_queue); +- INIT_LIST_HEAD(&new_sh_chan->ld_free); +- +- /* Add the channel to DMA device channel list */ +- list_add_tail(&new_sh_chan->common.device_node, +- &shdev->common.channels); +- shdev->common.chancnt++; ++ sh_chan->base = shdev->chan_reg + chan_pdata->offset / sizeof(u32); + ++ /* set up channel irq */ + if (pdev->id >= 0) +- snprintf(new_sh_chan->dev_id, sizeof(new_sh_chan->dev_id), +- "sh-dmae%d.%d", pdev->id, new_sh_chan->id); ++ snprintf(sh_chan->dev_id, sizeof(sh_chan->dev_id), ++ "sh-dmae%d.%d", pdev->id, id); + else +- snprintf(new_sh_chan->dev_id, sizeof(new_sh_chan->dev_id), +- "sh-dma%d", new_sh_chan->id); ++ snprintf(sh_chan->dev_id, sizeof(sh_chan->dev_id), ++ "sh-dma%d", id); + +- /* set up channel irq */ +- err = request_irq(irq, &sh_dmae_interrupt, flags, +- new_sh_chan->dev_id, new_sh_chan); ++ err = shdma_request_irq(schan, irq, flags, sh_chan->dev_id); + if (err) { +- dev_err(shdev->common.dev, "DMA channel %d request_irq error " +- "with return %d\n", id, err); ++ dev_err(sdev->dma_dev.dev, ++ "DMA channel %d request_irq error %d\n", ++ id, err); + goto err_no_irq; + } + +- shdev->chan[id] = new_sh_chan; ++ shdev->chan[id] = sh_chan; + return 0; + + err_no_irq: + /* remove from dmaengine device node */ +- list_del(&new_sh_chan->common.device_node); +- kfree(new_sh_chan); ++ shdma_chan_remove(schan); ++ kfree(sh_chan); + return err; + } + + static void sh_dmae_chan_remove(struct sh_dmae_device *shdev) + { ++ struct dma_device *dma_dev = &shdev->shdma_dev.dma_dev; ++ struct shdma_chan *schan; + int i; + +- for (i = shdev->common.chancnt - 1 ; i >= 0 ; i--) { +- if (shdev->chan[i]) { +- struct sh_dmae_chan *sh_chan = shdev->chan[i]; ++ shdma_for_each_chan(schan, &shdev->shdma_dev, i) { ++ struct sh_dmae_chan *sh_chan = container_of(schan, ++ struct sh_dmae_chan, shdma_chan); ++ BUG_ON(!schan); + +- free_irq(sh_chan->irq, sh_chan); ++ shdma_free_irq(&sh_chan->shdma_chan); + +- list_del(&sh_chan->common.device_node); +- kfree(sh_chan); +- shdev->chan[i] = NULL; ++ shdma_chan_remove(schan); ++ kfree(sh_chan); ++ } ++ dma_dev->chancnt = 0; ++} ++ ++static void sh_dmae_shutdown(struct platform_device *pdev) ++{ ++ struct sh_dmae_device *shdev = platform_get_drvdata(pdev); ++ sh_dmae_ctl_stop(shdev); ++} ++ ++static int sh_dmae_runtime_suspend(struct device *dev) ++{ ++ return 0; ++} ++ ++static int sh_dmae_runtime_resume(struct device *dev) ++{ ++ struct sh_dmae_device *shdev = dev_get_drvdata(dev); ++ ++ return sh_dmae_rst(shdev); ++} ++ ++#ifdef CONFIG_PM ++static int sh_dmae_suspend(struct device *dev) ++{ ++ return 0; ++} ++ ++static int sh_dmae_resume(struct device *dev) ++{ ++ struct sh_dmae_device *shdev = dev_get_drvdata(dev); ++ int i, ret; ++ ++ ret = sh_dmae_rst(shdev); ++ if (ret < 0) ++ dev_err(dev, "Failed to reset!\n"); ++ ++ for (i = 0; i < shdev->pdata->channel_num; i++) { ++ struct sh_dmae_chan *sh_chan = shdev->chan[i]; ++ struct sh_dmae_slave *param = sh_chan->shdma_chan.dma_chan.private; ++ ++ if (!sh_chan->shdma_chan.desc_num) ++ continue; ++ ++ if (param) { ++ const struct sh_dmae_slave_config *cfg = param->config; ++ dmae_set_dmars(sh_chan, cfg->mid_rid); ++ dmae_set_chcr(sh_chan, cfg->chcr); ++ } else { ++ dmae_init(sh_chan); + } + } +- shdev->common.chancnt = 0; ++ ++ return 0; + } ++#else ++#define sh_dmae_suspend NULL ++#define sh_dmae_resume NULL ++#endif + +-static int __init sh_dmae_probe(struct platform_device *pdev) ++const struct dev_pm_ops sh_dmae_pm = { ++ .suspend = sh_dmae_suspend, ++ .resume = sh_dmae_resume, ++ .runtime_suspend = sh_dmae_runtime_suspend, ++ .runtime_resume = sh_dmae_runtime_resume, ++}; ++ ++static dma_addr_t sh_dmae_slave_addr(struct shdma_chan *schan) ++{ ++ struct sh_dmae_slave *param = schan->dma_chan.private; ++ ++ /* ++ * Implicit BUG_ON(!param) ++ * if (param != NULL), this is a successfully requested slave channel, ++ * therefore param->config != NULL too. ++ */ ++ return param->config->addr; ++} ++ ++static struct shdma_desc *sh_dmae_embedded_desc(void *buf, int i) ++{ ++ return &((struct sh_dmae_desc *)buf)[i].shdma_desc; ++} ++ ++static const struct shdma_ops sh_dmae_shdma_ops = { ++ .desc_completed = sh_dmae_desc_completed, ++ .halt_channel = sh_dmae_halt, ++ .channel_busy = sh_dmae_channel_busy, ++ .slave_addr = sh_dmae_slave_addr, ++ .desc_setup = sh_dmae_desc_setup, ++ .set_slave = sh_dmae_set_slave, ++ .setup_xfer = sh_dmae_setup_xfer, ++ .start_xfer = sh_dmae_start_xfer, ++ .embedded_desc = sh_dmae_embedded_desc, ++ .chan_irq = sh_dmae_chan_irq, ++}; ++ ++static int __devinit sh_dmae_probe(struct platform_device *pdev) + { + struct sh_dmae_pdata *pdata = pdev->dev.platform_data; + unsigned long irqflags = IRQF_DISABLED, +- chan_flag[SH_DMAC_MAX_CHANNELS] = {}; +- int errirq, chan_irq[SH_DMAC_MAX_CHANNELS]; ++ chan_flag[SH_DMAE_MAX_CHANNELS] = {}; ++ int errirq, chan_irq[SH_DMAE_MAX_CHANNELS]; + int err, i, irq_cnt = 0, irqres = 0, irq_cap = 0; + struct sh_dmae_device *shdev; ++ struct dma_device *dma_dev; + struct resource *chan, *dmars, *errirq_res, *chanirq_res; + + /* get platform data */ +@@ -1211,6 +693,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev) + goto ealloc; + } + ++ dma_dev = &shdev->shdma_dev.dma_dev; ++ + shdev->chan_reg = ioremap(chan->start, resource_size(chan)); + if (!shdev->chan_reg) + goto emapchan; +@@ -1220,8 +704,23 @@ static int __init sh_dmae_probe(struct platform_device *pdev) + goto emapdmars; + } + ++ if (!pdata->slave_only) ++ dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask); ++ if (pdata->slave && pdata->slave_num) ++ dma_cap_set(DMA_SLAVE, dma_dev->cap_mask); ++ ++ /* Default transfer size of 32 bytes requires 32-byte alignment */ ++ dma_dev->copy_align = LOG2_DEFAULT_XFER_SIZE; ++ ++ shdev->shdma_dev.ops = &sh_dmae_shdma_ops; ++ shdev->shdma_dev.desc_size = sizeof(struct sh_dmae_desc); ++ err = shdma_init(&pdev->dev, &shdev->shdma_dev, ++ pdata->channel_num); ++ if (err < 0) ++ goto eshdma; ++ + /* platform data */ +- shdev->pdata = pdata; ++ shdev->pdata = pdev->dev.platform_data; + + if (pdata->chcr_offset) + shdev->chcr_offset = pdata->chcr_offset; +@@ -1235,10 +734,10 @@ static int __init sh_dmae_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, shdev); + +- shdev->common.dev = &pdev->dev; +- + pm_runtime_enable(&pdev->dev); +- pm_runtime_get_sync(&pdev->dev); ++ err = pm_runtime_get_sync(&pdev->dev); ++ if (err < 0) ++ dev_err(&pdev->dev, "%s(): GET = %d\n", __func__, err); + + spin_lock_irq(&sh_dmae_lock); + list_add_tail_rcu(&shdev->node, &sh_dmae_devices); +@@ -1249,27 +748,6 @@ static int __init sh_dmae_probe(struct platform_device *pdev) + if (err) + goto rst_err; + +- INIT_LIST_HEAD(&shdev->common.channels); +- +- if (!pdata->slave_only) +- dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask); +- if (pdata->slave && pdata->slave_num) +- dma_cap_set(DMA_SLAVE, shdev->common.cap_mask); +- +- shdev->common.device_alloc_chan_resources +- = sh_dmae_alloc_chan_resources; +- shdev->common.device_free_chan_resources = sh_dmae_free_chan_resources; +- shdev->common.device_prep_dma_memcpy = sh_dmae_prep_memcpy; +- shdev->common.device_tx_status = sh_dmae_tx_status; +- shdev->common.device_issue_pending = sh_dmae_memcpy_issue_pending; +- +- /* Compulsory for DMA_SLAVE fields */ +- shdev->common.device_prep_slave_sg = sh_dmae_prep_slave_sg; +- shdev->common.device_control = sh_dmae_control; +- +- /* Default transfer size of 32 bytes requires 32-byte alignment */ +- shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE; +- + #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) + chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); + +@@ -1301,7 +779,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) + !platform_get_resource(pdev, IORESOURCE_IRQ, 1)) { + /* Special case - all multiplexed */ + for (; irq_cnt < pdata->channel_num; irq_cnt++) { +- if (irq_cnt < SH_DMAC_MAX_CHANNELS) { ++ if (irq_cnt < SH_DMAE_MAX_CHANNELS) { + chan_irq[irq_cnt] = chanirq_res->start; + chan_flag[irq_cnt] = IRQF_SHARED; + } else { +@@ -1312,7 +790,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) + } else { + do { + for (i = chanirq_res->start; i <= chanirq_res->end; i++) { +- if (irq_cnt >= SH_DMAC_MAX_CHANNELS) { ++ if (irq_cnt >= SH_DMAE_MAX_CHANNELS) { + irq_cap = 1; + break; + } +@@ -1328,7 +806,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) + chan_irq[irq_cnt++] = i; + } + +- if (irq_cnt >= SH_DMAC_MAX_CHANNELS) ++ if (irq_cnt >= SH_DMAE_MAX_CHANNELS) + break; + + chanirq_res = platform_get_resource(pdev, +@@ -1346,14 +824,19 @@ static int __init sh_dmae_probe(struct platform_device *pdev) + if (irq_cap) + dev_notice(&pdev->dev, "Attempting to register %d DMA " + "channels when a maximum of %d are supported.\n", +- pdata->channel_num, SH_DMAC_MAX_CHANNELS); ++ pdata->channel_num, SH_DMAE_MAX_CHANNELS); + + pm_runtime_put(&pdev->dev); + +- dma_async_device_register(&shdev->common); ++ err = dma_async_device_register(&shdev->shdma_dev.dma_dev); ++ if (err < 0) ++ goto edmadevreg; + + return err; + ++edmadevreg: ++ pm_runtime_get(&pdev->dev); ++ + chan_probe_err: + sh_dmae_chan_remove(shdev); + +@@ -1369,10 +852,11 @@ rst_err: + pm_runtime_put(&pdev->dev); + pm_runtime_disable(&pdev->dev); + ++ platform_set_drvdata(pdev, NULL); ++ shdma_cleanup(&shdev->shdma_dev); ++eshdma: + if (dmars) + iounmap(shdev->dmars); +- +- platform_set_drvdata(pdev, NULL); + emapdmars: + iounmap(shdev->chan_reg); + synchronize_rcu(); +@@ -1387,13 +871,14 @@ ermrdmars: + return err; + } + +-static int __exit sh_dmae_remove(struct platform_device *pdev) ++static int __devexit sh_dmae_remove(struct platform_device *pdev) + { + struct sh_dmae_device *shdev = platform_get_drvdata(pdev); ++ struct dma_device *dma_dev = &shdev->shdma_dev.dma_dev; + struct resource *res; + int errirq = platform_get_irq(pdev, 0); + +- dma_async_device_unregister(&shdev->common); ++ dma_async_device_unregister(dma_dev); + + if (errirq > 0) + free_irq(errirq, shdev); +@@ -1402,11 +887,11 @@ static int __exit sh_dmae_remove(struct platform_device *pdev) + list_del_rcu(&shdev->node); + spin_unlock_irq(&sh_dmae_lock); + +- /* channel data remove */ +- sh_dmae_chan_remove(shdev); +- + pm_runtime_disable(&pdev->dev); + ++ sh_dmae_chan_remove(shdev); ++ shdma_cleanup(&shdev->shdma_dev); ++ + if (shdev->dmars) + iounmap(shdev->dmars); + iounmap(shdev->chan_reg); +@@ -1426,77 +911,14 @@ static int __exit sh_dmae_remove(struct platform_device *pdev) + return 0; + } + +-static void sh_dmae_shutdown(struct platform_device *pdev) +-{ +- struct sh_dmae_device *shdev = platform_get_drvdata(pdev); +- sh_dmae_ctl_stop(shdev); +-} +- +-static int sh_dmae_runtime_suspend(struct device *dev) +-{ +- return 0; +-} +- +-static int sh_dmae_runtime_resume(struct device *dev) +-{ +- struct sh_dmae_device *shdev = dev_get_drvdata(dev); +- +- return sh_dmae_rst(shdev); +-} +- +-#ifdef CONFIG_PM +-static int sh_dmae_suspend(struct device *dev) +-{ +- return 0; +-} +- +-static int sh_dmae_resume(struct device *dev) +-{ +- struct sh_dmae_device *shdev = dev_get_drvdata(dev); +- int i, ret; +- +- ret = sh_dmae_rst(shdev); +- if (ret < 0) +- dev_err(dev, "Failed to reset!\n"); +- +- for (i = 0; i < shdev->pdata->channel_num; i++) { +- struct sh_dmae_chan *sh_chan = shdev->chan[i]; +- struct sh_dmae_slave *param = sh_chan->common.private; +- +- if (!sh_chan->descs_allocated) +- continue; +- +- if (param) { +- const struct sh_dmae_slave_config *cfg = param->config; +- dmae_set_dmars(sh_chan, cfg->mid_rid); +- dmae_set_chcr(sh_chan, cfg->chcr); +- } else { +- dmae_init(sh_chan); +- } +- } +- +- return 0; +-} +-#else +-#define sh_dmae_suspend NULL +-#define sh_dmae_resume NULL +-#endif +- +-const struct dev_pm_ops sh_dmae_pm = { +- .suspend = sh_dmae_suspend, +- .resume = sh_dmae_resume, +- .runtime_suspend = sh_dmae_runtime_suspend, +- .runtime_resume = sh_dmae_runtime_resume, +-}; +- + static struct platform_driver sh_dmae_driver = { +- .remove = __exit_p(sh_dmae_remove), +- .shutdown = sh_dmae_shutdown, +- .driver = { ++ .driver = { + .owner = THIS_MODULE, +- .name = "sh-dma-engine", + .pm = &sh_dmae_pm, ++ .name = SH_DMAE_DRV_NAME, + }, ++ .remove = __devexit_p(sh_dmae_remove), ++ .shutdown = sh_dmae_shutdown, + }; + + static int __init sh_dmae_init(void) +@@ -1521,4 +943,4 @@ module_exit(sh_dmae_exit); + MODULE_AUTHOR("Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>"); + MODULE_DESCRIPTION("Renesas SH DMA Engine driver"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("platform:sh-dma-engine"); ++MODULE_ALIAS("platform:" SH_DMAE_DRV_NAME); +diff --git a/drivers/dma/sh/shdma.h b/drivers/dma/sh/shdma.h +index 0b1d2c1..840e47d 100644 +--- a/drivers/dma/sh/shdma.h ++++ b/drivers/dma/sh/shdma.h +@@ -13,42 +13,27 @@ + #ifndef __DMA_SHDMA_H + #define __DMA_SHDMA_H + ++#include <linux/shdma-base.h> + #include <linux/dmaengine.h> + #include <linux/interrupt.h> + #include <linux/list.h> + +-#define SH_DMAC_MAX_CHANNELS 20 +-#define SH_DMA_SLAVE_NUMBER 256 +-#define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */ ++#define SH_DMAE_MAX_CHANNELS 20 ++#define SH_DMAE_TCR_MAX 0x00FFFFFF /* 16MB */ + + struct device; + +-enum dmae_pm_state { +- DMAE_PM_ESTABLISHED, +- DMAE_PM_BUSY, +- DMAE_PM_PENDING, +-}; +- + struct sh_dmae_chan { +- spinlock_t desc_lock; /* Descriptor operation lock */ +- struct list_head ld_queue; /* Link descriptors queue */ +- struct list_head ld_free; /* Link descriptors free */ +- struct dma_chan common; /* DMA common channel */ +- struct device *dev; /* Channel device */ +- struct tasklet_struct tasklet; /* Tasklet */ +- int descs_allocated; /* desc count */ ++ struct shdma_chan shdma_chan; + int xmit_shift; /* log_2(bytes_per_xfer) */ +- int irq; +- int id; /* Raw id of this channel */ + u32 __iomem *base; + char dev_id[16]; /* unique name per DMAC of channel */ + int pm_error; +- enum dmae_pm_state pm_state; + }; + + struct sh_dmae_device { +- struct dma_device common; +- struct sh_dmae_chan *chan[SH_DMAC_MAX_CHANNELS]; ++ struct shdma_dev shdma_dev; ++ struct sh_dmae_chan *chan[SH_DMAE_MAX_CHANNELS]; + struct sh_dmae_pdata *pdata; + struct list_head node; + u32 __iomem *chan_reg; +@@ -57,10 +42,21 @@ struct sh_dmae_device { + u32 chcr_ie_bit; + }; + +-#define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, common) ++struct sh_dmae_regs { ++ u32 sar; /* SAR / source address */ ++ u32 dar; /* DAR / destination address */ ++ u32 tcr; /* TCR / transfer count */ ++}; ++ ++struct sh_dmae_desc { ++ struct sh_dmae_regs hw; ++ struct shdma_desc shdma_desc; ++}; ++ ++#define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, shdma_chan) + #define to_sh_desc(lh) container_of(lh, struct sh_desc, node) + #define tx_to_sh_desc(tx) container_of(tx, struct sh_desc, async_tx) +-#define to_sh_dev(chan) container_of(chan->common.device,\ +- struct sh_dmae_device, common) ++#define to_sh_dev(chan) container_of(chan->shdma_chan.dma_chan.device,\ ++ struct sh_dmae_device, shdma_dev.dma_dev) + + #endif /* __DMA_SHDMA_H */ +diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h +index e081e8e..7c8ca41 100644 +--- a/include/linux/sh_dma.h ++++ b/include/linux/sh_dma.h +@@ -13,34 +13,21 @@ + #include <linux/dmaengine.h> + #include <linux/list.h> + #include <linux/shdma-base.h> ++#include <linux/types.h> ++ ++struct device; + + /* Used by slave DMA clients to request DMA to/from a specific peripheral */ + struct sh_dmae_slave { +- union { +- unsigned int slave_id; /* Set by the platform */ +- struct shdma_slave shdma_slave; +- }; +- struct device *dma_dev; /* Set by the platform */ +- const struct sh_dmae_slave_config *config; /* Set by the driver */ +-}; +- +-struct sh_dmae_regs { +- u32 sar; /* SAR / source address */ +- u32 dar; /* DAR / destination address */ +- u32 tcr; /* TCR / transfer count */ +-}; +- +-struct sh_desc { +- struct sh_dmae_regs hw; +- struct list_head node; +- struct dma_async_tx_descriptor async_tx; +- enum dma_transfer_direction direction; +- dma_cookie_t cookie; +- size_t partial; +- int chunks; +- int mark; ++ struct shdma_slave shdma_slave; /* Set by the platform */ ++ struct device *dma_dev; /* Set by the platform */ ++ const struct sh_dmae_slave_config *config; /* Set by the driver */ + }; + ++/* ++ * Supplied by platforms to specify, how a DMA channel has to be configured for ++ * a certain peripheral ++ */ + struct sh_dmae_slave_config { + unsigned int slave_id; + dma_addr_t addr; +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0054-dmaengine-shdma-prepare-to-stop-using-struct-dma_cha.patch b/patches.marzen/0054-dmaengine-shdma-prepare-to-stop-using-struct-dma_cha.patch new file mode 100644 index 0000000000000..4e64c5a7c6189 --- /dev/null +++ b/patches.marzen/0054-dmaengine-shdma-prepare-to-stop-using-struct-dma_cha.patch @@ -0,0 +1,183 @@ +From a2071a25b2853b85f682b5a37d87faa4659141c6 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 5 Jul 2012 12:29:40 +0200 +Subject: dmaengine: shdma: prepare to stop using struct dma_chan::private + +Using struct dma_chan::private is deprecated. To update the shdma driver to +stop using it we first have to eliminate internal runtime uses of it. After +that we will also be able to stop using it for channel configuration. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit ecf90fbbdc66cde6f5fa25d88541112b9baac459) + +Conflicts: + drivers/dma/sh/shdma.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/dma/sh/shdma-base.c | 9 +++++---- + drivers/dma/sh/shdma.c | 24 ++++++++++-------------- + drivers/dma/sh/shdma.h | 2 ++ + include/linux/sh_dma.h | 2 -- + include/linux/shdma-base.h | 1 + + 5 files changed, 18 insertions(+), 20 deletions(-) + +diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c +index ff060d0..f75ebfa 100644 +--- a/drivers/dma/sh/shdma-base.c ++++ b/drivers/dma/sh/shdma-base.c +@@ -76,7 +76,7 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx) + container_of(tx, struct shdma_desc, async_tx), + *last = desc; + struct shdma_chan *schan = to_shdma_chan(tx->chan); +- struct shdma_slave *slave = tx->chan->private; ++ struct shdma_slave *slave = schan->slave; + dma_async_tx_callback callback = tx->callback; + dma_cookie_t cookie; + bool power_up; +@@ -208,6 +208,7 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan) + goto edescalloc; + } + schan->desc_num = NR_DESCS_PER_CHANNEL; ++ schan->slave = slave; + + for (i = 0; i < NR_DESCS_PER_CHANNEL; i++) { + desc = ops->embedded_desc(schan->desc, i); +@@ -365,9 +366,9 @@ static void shdma_free_chan_resources(struct dma_chan *chan) + if (!list_empty(&schan->ld_queue)) + shdma_chan_ld_cleanup(schan, true); + +- if (chan->private) { ++ if (schan->slave) { + /* The caller is holding dma_list_mutex */ +- struct shdma_slave *slave = chan->private; ++ struct shdma_slave *slave = schan->slave; + clear_bit(slave->slave_id, shdma_slave_used); + chan->private = NULL; + } +@@ -558,7 +559,7 @@ static struct dma_async_tx_descriptor *shdma_prep_slave_sg( + struct shdma_chan *schan = to_shdma_chan(chan); + struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device); + const struct shdma_ops *ops = sdev->ops; +- struct shdma_slave *slave = chan->private; ++ struct shdma_slave *slave = schan->slave; + dma_addr_t slave_addr; + + if (!chan) +diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c +index c393b35..305e77a 100644 +--- a/drivers/dma/sh/shdma.c ++++ b/drivers/dma/sh/shdma.c +@@ -291,10 +291,8 @@ static void sh_dmae_setup_xfer(struct shdma_chan *schan, + shdma_chan); + + if (sslave) { +- struct sh_dmae_slave *slave = container_of(sslave, +- struct sh_dmae_slave, shdma_slave); + const struct sh_dmae_slave_config *cfg = +- slave->config; ++ sh_chan->config; + + dmae_set_dmars(sh_chan, cfg->mid_rid); + dmae_set_chcr(sh_chan, cfg->chcr); +@@ -326,13 +324,11 @@ static int sh_dmae_set_slave(struct shdma_chan *schan, + { + struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan, + shdma_chan); +- struct sh_dmae_slave *slave = container_of(sslave, struct sh_dmae_slave, +- shdma_slave); + const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, slave); + if (!cfg) + return -ENODEV; + +- slave->config = cfg; ++ sh_chan->config = cfg; + + return 0; + } +@@ -579,13 +575,12 @@ static int sh_dmae_resume(struct device *dev) + + for (i = 0; i < shdev->pdata->channel_num; i++) { + struct sh_dmae_chan *sh_chan = shdev->chan[i]; +- struct sh_dmae_slave *param = sh_chan->shdma_chan.dma_chan.private; + + if (!sh_chan->shdma_chan.desc_num) + continue; + +- if (param) { +- const struct sh_dmae_slave_config *cfg = param->config; ++ if (sh_chan->shdma_chan.slave) { ++ const struct sh_dmae_slave_config *cfg = sh_chan->config; + dmae_set_dmars(sh_chan, cfg->mid_rid); + dmae_set_chcr(sh_chan, cfg->chcr); + } else { +@@ -609,14 +604,15 @@ const struct dev_pm_ops sh_dmae_pm = { + + static dma_addr_t sh_dmae_slave_addr(struct shdma_chan *schan) + { +- struct sh_dmae_slave *param = schan->dma_chan.private; ++ struct sh_dmae_chan *sh_chan = container_of(schan, ++ struct sh_dmae_chan, shdma_chan); + + /* +- * Implicit BUG_ON(!param) +- * if (param != NULL), this is a successfully requested slave channel, +- * therefore param->config != NULL too. ++ * Implicit BUG_ON(!sh_chan->config) ++ * This is an exclusive slave DMA operation, may only be called after a ++ * successful slave configuration. + */ +- return param->config->addr; ++ return sh_chan->config->addr; + } + + static struct shdma_desc *sh_dmae_embedded_desc(void *buf, int i) +diff --git a/drivers/dma/sh/shdma.h b/drivers/dma/sh/shdma.h +index 840e47d..9314e93 100644 +--- a/drivers/dma/sh/shdma.h ++++ b/drivers/dma/sh/shdma.h +@@ -13,6 +13,7 @@ + #ifndef __DMA_SHDMA_H + #define __DMA_SHDMA_H + ++#include <linux/sh_dma.h> + #include <linux/shdma-base.h> + #include <linux/dmaengine.h> + #include <linux/interrupt.h> +@@ -25,6 +26,7 @@ struct device; + + struct sh_dmae_chan { + struct shdma_chan shdma_chan; ++ const struct sh_dmae_slave_config *config; /* Slave DMA configuration */ + int xmit_shift; /* log_2(bytes_per_xfer) */ + u32 __iomem *base; + char dev_id[16]; /* unique name per DMAC of channel */ +diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h +index 7c8ca41..a79f10a 100644 +--- a/include/linux/sh_dma.h ++++ b/include/linux/sh_dma.h +@@ -20,8 +20,6 @@ struct device; + /* Used by slave DMA clients to request DMA to/from a specific peripheral */ + struct sh_dmae_slave { + struct shdma_slave shdma_slave; /* Set by the platform */ +- struct device *dma_dev; /* Set by the platform */ +- const struct sh_dmae_slave_config *config; /* Set by the driver */ + }; + + /* +diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h +index 83efd13..c3a19e9 100644 +--- a/include/linux/shdma-base.h ++++ b/include/linux/shdma-base.h +@@ -66,6 +66,7 @@ struct shdma_chan { + size_t max_xfer_len; /* max transfer length */ + int id; /* Raw id of this channel */ + int irq; /* Channel IRQ */ ++ struct shdma_slave *slave; /* Client data for slave DMA */ + enum shdma_pm_state pm_state; + }; + +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0055-dmaengine-shdma-cosmetic-simplify-a-static-function.patch b/patches.marzen/0055-dmaengine-shdma-cosmetic-simplify-a-static-function.patch new file mode 100644 index 0000000000000..96374c2ea4e16 --- /dev/null +++ b/patches.marzen/0055-dmaengine-shdma-cosmetic-simplify-a-static-function.patch @@ -0,0 +1,58 @@ +From fc5aa8d8ebed522f219c9a368306cbe41fe75ca9 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 5 Jul 2012 12:29:37 +0200 +Subject: dmaengine: shdma: (cosmetic) simplify a static function + +dmae_find_slave() needs only the slave_id field from the slave object, no +need to pass the pointer to the object, pass the slave_id directly. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit 341f4dc5dcecbf60f038055db177845b9af480ed) + +Conflicts: + drivers/dma/sh/shdma.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/dma/sh/shdma.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c +index 305e77a..9f0a2e5 100644 +--- a/drivers/dma/sh/shdma.c ++++ b/drivers/dma/sh/shdma.c +@@ -302,18 +302,18 @@ static void sh_dmae_setup_xfer(struct shdma_chan *schan, + } + + static const struct sh_dmae_slave_config *dmae_find_slave( +- struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *slave) ++ struct sh_dmae_chan *sh_chan, unsigned int slave_id) + { + struct sh_dmae_device *shdev = to_sh_dev(sh_chan); + struct sh_dmae_pdata *pdata = shdev->pdata; + const struct sh_dmae_slave_config *cfg; + int i; + +- if (slave->shdma_slave.slave_id >= SH_DMA_SLAVE_NUMBER) ++ if (slave_id >= SH_DMA_SLAVE_NUMBER) + return NULL; + + for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++) +- if (cfg->slave_id == slave->shdma_slave.slave_id) ++ if (cfg->slave_id == slave_id) + return cfg; + + return NULL; +@@ -324,7 +324,7 @@ static int sh_dmae_set_slave(struct shdma_chan *schan, + { + struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan, + shdma_chan); +- const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, slave); ++ const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, sslave->slave_id); + if (!cfg) + return -ENODEV; + +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0056-dma-sh-use-an-integer-slave-ID-to-improve-API-compat.patch b/patches.marzen/0056-dma-sh-use-an-integer-slave-ID-to-improve-API-compat.patch new file mode 100644 index 0000000000000..d7aba34506d97 --- /dev/null +++ b/patches.marzen/0056-dma-sh-use-an-integer-slave-ID-to-improve-API-compat.patch @@ -0,0 +1,220 @@ +From 994962e925ac52b6a5c870d02f537c5e3dd535ca Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 5 Jul 2012 12:29:41 +0200 +Subject: dma: sh: use an integer slave ID to improve API compatibility + +Initially struct shdma_slave has been introduced with the only member - an +unsigned slave ID - to describe common properties of DMA slaves in an +extensible way. However, experience shows, that a slave ID is indeed the +only parameter, needed to identify DMA slaves. This is also, what is used +by the core dmaengine API in struct dma_slave_config. We switch to using +the slave_id directly, instead of passing a pointer to struct shdma_slave +to improve compatibility with the core. We also make the slave_id signed +for easier error checking. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit c2cdb7e4d16394fc51dc5c2c5b3e7c3733bdfaac) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/dma/sh/shdma-base.c | 25 +++++++++++++------------ + drivers/dma/sh/shdma.c | 12 ++++++------ + include/linux/sh_dma.h | 8 ++++---- + include/linux/shdma-base.h | 8 ++++---- + 4 files changed, 27 insertions(+), 26 deletions(-) + +diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c +index f75ebfa..73db282 100644 +--- a/drivers/dma/sh/shdma-base.c ++++ b/drivers/dma/sh/shdma-base.c +@@ -76,7 +76,6 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx) + container_of(tx, struct shdma_desc, async_tx), + *last = desc; + struct shdma_chan *schan = to_shdma_chan(tx->chan); +- struct shdma_slave *slave = schan->slave; + dma_async_tx_callback callback = tx->callback; + dma_cookie_t cookie; + bool power_up; +@@ -138,7 +137,7 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx) + * Make it int then, on error remove chunks from the + * queue again + */ +- ops->setup_xfer(schan, slave); ++ ops->setup_xfer(schan, schan->slave_id); + + if (schan->pm_state == SHDMA_PM_PENDING) + shdma_chan_xfer_ld_queue(schan); +@@ -186,7 +185,7 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan) + * never runs concurrently with itself or free_chan_resources. + */ + if (slave) { +- if (slave->slave_id >= slave_num) { ++ if (slave->slave_id < 0 || slave->slave_id >= slave_num) { + ret = -EINVAL; + goto evalid; + } +@@ -196,9 +195,13 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan) + goto etestused; + } + +- ret = ops->set_slave(schan, slave); ++ ret = ops->set_slave(schan, slave->slave_id); + if (ret < 0) + goto esetslave; ++ ++ schan->slave_id = slave->slave_id; ++ } else { ++ schan->slave_id = -EINVAL; + } + + schan->desc = kcalloc(NR_DESCS_PER_CHANNEL, +@@ -208,7 +211,6 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan) + goto edescalloc; + } + schan->desc_num = NR_DESCS_PER_CHANNEL; +- schan->slave = slave; + + for (i = 0; i < NR_DESCS_PER_CHANNEL; i++) { + desc = ops->embedded_desc(schan->desc, i); +@@ -366,10 +368,9 @@ static void shdma_free_chan_resources(struct dma_chan *chan) + if (!list_empty(&schan->ld_queue)) + shdma_chan_ld_cleanup(schan, true); + +- if (schan->slave) { ++ if (schan->slave_id >= 0) { + /* The caller is holding dma_list_mutex */ +- struct shdma_slave *slave = schan->slave; +- clear_bit(slave->slave_id, shdma_slave_used); ++ clear_bit(schan->slave_id, shdma_slave_used); + chan->private = NULL; + } + +@@ -559,7 +560,7 @@ static struct dma_async_tx_descriptor *shdma_prep_slave_sg( + struct shdma_chan *schan = to_shdma_chan(chan); + struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device); + const struct shdma_ops *ops = sdev->ops; +- struct shdma_slave *slave = schan->slave; ++ int slave_id = schan->slave_id; + dma_addr_t slave_addr; + + if (!chan) +@@ -568,9 +569,9 @@ static struct dma_async_tx_descriptor *shdma_prep_slave_sg( + BUG_ON(!schan->desc_num); + + /* Someone calling slave DMA on a generic channel? */ +- if (!slave || !sg_len) { +- dev_warn(schan->dev, "%s: bad parameter: %p, %d, %d\n", +- __func__, slave, sg_len, slave ? slave->slave_id : -1); ++ if (slave_id < 0 || !sg_len) { ++ dev_warn(schan->dev, "%s: bad parameter: len=%d, id=%d\n", ++ __func__, sg_len, slave_id); + return NULL; + } + +diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c +index 9f0a2e5..9a10d8b 100644 +--- a/drivers/dma/sh/shdma.c ++++ b/drivers/dma/sh/shdma.c +@@ -285,12 +285,12 @@ static bool sh_dmae_channel_busy(struct shdma_chan *schan) + } + + static void sh_dmae_setup_xfer(struct shdma_chan *schan, +- struct shdma_slave *sslave) ++ int slave_id) + { + struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan, + shdma_chan); + +- if (sslave) { ++ if (slave_id >= 0) { + const struct sh_dmae_slave_config *cfg = + sh_chan->config; + +@@ -302,7 +302,7 @@ static void sh_dmae_setup_xfer(struct shdma_chan *schan, + } + + static const struct sh_dmae_slave_config *dmae_find_slave( +- struct sh_dmae_chan *sh_chan, unsigned int slave_id) ++ struct sh_dmae_chan *sh_chan, int slave_id) + { + struct sh_dmae_device *shdev = to_sh_dev(sh_chan); + struct sh_dmae_pdata *pdata = shdev->pdata; +@@ -320,11 +320,11 @@ static const struct sh_dmae_slave_config *dmae_find_slave( + } + + static int sh_dmae_set_slave(struct shdma_chan *schan, +- struct shdma_slave *sslave) ++ int slave_id) + { + struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan, + shdma_chan); +- const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, sslave->slave_id); ++ const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, slave_id); + if (!cfg) + return -ENODEV; + +@@ -579,7 +579,7 @@ static int sh_dmae_resume(struct device *dev) + if (!sh_chan->shdma_chan.desc_num) + continue; + +- if (sh_chan->shdma_chan.slave) { ++ if (sh_chan->shdma_chan.slave_id >= 0) { + const struct sh_dmae_slave_config *cfg = sh_chan->config; + dmae_set_dmars(sh_chan, cfg->mid_rid); + dmae_set_chcr(sh_chan, cfg->chcr); +diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h +index a79f10a..4e83f3e 100644 +--- a/include/linux/sh_dma.h ++++ b/include/linux/sh_dma.h +@@ -27,10 +27,10 @@ struct sh_dmae_slave { + * a certain peripheral + */ + struct sh_dmae_slave_config { +- unsigned int slave_id; +- dma_addr_t addr; +- u32 chcr; +- char mid_rid; ++ int slave_id; ++ dma_addr_t addr; ++ u32 chcr; ++ char mid_rid; + }; + + struct sh_dmae_channel { +diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h +index c3a19e9..6263ad2 100644 +--- a/include/linux/shdma-base.h ++++ b/include/linux/shdma-base.h +@@ -43,7 +43,7 @@ struct device; + */ + + struct shdma_slave { +- unsigned int slave_id; ++ int slave_id; + }; + + struct shdma_desc { +@@ -66,7 +66,7 @@ struct shdma_chan { + size_t max_xfer_len; /* max transfer length */ + int id; /* Raw id of this channel */ + int irq; /* Channel IRQ */ +- struct shdma_slave *slave; /* Client data for slave DMA */ ++ int slave_id; /* Client ID for slave DMA */ + enum shdma_pm_state pm_state; + }; + +@@ -93,8 +93,8 @@ struct shdma_ops { + dma_addr_t (*slave_addr)(struct shdma_chan *); + int (*desc_setup)(struct shdma_chan *, struct shdma_desc *, + dma_addr_t, dma_addr_t, size_t *); +- int (*set_slave)(struct shdma_chan *, struct shdma_slave *); +- void (*setup_xfer)(struct shdma_chan *, struct shdma_slave *); ++ int (*set_slave)(struct shdma_chan *, int); ++ void (*setup_xfer)(struct shdma_chan *, int); + void (*start_xfer)(struct shdma_chan *, struct shdma_desc *); + struct shdma_desc *(*embedded_desc)(void *, int); + bool (*chan_irq)(struct shdma_chan *, int); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0057-dma-sh-provide-a-migration-path-for-slave-drivers-to.patch b/patches.marzen/0057-dma-sh-provide-a-migration-path-for-slave-drivers-to.patch new file mode 100644 index 0000000000000..b1aa4af404953 --- /dev/null +++ b/patches.marzen/0057-dma-sh-provide-a-migration-path-for-slave-drivers-to.patch @@ -0,0 +1,231 @@ +From 3f976e575c229dad477f66090af9286700b35b3e Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 5 Jul 2012 12:29:42 +0200 +Subject: dma: sh: provide a migration path for slave drivers to stop using + .private + +This patch extends the sh dmaengine driver to support the preferred channel +selection and configuration method, instead of using the "private" field +from struct dma_chan. We add a standard filter function to be used by +slave drivers instead of implementing their own ones, and add support for +the DMA_SLAVE_CONFIG control operation, which must accompany the new +channel selection method. We still support the legacy .private channel +allocation method to cater for a smooth driver migration. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +[applied a trvial checkpath fix] +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit 1ff8df4f5388ad66bd7d0199b5839a2e3345c055) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/dma/sh/shdma-base.c | 114 ++++++++++++++++++++++++++++++++++---------- + drivers/dma/sh/shdma.c | 5 +- + include/linux/sh_dma.h | 2 + + include/linux/shdma-base.h | 2 +- + 4 files changed, 95 insertions(+), 28 deletions(-) + +diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c +index 73db282..27f5c78 100644 +--- a/drivers/dma/sh/shdma-base.c ++++ b/drivers/dma/sh/shdma-base.c +@@ -171,6 +171,65 @@ static struct shdma_desc *shdma_get_desc(struct shdma_chan *schan) + return NULL; + } + ++static int shdma_setup_slave(struct shdma_chan *schan, int slave_id) ++{ ++ struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device); ++ const struct shdma_ops *ops = sdev->ops; ++ int ret; ++ ++ if (slave_id < 0 || slave_id >= slave_num) ++ return -EINVAL; ++ ++ if (test_and_set_bit(slave_id, shdma_slave_used)) ++ return -EBUSY; ++ ++ ret = ops->set_slave(schan, slave_id, false); ++ if (ret < 0) { ++ clear_bit(slave_id, shdma_slave_used); ++ return ret; ++ } ++ ++ schan->slave_id = slave_id; ++ ++ return 0; ++} ++ ++/* ++ * This is the standard shdma filter function to be used as a replacement to the ++ * "old" method, using the .private pointer. If for some reason you allocate a ++ * channel without slave data, use something like ERR_PTR(-EINVAL) as a filter ++ * parameter. If this filter is used, the slave driver, after calling ++ * dma_request_channel(), will also have to call dmaengine_slave_config() with ++ * .slave_id, .direction, and either .src_addr or .dst_addr set. ++ * NOTE: this filter doesn't support multiple DMAC drivers with the DMA_SLAVE ++ * capability! If this becomes a requirement, hardware glue drivers, using this ++ * services would have to provide their own filters, which first would check ++ * the device driver, similar to how other DMAC drivers, e.g., sa11x0-dma.c, do ++ * this, and only then, in case of a match, call this common filter. ++ */ ++bool shdma_chan_filter(struct dma_chan *chan, void *arg) ++{ ++ struct shdma_chan *schan = to_shdma_chan(chan); ++ struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device); ++ const struct shdma_ops *ops = sdev->ops; ++ int slave_id = (int)arg; ++ int ret; ++ ++ if (slave_id < 0) ++ /* No slave requested - arbitrary channel */ ++ return true; ++ ++ if (slave_id >= slave_num) ++ return false; ++ ++ ret = ops->set_slave(schan, slave_id, true); ++ if (ret < 0) ++ return false; ++ ++ return true; ++} ++EXPORT_SYMBOL(shdma_chan_filter); ++ + static int shdma_alloc_chan_resources(struct dma_chan *chan) + { + struct shdma_chan *schan = to_shdma_chan(chan); +@@ -185,21 +244,10 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan) + * never runs concurrently with itself or free_chan_resources. + */ + if (slave) { +- if (slave->slave_id < 0 || slave->slave_id >= slave_num) { +- ret = -EINVAL; +- goto evalid; +- } +- +- if (test_and_set_bit(slave->slave_id, shdma_slave_used)) { +- ret = -EBUSY; +- goto etestused; +- } +- +- ret = ops->set_slave(schan, slave->slave_id); ++ /* Legacy mode: .private is set in filter */ ++ ret = shdma_setup_slave(schan, slave->slave_id); + if (ret < 0) + goto esetslave; +- +- schan->slave_id = slave->slave_id; + } else { + schan->slave_id = -EINVAL; + } +@@ -228,8 +276,6 @@ edescalloc: + if (slave) + esetslave: + clear_bit(slave->slave_id, shdma_slave_used); +-etestused: +-evalid: + chan->private = NULL; + return ret; + } +@@ -587,22 +633,40 @@ static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + struct shdma_chan *schan = to_shdma_chan(chan); + struct shdma_dev *sdev = to_shdma_dev(chan->device); + const struct shdma_ops *ops = sdev->ops; ++ struct dma_slave_config *config; + unsigned long flags; +- +- /* Only supports DMA_TERMINATE_ALL */ +- if (cmd != DMA_TERMINATE_ALL) +- return -ENXIO; ++ int ret; + + if (!chan) + return -EINVAL; + +- spin_lock_irqsave(&schan->chan_lock, flags); +- +- ops->halt_channel(schan); +- +- spin_unlock_irqrestore(&schan->chan_lock, flags); ++ switch (cmd) { ++ case DMA_TERMINATE_ALL: ++ spin_lock_irqsave(&schan->chan_lock, flags); ++ ops->halt_channel(schan); ++ spin_unlock_irqrestore(&schan->chan_lock, flags); + +- shdma_chan_ld_cleanup(schan, true); ++ shdma_chan_ld_cleanup(schan, true); ++ break; ++ case DMA_SLAVE_CONFIG: ++ /* ++ * So far only .slave_id is used, but the slave drivers are ++ * encouraged to also set a transfer direction and an address. ++ */ ++ if (!arg) ++ return -EINVAL; ++ /* ++ * We could lock this, but you shouldn't be configuring the ++ * channel, while using it... ++ */ ++ config = (struct dma_slave_config *)arg; ++ ret = shdma_setup_slave(schan, config->slave_id); ++ if (ret < 0) ++ return ret; ++ break; ++ default: ++ return -ENXIO; ++ } + + return 0; + } +diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c +index 9a10d8b..027c9be 100644 +--- a/drivers/dma/sh/shdma.c ++++ b/drivers/dma/sh/shdma.c +@@ -320,7 +320,7 @@ static const struct sh_dmae_slave_config *dmae_find_slave( + } + + static int sh_dmae_set_slave(struct shdma_chan *schan, +- int slave_id) ++ int slave_id, bool try) + { + struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan, + shdma_chan); +@@ -328,7 +328,8 @@ static int sh_dmae_set_slave(struct shdma_chan *schan, + if (!cfg) + return -ENODEV; + +- sh_chan->config = cfg; ++ if (!try) ++ sh_chan->config = cfg; + + return 0; + } +diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h +index 4e83f3e..b64d6be 100644 +--- a/include/linux/sh_dma.h ++++ b/include/linux/sh_dma.h +@@ -99,4 +99,6 @@ struct sh_dmae_pdata { + #define CHCR_TE 0x00000002 + #define CHCR_IE 0x00000004 + ++bool shdma_chan_filter(struct dma_chan *chan, void *arg); ++ + #endif +diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h +index 6263ad2..93f9821 100644 +--- a/include/linux/shdma-base.h ++++ b/include/linux/shdma-base.h +@@ -93,7 +93,7 @@ struct shdma_ops { + dma_addr_t (*slave_addr)(struct shdma_chan *); + int (*desc_setup)(struct shdma_chan *, struct shdma_desc *, + dma_addr_t, dma_addr_t, size_t *); +- int (*set_slave)(struct shdma_chan *, int); ++ int (*set_slave)(struct shdma_chan *, int, bool); + void (*setup_xfer)(struct shdma_chan *, int); + void (*start_xfer)(struct shdma_chan *, struct shdma_desc *); + struct shdma_desc *(*embedded_desc)(void *, int); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0058-dmaengine-shdma-restore-partial-transfer-calculation.patch b/patches.marzen/0058-dmaengine-shdma-restore-partial-transfer-calculation.patch new file mode 100644 index 0000000000000..8352cb6d0451b --- /dev/null +++ b/patches.marzen/0058-dmaengine-shdma-restore-partial-transfer-calculation.patch @@ -0,0 +1,101 @@ +From b1cb8efea85092e5441a428691a36d9fec40ca0f Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Mon, 30 Jul 2012 21:28:27 +0200 +Subject: dmaengine: shdma: restore partial transfer calculation + +The recent shdma driver split has mistakenly removed support for partial +DMA transfer size calculation on forced termination. This patch restores +it. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Acked-by: Vinod Koul <vinod.koul@linux.intel.com> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 4f46f8ac80416b0e8fd3aba6a0d842205fb29140) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/dma/sh/shdma-base.c | 9 +++++++++ + drivers/dma/sh/shdma.c | 12 ++++++++++++ + include/linux/shdma-base.h | 2 ++ + 3 files changed, 23 insertions(+) + +diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c +index 27f5c78..f4cd946 100644 +--- a/drivers/dma/sh/shdma-base.c ++++ b/drivers/dma/sh/shdma-base.c +@@ -483,6 +483,7 @@ static struct shdma_desc *shdma_add_desc(struct shdma_chan *schan, + new->mark = DESC_PREPARED; + new->async_tx.flags = flags; + new->direction = direction; ++ new->partial = 0; + + *len -= copy_size; + if (direction == DMA_MEM_TO_MEM || direction == DMA_MEM_TO_DEV) +@@ -644,6 +645,14 @@ static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + case DMA_TERMINATE_ALL: + spin_lock_irqsave(&schan->chan_lock, flags); + ops->halt_channel(schan); ++ ++ if (ops->get_partial && !list_empty(&schan->ld_queue)) { ++ /* Record partial transfer */ ++ struct shdma_desc *desc = list_first_entry(&schan->ld_queue, ++ struct shdma_desc, node); ++ desc->partial = ops->get_partial(schan, desc); ++ } ++ + spin_unlock_irqrestore(&schan->chan_lock, flags); + + shdma_chan_ld_cleanup(schan, true); +diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c +index 027c9be..f41bcc5 100644 +--- a/drivers/dma/sh/shdma.c ++++ b/drivers/dma/sh/shdma.c +@@ -381,6 +381,17 @@ static bool sh_dmae_chan_irq(struct shdma_chan *schan, int irq) + return true; + } + ++static size_t sh_dmae_get_partial(struct shdma_chan *schan, ++ struct shdma_desc *sdesc) ++{ ++ struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan, ++ shdma_chan); ++ struct sh_dmae_desc *sh_desc = container_of(sdesc, ++ struct sh_dmae_desc, shdma_desc); ++ return (sh_desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) << ++ sh_chan->xmit_shift; ++} ++ + /* Called from error IRQ or NMI */ + static bool sh_dmae_reset(struct sh_dmae_device *shdev) + { +@@ -632,6 +643,7 @@ static const struct shdma_ops sh_dmae_shdma_ops = { + .start_xfer = sh_dmae_start_xfer, + .embedded_desc = sh_dmae_embedded_desc, + .chan_irq = sh_dmae_chan_irq, ++ .get_partial = sh_dmae_get_partial, + }; + + static int __devinit sh_dmae_probe(struct platform_device *pdev) +diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h +index 93f9821..a3728bf 100644 +--- a/include/linux/shdma-base.h ++++ b/include/linux/shdma-base.h +@@ -50,6 +50,7 @@ struct shdma_desc { + struct list_head node; + struct dma_async_tx_descriptor async_tx; + enum dma_transfer_direction direction; ++ size_t partial; + dma_cookie_t cookie; + int chunks; + int mark; +@@ -98,6 +99,7 @@ struct shdma_ops { + void (*start_xfer)(struct shdma_chan *, struct shdma_desc *); + struct shdma_desc *(*embedded_desc)(void *, int); + bool (*chan_irq)(struct shdma_chan *, int); ++ size_t (*get_partial)(struct shdma_chan *, struct shdma_desc *); + }; + + struct shdma_dev { +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0059-serial-sh-sci-modify-sci_break_ctl.patch b/patches.marzen/0059-serial-sh-sci-modify-sci_break_ctl.patch new file mode 100644 index 0000000000000..0b342ddc24cff --- /dev/null +++ b/patches.marzen/0059-serial-sh-sci-modify-sci_break_ctl.patch @@ -0,0 +1,77 @@ +From f51d4dcccbe271ab892444ddb9821b2e8b976c04 Mon Sep 17 00:00:00 2001 +From: "Shimoda, Yoshihiro" <yoshihiro.shimoda.uh@renesas.com> +Date: Fri, 6 Apr 2012 09:59:14 +0900 +Subject: serial: sh-sci: modify sci_break_ctl() + +SCIF modules which have SCSPTR can output the break signal. Now that we +have a way of determining port features/capabilities, add trivial break +control via SCSPTR support. Tested on sh7757lcr. + +Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Reviewed-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit bbb4ce50f3169b08764f9965fd5b9655646d545a) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/tty/serial/sh-sci.c | 30 ++++++++++++++++++++++++++---- + include/linux/serial_sci.h | 2 ++ + 2 files changed, 28 insertions(+), 4 deletions(-) + +diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c +index 3158e17..3e471fc 100644 +--- a/drivers/tty/serial/sh-sci.c ++++ b/drivers/tty/serial/sh-sci.c +@@ -1564,10 +1564,32 @@ static void sci_enable_ms(struct uart_port *port) + + static void sci_break_ctl(struct uart_port *port, int break_state) + { +- /* +- * Not supported by hardware. Most parts couple break and rx +- * interrupts together, with break detection always enabled. +- */ ++ struct sci_port *s = to_sci_port(port); ++ unsigned short scscr, scsptr; ++ ++ switch (s->cfg->regtype) { ++ case SCIx_SH4_SCIF_REGTYPE: ++ scsptr = serial_port_in(port, SCSPTR); ++ scscr = serial_port_in(port, SCSCR); ++ ++ if (break_state == -1) { ++ scsptr = (scsptr | SCSPTR_SPB2IO) & ~SCSPTR_SPB2DT; ++ scscr &= ~SCSCR_TE; ++ } else { ++ scsptr = (scsptr | SCSPTR_SPB2DT) & ~SCSPTR_SPB2IO; ++ scscr |= SCSCR_TE; ++ } ++ ++ serial_port_out(port, SCSPTR, scsptr); ++ serial_port_out(port, SCSCR, scscr); ++ break; ++ default: ++ /* ++ * Not supported by hardware. Most parts couple break and rx ++ * interrupts together, with break detection always enabled. ++ */ ++ break; ++ } + } + + #ifdef CONFIG_SERIAL_SH_SCI_DMA +diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h +index 7877907..eb763ad 100644 +--- a/include/linux/serial_sci.h ++++ b/include/linux/serial_sci.h +@@ -52,6 +52,8 @@ enum { + /* SCSPTR, optional */ + #define SCSPTR_RTSIO (1 << 7) + #define SCSPTR_CTSIO (1 << 5) ++#define SCSPTR_SPB2IO (1 << 1) ++#define SCSPTR_SPB2DT (1 << 0) + + /* Offsets into the sci_port->irqs array */ + enum { +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0060-serial-sh-sci-Update-break_ctl-handling-for-all-SCSP.patch b/patches.marzen/0060-serial-sh-sci-Update-break_ctl-handling-for-all-SCSP.patch new file mode 100644 index 0000000000000..807ce53b01bf2 --- /dev/null +++ b/patches.marzen/0060-serial-sh-sci-Update-break_ctl-handling-for-all-SCSP.patch @@ -0,0 +1,77 @@ +From 771d21f0510973f1da8789ad877a0fa806aa1ec7 Mon Sep 17 00:00:00 2001 +From: "Shimoda, Yoshihiro" <yoshihiro.shimoda.uh@renesas.com> +Date: Thu, 12 Apr 2012 19:19:21 +0900 +Subject: serial: sh-sci: Update break_ctl handling for all SCSPTR-capable + regtypes. + +This updates the earlier break_ctl support regardless of regtype so long +as the requisite SCSPTR exists. This is the same approach used by +sci_init_pins() for providing a generic solution now that we're able to +detect register capabilities on a per-port basis. + +Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit a4e02f6d83d4fcdb13bcaba76878fc5ea0da9911) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/tty/serial/sh-sci.c | 36 ++++++++++++++++++------------------ + 1 file changed, 18 insertions(+), 18 deletions(-) + +diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c +index 3e471fc..be31d85 100644 +--- a/drivers/tty/serial/sh-sci.c ++++ b/drivers/tty/serial/sh-sci.c +@@ -1565,31 +1565,31 @@ static void sci_enable_ms(struct uart_port *port) + static void sci_break_ctl(struct uart_port *port, int break_state) + { + struct sci_port *s = to_sci_port(port); ++ struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR; + unsigned short scscr, scsptr; + +- switch (s->cfg->regtype) { +- case SCIx_SH4_SCIF_REGTYPE: +- scsptr = serial_port_in(port, SCSPTR); +- scscr = serial_port_in(port, SCSCR); +- +- if (break_state == -1) { +- scsptr = (scsptr | SCSPTR_SPB2IO) & ~SCSPTR_SPB2DT; +- scscr &= ~SCSCR_TE; +- } else { +- scsptr = (scsptr | SCSPTR_SPB2DT) & ~SCSPTR_SPB2IO; +- scscr |= SCSCR_TE; +- } +- +- serial_port_out(port, SCSPTR, scsptr); +- serial_port_out(port, SCSCR, scscr); +- break; +- default: ++ /* check wheter the port has SCSPTR */ ++ if (!reg->size) { + /* + * Not supported by hardware. Most parts couple break and rx + * interrupts together, with break detection always enabled. + */ +- break; ++ return; + } ++ ++ scsptr = serial_port_in(port, SCSPTR); ++ scscr = serial_port_in(port, SCSCR); ++ ++ if (break_state == -1) { ++ scsptr = (scsptr | SCSPTR_SPB2IO) & ~SCSPTR_SPB2DT; ++ scscr &= ~SCSCR_TE; ++ } else { ++ scsptr = (scsptr | SCSPTR_SPB2DT) & ~SCSPTR_SPB2IO; ++ scscr |= SCSCR_TE; ++ } ++ ++ serial_port_out(port, SCSPTR, scsptr); ++ serial_port_out(port, SCSCR, scscr); + } + + #ifdef CONFIG_SERIAL_SH_SCI_DMA +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0061-serial-sh-sci-Fix-for-port-types-without-BRI-interru.patch b/patches.marzen/0061-serial-sh-sci-Fix-for-port-types-without-BRI-interru.patch new file mode 100644 index 0000000000000..990a00fa3cdc7 --- /dev/null +++ b/patches.marzen/0061-serial-sh-sci-Fix-for-port-types-without-BRI-interru.patch @@ -0,0 +1,63 @@ +From 0491f004737edadd928f7d46f5e9f0f8f5f054e0 Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Fri, 18 May 2012 18:21:06 +0900 +Subject: serial: sh-sci: Fix for port types without BRI interrupts. + +In doing the evt2irq() + muxed vector conversion for various port types +it became apparent that some of the legacy port types will presently +error out due to the irq requesting logic attempting to acquire the +non-existent BRI IRQ. This adds some sanity checks to the request/free +path to ensure that non-existence of a source in itself is not an error. + +This should restore functionality for legacy PORT_SCI ports. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 0e8963de1fe95e7fbc30c79c1dbc7cb1ea0cf699) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/tty/serial/sh-sci.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c +index be31d85..4604153 100644 +--- a/drivers/tty/serial/sh-sci.c ++++ b/drivers/tty/serial/sh-sci.c +@@ -1052,9 +1052,17 @@ static int sci_request_irq(struct sci_port *port) + if (SCIx_IRQ_IS_MUXED(port)) { + i = SCIx_MUX_IRQ; + irq = up->irq; +- } else ++ } else { + irq = port->cfg->irqs[i]; + ++ /* ++ * Certain port types won't support all of the ++ * available interrupt sources. ++ */ ++ if (unlikely(!irq)) ++ continue; ++ } ++ + desc = sci_irq_desc + i; + port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s", + dev_name(up->dev), desc->desc); +@@ -1094,6 +1102,15 @@ static void sci_free_irq(struct sci_port *port) + * IRQ first. + */ + for (i = 0; i < SCIx_NR_IRQS; i++) { ++ unsigned int irq = port->cfg->irqs[i]; ++ ++ /* ++ * Certain port types won't support all of the available ++ * interrupt sources. ++ */ ++ if (unlikely(!irq)) ++ continue; ++ + free_irq(port->cfg->irqs[i], port); + kfree(port->irqstr[i]); + +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0062-serial-sh-sci-Fix-probe-error-paths.patch b/patches.marzen/0062-serial-sh-sci-Fix-probe-error-paths.patch new file mode 100644 index 0000000000000..fc41e2d061649 --- /dev/null +++ b/patches.marzen/0062-serial-sh-sci-Fix-probe-error-paths.patch @@ -0,0 +1,102 @@ +From 61760a1e6363eeb42b29b76176e3ec4ac837753b Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Wed, 13 Jun 2012 00:28:23 +0200 +Subject: serial: sh-sci: Fix probe error paths + +When probing fails, the driver must not try to cleanup resources that +have not been initialized. Fix this. + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 6dae14216c85eea13db7b12c469475c5d30e5499) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/tty/serial/sh-sci.c | 36 +++++++++++++++++++++++------------- + 1 file changed, 23 insertions(+), 13 deletions(-) + +diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c +index 4604153..27df2ad 100644 +--- a/drivers/tty/serial/sh-sci.c ++++ b/drivers/tty/serial/sh-sci.c +@@ -2179,6 +2179,16 @@ static int __devinit sci_init_single(struct platform_device *dev, + return 0; + } + ++static void sci_cleanup_single(struct sci_port *port) ++{ ++ sci_free_gpios(port); ++ ++ clk_put(port->iclk); ++ clk_put(port->fclk); ++ ++ pm_runtime_disable(port->port.dev); ++} ++ + #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE + static void serial_console_putchar(struct uart_port *port, int ch) + { +@@ -2360,14 +2370,10 @@ static int sci_remove(struct platform_device *dev) + cpufreq_unregister_notifier(&port->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); + +- sci_free_gpios(port); +- + uart_remove_one_port(&sci_uart_driver, &port->port); + +- clk_put(port->iclk); +- clk_put(port->fclk); ++ sci_cleanup_single(port); + +- pm_runtime_disable(&dev->dev); + return 0; + } + +@@ -2392,7 +2398,13 @@ static int __devinit sci_probe_single(struct platform_device *dev, + if (ret) + return ret; + +- return uart_add_one_port(&sci_uart_driver, &sciport->port); ++ ret = uart_add_one_port(&sci_uart_driver, &sciport->port); ++ if (ret) { ++ sci_cleanup_single(sciport); ++ return ret; ++ } ++ ++ return 0; + } + + static int __devinit sci_probe(struct platform_device *dev) +@@ -2413,24 +2425,22 @@ static int __devinit sci_probe(struct platform_device *dev) + + ret = sci_probe_single(dev, dev->id, p, sp); + if (ret) +- goto err_unreg; ++ return ret; + + sp->freq_transition.notifier_call = sci_notifier; + + ret = cpufreq_register_notifier(&sp->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); +- if (unlikely(ret < 0)) +- goto err_unreg; ++ if (unlikely(ret < 0)) { ++ sci_cleanup_single(sp); ++ return ret; ++ } + + #ifdef CONFIG_SH_STANDARD_BIOS + sh_bios_gdb_detach(); + #endif + + return 0; +- +-err_unreg: +- sci_remove(dev); +- return ret; + } + + static int sci_suspend(struct device *dev) +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0063-serial-sh-sci-Make-probe-fail-for-ports-that-exceed-.patch b/patches.marzen/0063-serial-sh-sci-Make-probe-fail-for-ports-that-exceed-.patch new file mode 100644 index 0000000000000..7ca587c33cb57 --- /dev/null +++ b/patches.marzen/0063-serial-sh-sci-Make-probe-fail-for-ports-that-exceed-.patch @@ -0,0 +1,39 @@ +From e78402772bb6c357710275ae6958fd9eaab70036 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Wed, 13 Jun 2012 00:28:24 +0200 +Subject: serial: sh-sci: Make probe fail for ports that exceed the maximum + count + +The driver supports a maximum number of ports configurable at compile +time. Make sure the probe() method fails when registering a port that +exceeds the maximum instead of returning success without registering the +port. + +This fixes a crash at system suspend time, when the driver tried to +suspend a non-registered port using the UART core. + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit b6c5ef6f6d3e46d6200b141c30ac000a11b851df) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/tty/serial/sh-sci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c +index 27df2ad..1bd9163 100644 +--- a/drivers/tty/serial/sh-sci.c ++++ b/drivers/tty/serial/sh-sci.c +@@ -2391,7 +2391,7 @@ static int __devinit sci_probe_single(struct platform_device *dev, + index+1, SCI_NPORTS); + dev_notice(&dev->dev, "Consider bumping " + "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n"); +- return 0; ++ return -EINVAL; + } + + ret = sci_init_single(dev, sciport, index, p); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0064-serial-sh-sci-prepare-for-conversion-to-the-shdma-ba.patch b/patches.marzen/0064-serial-sh-sci-prepare-for-conversion-to-the-shdma-ba.patch new file mode 100644 index 0000000000000..75ad2f363dca8 --- /dev/null +++ b/patches.marzen/0064-serial-sh-sci-prepare-for-conversion-to-the-shdma-ba.patch @@ -0,0 +1,53 @@ +From d9a397f8913cef21e0cc251856d5e3e709d057f8 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 9 May 2012 17:09:17 +0200 +Subject: serial: sh-sci: prepare for conversion to the shdma base library + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Cc: Alan Cox <alan@linux.intel.com> +Acked-by: Paul Mundt <lethal@linux-sh.org> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit d6fa5a4e7ab605370fd6c982782f84ef2e6660e7) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/tty/serial/sh-sci.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c +index 1bd9163..d4d8c94 100644 +--- a/drivers/tty/serial/sh-sci.c ++++ b/drivers/tty/serial/sh-sci.c +@@ -1615,9 +1615,9 @@ static bool filter(struct dma_chan *chan, void *slave) + struct sh_dmae_slave *param = slave; + + dev_dbg(chan->device->dev, "%s: slave ID %d\n", __func__, +- param->slave_id); ++ param->shdma_slave.slave_id); + +- chan->private = param; ++ chan->private = ¶m->shdma_slave; + return true; + } + +@@ -1656,7 +1656,7 @@ static void sci_request_dma(struct uart_port *port) + param = &s->param_tx; + + /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_TX */ +- param->slave_id = s->cfg->dma_slave_tx; ++ param->shdma_slave.slave_id = s->cfg->dma_slave_tx; + + s->cookie_tx = -EINVAL; + chan = dma_request_channel(mask, filter, param); +@@ -1684,7 +1684,7 @@ static void sci_request_dma(struct uart_port *port) + param = &s->param_rx; + + /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_RX */ +- param->slave_id = s->cfg->dma_slave_rx; ++ param->shdma_slave.slave_id = s->cfg->dma_slave_rx; + + chan = dma_request_channel(mask, filter, param); + dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0065-serial-sh-sci-fix-compilation-breakage-when-DMA-is-e.patch b/patches.marzen/0065-serial-sh-sci-fix-compilation-breakage-when-DMA-is-e.patch new file mode 100644 index 0000000000000..543dee31535c1 --- /dev/null +++ b/patches.marzen/0065-serial-sh-sci-fix-compilation-breakage-when-DMA-is-e.patch @@ -0,0 +1,51 @@ +From 3e91d8139916610c1a34ff1359fb866b2bc82bab Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Mon, 30 Jul 2012 21:28:47 +0200 +Subject: serial: sh-sci: fix compilation breakage, when DMA is enabled + +A recent commit: + +commit d6fa5a4e7ab605370fd6c982782f84ef2e6660e7 +Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de> + serial: sh-sci: prepare for conversion to the shdma base library + +is not sufficient to update the sh-sci driver to the new shdma driver +layout. This caused compilation breakage, when CONFIG_SERIAL_SH_SCI_DMA +is enabled. This patch trivially fixes the problem by updating the DMA +descriptor manipulation code. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit 4dc4c51675c137c30838425ecc8d471ff5eb138b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/tty/serial/sh-sci.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c +index d4d8c94..9be296c 100644 +--- a/drivers/tty/serial/sh-sci.c ++++ b/drivers/tty/serial/sh-sci.c +@@ -25,6 +25,7 @@ + + #include <linux/module.h> + #include <linux/errno.h> ++#include <linux/sh_dma.h> + #include <linux/timer.h> + #include <linux/interrupt.h> + #include <linux/tty.h> +@@ -1410,8 +1411,8 @@ static void work_fn_rx(struct work_struct *work) + /* Handle incomplete DMA receive */ + struct tty_struct *tty = port->state->port.tty; + struct dma_chan *chan = s->chan_rx; +- struct sh_desc *sh_desc = container_of(desc, struct sh_desc, +- async_tx); ++ struct shdma_desc *sh_desc = container_of(desc, ++ struct shdma_desc, async_tx); + unsigned long flags; + int count; + +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0066-net-smsc911x-Repair-broken-failure-paths.patch b/patches.marzen/0066-net-smsc911x-Repair-broken-failure-paths.patch new file mode 100644 index 0000000000000..5c96ddc5c9786 --- /dev/null +++ b/patches.marzen/0066-net-smsc911x-Repair-broken-failure-paths.patch @@ -0,0 +1,53 @@ +From 925ce819e01d210634e6108067368107fe17fd8c Mon Sep 17 00:00:00 2001 +From: Lee Jones <lee.jones@linaro.org> +Date: Tue, 29 May 2012 18:47:37 +0000 +Subject: net/smsc911x: Repair broken failure paths + +Current failure paths attempt to free resources which we failed to request +and disable resources which we failed to enable ones. This leads to kernel +oops/panic. This patch does some simple re-ordering to prevent this from +happening. + +Cc: netdev@vger.kernel.org +Signed-off-by: Lee Jones <lee.jones@linaro.org> +Acked-by: Linus Walleij <linus.walleij@linaro.org> +Signed-off-by: David S. Miller <davem@davemloft.net> +(cherry picked from commit 2e1d4a065a77d076a679df22a4eddbc7e33cad98) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/net/ethernet/smsc/smsc911x.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c +index cd3defb..245c700 100644 +--- a/drivers/net/ethernet/smsc/smsc911x.c ++++ b/drivers/net/ethernet/smsc/smsc911x.c +@@ -2389,11 +2389,11 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) + + retval = smsc911x_request_resources(pdev); + if (retval) +- goto out_return_resources; ++ goto out_request_resources_fail; + + retval = smsc911x_enable_resources(pdev); + if (retval) +- goto out_disable_resources; ++ goto out_enable_resources_fail; + + if (pdata->ioaddr == NULL) { + SMSC_WARN(pdata, probe, "Error smsc911x base address invalid"); +@@ -2500,8 +2500,9 @@ out_free_irq: + free_irq(dev->irq, dev); + out_disable_resources: + (void)smsc911x_disable_resources(pdev); +-out_return_resources: ++out_enable_resources_fail: + smsc911x_free_resources(pdev); ++out_request_resources_fail: + platform_set_drvdata(pdev, NULL); + iounmap(pdata->ioaddr); + free_netdev(dev); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0067-smsc911x.c-encapsulate-enable-irq-calls.patch b/patches.marzen/0067-smsc911x.c-encapsulate-enable-irq-calls.patch new file mode 100644 index 0000000000000..b80d5b0d7db53 --- /dev/null +++ b/patches.marzen/0067-smsc911x.c-encapsulate-enable-irq-calls.patch @@ -0,0 +1,70 @@ +From 89b2c2592f45401b0862a70a6d71e4c81274c1a3 Mon Sep 17 00:00:00 2001 +From: Matthias Brugger <mbrugger@iseebcn.com> +Date: Fri, 22 Jun 2012 01:10:15 +0000 +Subject: smsc911x.c: encapsulate enable irq calls + +We encapsulate enbale irq functionality in a function call. +As on probe the interrupts will be disabled twice, we delete +one. + +Signed-off-by: Matthias Brugger <mbrugger@iseebcn.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +(cherry picked from commit 8e27628ecf883b9e5825103e40e6f86bf8225f1a) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/net/ethernet/smsc/smsc911x.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c +index 245c700..759e9b4 100644 +--- a/drivers/net/ethernet/smsc/smsc911x.c ++++ b/drivers/net/ethernet/smsc/smsc911x.c +@@ -1442,6 +1442,14 @@ smsc911x_set_hw_mac_address(struct smsc911x_data *pdata, u8 dev_addr[6]) + smsc911x_mac_write(pdata, ADDRL, mac_low32); + } + ++static void smsc911x_disable_irq_chip(struct net_device *dev) ++{ ++ struct smsc911x_data *pdata = netdev_priv(dev); ++ ++ smsc911x_reg_write(pdata, INT_EN, 0); ++ smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF); ++} ++ + static int smsc911x_open(struct net_device *dev) + { + struct smsc911x_data *pdata = netdev_priv(dev); +@@ -1494,8 +1502,7 @@ static int smsc911x_open(struct net_device *dev) + spin_unlock_irq(&pdata->mac_lock); + + /* Initialise irqs, but leave all sources disabled */ +- smsc911x_reg_write(pdata, INT_EN, 0); +- smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF); ++ smsc911x_disable_irq_chip(dev); + + /* Set interrupt deassertion to 100uS */ + intcfg = ((10 << 24) | INT_CFG_IRQ_EN_); +@@ -2214,9 +2221,6 @@ static int __devinit smsc911x_init(struct net_device *dev) + if (smsc911x_soft_reset(pdata)) + return -ENODEV; + +- /* Disable all interrupt sources until we bring the device up */ +- smsc911x_reg_write(pdata, INT_EN, 0); +- + ether_setup(dev); + dev->flags |= IFF_MULTICAST; + netif_napi_add(dev, &pdata->napi, smsc911x_poll, SMSC_NAPI_WEIGHT); +@@ -2433,8 +2437,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) + smsc911x_reg_write(pdata, INT_CFG, intcfg); + + /* Ensure interrupts are globally disabled before connecting ISR */ +- smsc911x_reg_write(pdata, INT_EN, 0); +- smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF); ++ smsc911x_disable_irq_chip(dev); + + retval = request_irq(dev->irq, smsc911x_irqhandler, + irq_flags | IRQF_SHARED, dev->name, dev); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0068-clocksource-sh_tmu-Convert-timer-lock-to-raw-spinloc.patch b/patches.marzen/0068-clocksource-sh_tmu-Convert-timer-lock-to-raw-spinloc.patch new file mode 100644 index 0000000000000..d7ad043eb4275 --- /dev/null +++ b/patches.marzen/0068-clocksource-sh_tmu-Convert-timer-lock-to-raw-spinloc.patch @@ -0,0 +1,47 @@ +From 3dc719e07177476e63995abda41f8d86f7c6056d Mon Sep 17 00:00:00 2001 +From: Paul Mundt <lethal@linux-sh.org> +Date: Fri, 25 May 2012 13:39:09 +0900 +Subject: clocksource: sh_tmu: Convert timer lock to raw spinlock. + +Signed-off-by: Paul Mundt <lethal@linux-sh.org> +(cherry picked from commit c2225a57e596a308424e59abc7e864f866fe4493) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/clocksource/sh_tmu.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c +index 97f54b6..852b3f1 100644 +--- a/drivers/clocksource/sh_tmu.c ++++ b/drivers/clocksource/sh_tmu.c +@@ -45,7 +45,7 @@ struct sh_tmu_priv { + struct clocksource cs; + }; + +-static DEFINE_SPINLOCK(sh_tmu_lock); ++static DEFINE_RAW_SPINLOCK(sh_tmu_lock); + + #define TSTR -1 /* shared register */ + #define TCOR 0 /* channel register */ +@@ -95,7 +95,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start) + unsigned long flags, value; + + /* start stop register shared by multiple timer channels */ +- spin_lock_irqsave(&sh_tmu_lock, flags); ++ raw_spin_lock_irqsave(&sh_tmu_lock, flags); + value = sh_tmu_read(p, TSTR); + + if (start) +@@ -104,7 +104,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start) + value &= ~(1 << cfg->timer_bit); + + sh_tmu_write(p, TSTR, value); +- spin_unlock_irqrestore(&sh_tmu_lock, flags); ++ raw_spin_unlock_irqrestore(&sh_tmu_lock, flags); + } + + static int sh_tmu_enable(struct sh_tmu_priv *p) +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0069-mmc-tmio-use-MMC-opcode-defines-instead-of-numbers.patch b/patches.marzen/0069-mmc-tmio-use-MMC-opcode-defines-instead-of-numbers.patch new file mode 100644 index 0000000000000..792f03263dc4f --- /dev/null +++ b/patches.marzen/0069-mmc-tmio-use-MMC-opcode-defines-instead-of-numbers.patch @@ -0,0 +1,52 @@ +From 611af69d5a747a3c8d6268a006dd0d913257fe02 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 20 Jun 2012 19:10:35 +0200 +Subject: mmc: tmio: use MMC opcode defines instead of numbers + +mmc.h defines macros for most frequently used MMC opcodes. Use them instead +of hard-coded numbers. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 0f506a96693d8ad4aeccbd98dbd54a3c7357cfa8) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc_pio.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index 9a7996a..0ad3917 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -36,6 +36,7 @@ + #include <linux/mfd/tmio.h> + #include <linux/mmc/cd-gpio.h> + #include <linux/mmc/host.h> ++#include <linux/mmc/mmc.h> + #include <linux/mmc/tmio.h> + #include <linux/module.h> + #include <linux/pagemap.h> +@@ -305,8 +306,8 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command + int c = cmd->opcode; + u32 irq_mask = TMIO_MASK_CMD; + +- /* Command 12 is handled by hardware */ +- if (cmd->opcode == 12 && !cmd->arg) { ++ /* CMD12 is handled by hardware */ ++ if (cmd->opcode == MMC_STOP_TRANSMISSION && !cmd->arg) { + sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x001); + return 0; + } +@@ -449,7 +450,7 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host) + } + + if (stop) { +- if (stop->opcode == 12 && !stop->arg) ++ if (stop->opcode == MMC_STOP_TRANSMISSION && !stop->arg) + sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x000); + else + BUG(); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0070-mmc-cd-gpio-pass-IRQF_ONESHOT-to-request_threaded_ir.patch b/patches.marzen/0070-mmc-cd-gpio-pass-IRQF_ONESHOT-to-request_threaded_ir.patch new file mode 100644 index 0000000000000..325a3c169f92c --- /dev/null +++ b/patches.marzen/0070-mmc-cd-gpio-pass-IRQF_ONESHOT-to-request_threaded_ir.patch @@ -0,0 +1,43 @@ +From a43c0fe8cb2e7a3312b979c3b1fe1ab5b762994a Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Tue, 10 Jul 2012 22:54:11 -0400 +Subject: mmc: cd-gpio: pass IRQF_ONESHOT to request_threaded_irq() + +Fix a boot regression on Mackerel boards with sh_mobile_sdhi +in existing kernels causing: + +genirq: Threaded irq requested with handler=NULL and !ONESHOT for irq XXX + +caused by 1c6c6952 (genirq: Reject bogus threaded irq requests). + +This is backported from Guennadi's patch: +"mmc: extend and rename cd-gpio helpers to handle more slot GPIO functions" + +Reported-by: Rafael J. Wysocki <rjw@sisk.pl> +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 623b51fc8642fd3c795fa9903be3adaa537ad9c5) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/core/cd-gpio.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/mmc/core/cd-gpio.c b/drivers/mmc/core/cd-gpio.c +index f13e38d..8f5dc08 100644 +--- a/drivers/mmc/core/cd-gpio.c ++++ b/drivers/mmc/core/cd-gpio.c +@@ -50,8 +50,8 @@ int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio) + goto egpioreq; + + ret = request_threaded_irq(irq, NULL, mmc_cd_gpio_irqt, +- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, +- cd->label, host); ++ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | ++ IRQF_ONESHOT, cd->label, host); + if (ret < 0) + goto eirqreq; + +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0071-mmc-extend-and-rename-cd-gpio-helpers-to-handle-more.patch b/patches.marzen/0071-mmc-extend-and-rename-cd-gpio-helpers-to-handle-more.patch new file mode 100644 index 0000000000000..7a17b5a007027 --- /dev/null +++ b/patches.marzen/0071-mmc-extend-and-rename-cd-gpio-helpers-to-handle-more.patch @@ -0,0 +1,199 @@ +From 06a2252e0baf7bc5e4dd3b8c31898edcc838b518 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Mon, 30 Apr 2012 23:31:57 +0200 +Subject: mmc: extend and rename cd-gpio helpers to handle more slot GPIO + functions + +GPIOs can be used in MMC/SD-card slots not only for hotplug detection, but +also to implement the write-protection pin. Rename cd-gpio helpers to +slot-gpio to make addition of further slot GPIO functions possible. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit fd0ea65d3e675e479e022b6cfc9ebe1864c76afc) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/core/Makefile | 2 +- + drivers/mmc/core/{cd-gpio.c => slot-gpio.c} | 48 ++++++++++++++-------------- + drivers/mmc/host/tmio_mmc_pio.c | 6 ++-- + include/linux/mmc/{cd-gpio.h => slot-gpio.h} | 8 ++--- + 4 files changed, 32 insertions(+), 32 deletions(-) + rename drivers/mmc/core/{cd-gpio.c => slot-gpio.c} (53%) + rename include/linux/mmc/{cd-gpio.h => slot-gpio.h} (68%) + +diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile +index dca4428..38ed210 100644 +--- a/drivers/mmc/core/Makefile ++++ b/drivers/mmc/core/Makefile +@@ -7,6 +7,6 @@ mmc_core-y := core.o bus.o host.o \ + mmc.o mmc_ops.o sd.o sd_ops.o \ + sdio.o sdio_ops.o sdio_bus.o \ + sdio_cis.o sdio_io.o sdio_irq.o \ +- quirks.o cd-gpio.o ++ quirks.o slot-gpio.o + + mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o +diff --git a/drivers/mmc/core/cd-gpio.c b/drivers/mmc/core/slot-gpio.c +similarity index 53% +rename from drivers/mmc/core/cd-gpio.c +rename to drivers/mmc/core/slot-gpio.c +index 8f5dc08..9796710 100644 +--- a/drivers/mmc/core/cd-gpio.c ++++ b/drivers/mmc/core/slot-gpio.c +@@ -12,72 +12,72 @@ + #include <linux/gpio.h> + #include <linux/interrupt.h> + #include <linux/jiffies.h> +-#include <linux/mmc/cd-gpio.h> + #include <linux/mmc/host.h> ++#include <linux/mmc/slot-gpio.h> + #include <linux/module.h> + #include <linux/slab.h> + +-struct mmc_cd_gpio { +- unsigned int gpio; +- char label[0]; ++struct mmc_gpio { ++ unsigned int cd_gpio; ++ char cd_label[0]; + }; + +-static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id) ++static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) + { + /* Schedule a card detection after a debounce timeout */ + mmc_detect_change(dev_id, msecs_to_jiffies(100)); + return IRQ_HANDLED; + } + +-int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio) ++int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) + { + size_t len = strlen(dev_name(host->parent)) + 4; +- struct mmc_cd_gpio *cd; ++ struct mmc_gpio *ctx; + int irq = gpio_to_irq(gpio); + int ret; + + if (irq < 0) + return irq; + +- cd = kmalloc(sizeof(*cd) + len, GFP_KERNEL); +- if (!cd) ++ ctx = kmalloc(sizeof(*ctx) + len, GFP_KERNEL); ++ if (!ctx) + return -ENOMEM; + +- snprintf(cd->label, len, "%s cd", dev_name(host->parent)); ++ snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent)); + +- ret = gpio_request_one(gpio, GPIOF_DIR_IN, cd->label); ++ ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->cd_label); + if (ret < 0) + goto egpioreq; + +- ret = request_threaded_irq(irq, NULL, mmc_cd_gpio_irqt, +- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | +- IRQF_ONESHOT, cd->label, host); ++ ret = request_threaded_irq(irq, NULL, mmc_gpio_cd_irqt, ++ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, ++ ctx->cd_label, host); + if (ret < 0) + goto eirqreq; + +- cd->gpio = gpio; ++ ctx->cd_gpio = gpio; + host->hotplug.irq = irq; +- host->hotplug.handler_priv = cd; ++ host->hotplug.handler_priv = ctx; + + return 0; + + eirqreq: + gpio_free(gpio); + egpioreq: +- kfree(cd); ++ kfree(ctx); + return ret; + } +-EXPORT_SYMBOL(mmc_cd_gpio_request); ++EXPORT_SYMBOL(mmc_gpio_request_cd); + +-void mmc_cd_gpio_free(struct mmc_host *host) ++void mmc_gpio_free_cd(struct mmc_host *host) + { +- struct mmc_cd_gpio *cd = host->hotplug.handler_priv; ++ struct mmc_gpio *ctx = host->hotplug.handler_priv; + +- if (!cd) ++ if (!ctx) + return; + + free_irq(host->hotplug.irq, host); +- gpio_free(cd->gpio); +- kfree(cd); ++ gpio_free(ctx->cd_gpio); ++ kfree(ctx); + } +-EXPORT_SYMBOL(mmc_cd_gpio_free); ++EXPORT_SYMBOL(mmc_gpio_free_cd); +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index 0ad3917..7ffc489 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -34,9 +34,9 @@ + #include <linux/io.h> + #include <linux/irq.h> + #include <linux/mfd/tmio.h> +-#include <linux/mmc/cd-gpio.h> + #include <linux/mmc/host.h> + #include <linux/mmc/mmc.h> ++#include <linux/mmc/slot-gpio.h> + #include <linux/mmc/tmio.h> + #include <linux/module.h> + #include <linux/pagemap.h> +@@ -977,7 +977,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + tmio_mmc_enable_mmc_irqs(_host, irq_mask); + + if (pdata->flags & TMIO_MMC_USE_GPIO_CD) { +- ret = mmc_cd_gpio_request(mmc, pdata->cd_gpio); ++ ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio); + if (ret < 0) { + tmio_mmc_host_remove(_host); + return ret; +@@ -1009,7 +1009,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host) + * This means we can miss a card-eject, but this is anyway + * possible, because of delayed processing of hotplug events. + */ +- mmc_cd_gpio_free(mmc); ++ mmc_gpio_free_cd(mmc); + + if (!host->native_hotplug) + pm_runtime_get_sync(&pdev->dev); +diff --git a/include/linux/mmc/cd-gpio.h b/include/linux/mmc/slot-gpio.h +similarity index 68% +rename from include/linux/mmc/cd-gpio.h +rename to include/linux/mmc/slot-gpio.h +index cefaba0..edfaa32 100644 +--- a/include/linux/mmc/cd-gpio.h ++++ b/include/linux/mmc/slot-gpio.h +@@ -8,11 +8,11 @@ + * published by the Free Software Foundation. + */ + +-#ifndef MMC_CD_GPIO_H +-#define MMC_CD_GPIO_H ++#ifndef MMC_SLOT_GPIO_H ++#define MMC_SLOT_GPIO_H + + struct mmc_host; +-int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio); +-void mmc_cd_gpio_free(struct mmc_host *host); ++int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio); ++void mmc_gpio_free_cd(struct mmc_host *host); + + #endif +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0072-mmc-tmio-Don-t-access-hardware-registers-after-stopp.patch b/patches.marzen/0072-mmc-tmio-Don-t-access-hardware-registers-after-stopp.patch new file mode 100644 index 0000000000000..a3be21ce973b7 --- /dev/null +++ b/patches.marzen/0072-mmc-tmio-Don-t-access-hardware-registers-after-stopp.patch @@ -0,0 +1,66 @@ +From b1c9b658ce7354835934388f45df16bfd25a37fc Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Tue, 12 Jun 2012 23:29:35 +0200 +Subject: mmc: tmio: Don't access hardware registers after stopping clocks + +The tmio_mmc_set_ios() function configures the MMC power, clock and bus +width. When the mmc core requests the driver to power off the card, we +inform runtime PM, that the controller can be suspended. This can lead +to the MSTP clock being turned off. + +Writing to any 16-bit hardware registers with the MSTP clock off leads +to timeouts and errors being printed to the kernel log. This can occur +both when stopping the MMC clock and when configuring the bus width. + +To fix this, stop the MMC clock before calling put_runtime_pm(), and +skip bus width configuration when power is off. + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Tested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Simon Horman <horms@verge.net.au> +Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 6de707f200f73af7a58b58b3a5b956cff7b6e228) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc_pio.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index 7ffc489..4f26edf 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -811,19 +811,21 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + if (host->set_pwr && ios->power_mode == MMC_POWER_OFF) + host->set_pwr(host->pdev, 0); + if (host->power) { ++ tmio_mmc_clk_stop(host); + host->power = false; + pm_runtime_put(dev); + } +- tmio_mmc_clk_stop(host); + } + +- switch (ios->bus_width) { +- case MMC_BUS_WIDTH_1: +- sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0); +- break; +- case MMC_BUS_WIDTH_4: +- sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0); +- break; ++ if (host->power) { ++ switch (ios->bus_width) { ++ case MMC_BUS_WIDTH_1: ++ sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0); ++ break; ++ case MMC_BUS_WIDTH_4: ++ sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0); ++ break; ++ } + } + + /* Let things settle. delay taken from winCE driver */ +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0073-mmc-tmio-don-t-needlessly-enable-interrupts-during-p.patch b/patches.marzen/0073-mmc-tmio-don-t-needlessly-enable-interrupts-during-p.patch new file mode 100644 index 0000000000000..0ccb9cd52163a --- /dev/null +++ b/patches.marzen/0073-mmc-tmio-don-t-needlessly-enable-interrupts-during-p.patch @@ -0,0 +1,60 @@ +From 13b6cca29fb687ec7821001eb9bc38ba8a6270a1 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 20 Jun 2012 19:10:30 +0200 +Subject: mmc: tmio: don't needlessly enable interrupts during probing + +We don't have to force-enable MMC interrupts in our .probe() method, +mmc_add_host() will trigger card detection, that will enable all the +necessary interrupts. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit e0337cc8b02fcb3f725746735db84d6d1b6b9196) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc_pio.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index 4f26edf..4318c1a 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -951,6 +951,17 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + + _host->sdcard_irq_mask = sd_ctrl_read32(_host, CTL_IRQ_MASK); + tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL); ++ ++ /* Unmask the IRQs we want to know about */ ++ if (!_host->chan_rx) ++ irq_mask |= TMIO_MASK_READOP; ++ if (!_host->chan_tx) ++ irq_mask |= TMIO_MASK_WRITEOP; ++ if (!_host->native_hotplug) ++ irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT); ++ ++ _host->sdcard_irq_mask &= ~irq_mask; ++ + if (pdata->flags & TMIO_MMC_SDIO_IRQ) + tmio_mmc_enable_sdio_irq(mmc, 0); + +@@ -968,16 +979,6 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + + dev_pm_qos_expose_latency_limit(&pdev->dev, 100); + +- /* Unmask the IRQs we want to know about */ +- if (!_host->chan_rx) +- irq_mask |= TMIO_MASK_READOP; +- if (!_host->chan_tx) +- irq_mask |= TMIO_MASK_WRITEOP; +- if (!_host->native_hotplug) +- irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT); +- +- tmio_mmc_enable_mmc_irqs(_host, irq_mask); +- + if (pdata->flags & TMIO_MMC_USE_GPIO_CD) { + ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio); + if (ret < 0) { +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0074-mmc-sdhi-implement-tmio-mmc-clock-enable-update-and-.patch b/patches.marzen/0074-mmc-sdhi-implement-tmio-mmc-clock-enable-update-and-.patch new file mode 100644 index 0000000000000..a5ee7203d1faa --- /dev/null +++ b/patches.marzen/0074-mmc-sdhi-implement-tmio-mmc-clock-enable-update-and-.patch @@ -0,0 +1,66 @@ +From 9000384872b9fb65e1fb9b7042da31d2d4023c7b Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 20 Jun 2012 19:10:32 +0200 +Subject: mmc: sdhi: implement tmio-mmc clock enable-update and disable + callbacks + +Instead of delivering one static clock frequency value, read from the +hardware during probing, enable the tmio-mmc driver to re-read the +frequency dynamically. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 56c492879318f43b1a7911675ff30fb0ede123b5) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mobile_sdhi.c | 24 +++++++++++++++++++++++- + 1 file changed, 23 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index 934b68e..d8b167c 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -39,6 +39,27 @@ struct sh_mobile_sdhi { + struct tmio_mmc_dma dma_priv; + }; + ++static int sh_mobile_sdhi_clk_enable(struct platform_device *pdev, unsigned int *f) ++{ ++ struct mmc_host *mmc = dev_get_drvdata(&pdev->dev); ++ struct tmio_mmc_host *host = mmc_priv(mmc); ++ struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); ++ int ret = clk_enable(priv->clk); ++ if (ret < 0) ++ return ret; ++ ++ *f = clk_get_rate(priv->clk); ++ return 0; ++} ++ ++static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc = dev_get_drvdata(&pdev->dev); ++ struct tmio_mmc_host *host = mmc_priv(mmc); ++ struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); ++ clk_disable(priv->clk); ++} ++ + static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state) + { + struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; +@@ -132,9 +153,10 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + goto eclkget; + } + +- mmc_data->hclk = clk_get_rate(priv->clk); + mmc_data->set_pwr = sh_mobile_sdhi_set_pwr; + mmc_data->get_cd = sh_mobile_sdhi_get_cd; ++ mmc_data->clk_enable = sh_mobile_sdhi_clk_enable; ++ mmc_data->clk_disable = sh_mobile_sdhi_clk_disable; + mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED; + if (p) { + mmc_data->flags = p->tmio_flags; +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0075-mmc-tmio-add-callbacks-to-enable-update-and-disable-.patch b/patches.marzen/0075-mmc-tmio-add-callbacks-to-enable-update-and-disable-.patch new file mode 100644 index 0000000000000..bf6f327b3aaa6 --- /dev/null +++ b/patches.marzen/0075-mmc-tmio-add-callbacks-to-enable-update-and-disable-.patch @@ -0,0 +1,120 @@ +From 2351d645d302b589c88ca21a2ea3198fd7bfa752 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 20 Jun 2012 19:10:31 +0200 +Subject: mmc: tmio: add callbacks to enable-update and disable the interface + clock + +Every time the clock is enabled after possibly being disabled, we have +to re-read its frequency and update our configuration. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 8c102a964655b1a8df41b1f9e2355657471a45e3) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc_pio.c | 35 ++++++++++++++++++++++++++++++++--- + include/linux/mfd/tmio.h | 3 +++ + 2 files changed, 35 insertions(+), 3 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index 4318c1a..c6c0334 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -752,6 +752,22 @@ fail: + mmc_request_done(mmc, mrq); + } + ++static int tmio_mmc_clk_update(struct mmc_host *mmc) ++{ ++ struct tmio_mmc_host *host = mmc_priv(mmc); ++ struct tmio_mmc_data *pdata = host->pdata; ++ int ret; ++ ++ if (!pdata->clk_enable) ++ return -ENOTSUPP; ++ ++ ret = pdata->clk_enable(host->pdev, &mmc->f_max); ++ if (!ret) ++ mmc->f_min = mmc->f_max / 512; ++ ++ return ret; ++} ++ + /* Set MMC clock / power. + * Note: This controller uses a simple divider scheme therefore it cannot + * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as +@@ -798,6 +814,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + */ + if (ios->power_mode == MMC_POWER_ON && ios->clock) { + if (!host->power) { ++ tmio_mmc_clk_update(mmc); + pm_runtime_get_sync(dev); + host->power = true; + } +@@ -811,9 +828,12 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + if (host->set_pwr && ios->power_mode == MMC_POWER_OFF) + host->set_pwr(host->pdev, 0); + if (host->power) { ++ struct tmio_mmc_data *pdata = host->pdata; + tmio_mmc_clk_stop(host); + host->power = false; + pm_runtime_put(dev); ++ if (pdata->clk_disable) ++ pdata->clk_disable(host->pdev); + } + } + +@@ -907,8 +927,6 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + + mmc->ops = &tmio_mmc_ops; + mmc->caps = MMC_CAP_4_BIT_DATA | pdata->capabilities; +- mmc->f_max = pdata->hclk; +- mmc->f_min = mmc->f_max / 512; + mmc->max_segs = 32; + mmc->max_blk_size = 512; + mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) * +@@ -930,6 +948,11 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + if (ret < 0) + goto pm_disable; + ++ if (tmio_mmc_clk_update(mmc) < 0) { ++ mmc->f_max = pdata->hclk; ++ mmc->f_min = mmc->f_max / 512; ++ } ++ + /* + * There are 4 different scenarios for the card detection: + * 1) an external gpio irq handles the cd (best for power savings) +@@ -975,7 +998,13 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + /* See if we also get DMA */ + tmio_mmc_request_dma(_host, pdata); + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (pdata->clk_disable) ++ pdata->clk_disable(pdev); ++ if (ret < 0) { ++ tmio_mmc_host_remove(_host); ++ return ret; ++ } + + dev_pm_qos_expose_latency_limit(&pdev->dev, 100); + +diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h +index f5171db..b332c4c 100644 +--- a/include/linux/mfd/tmio.h ++++ b/include/linux/mfd/tmio.h +@@ -110,6 +110,9 @@ struct tmio_mmc_data { + void (*set_clk_div)(struct platform_device *host, int state); + int (*get_cd)(struct platform_device *host); + int (*write16_hook)(struct tmio_mmc_host *host, int addr); ++ /* clock management callbacks */ ++ int (*clk_enable)(struct platform_device *pdev, unsigned int *f); ++ void (*clk_disable)(struct platform_device *pdev); + }; + + /* +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0076-mmc-sdhi-do-not-install-dummy-callbacks.patch b/patches.marzen/0076-mmc-sdhi-do-not-install-dummy-callbacks.patch new file mode 100644 index 0000000000000..dba509b359093 --- /dev/null +++ b/patches.marzen/0076-mmc-sdhi-do-not-install-dummy-callbacks.patch @@ -0,0 +1,62 @@ +From 399a8f308acebcabaa5c10f336668cd3f73ac273 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 20 Jun 2012 19:10:34 +0200 +Subject: mmc: sdhi: do not install dummy callbacks + +Currently the SDHI glue for the TMIO MMC driver installs dummy .get_cd() and +.set_pwr() callbacks even if the platform didn't supply them. This is not +necessary, since the TMIO MMC driver itself checks for NULL callbacks. This +is also dubious if the platform provides a regulator for SD-card power +switching. It is better to only install those callbacks, if they are really +provided by the platform. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 71da63e767c393c0ebbd3c65df428df0ce42a16c) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mobile_sdhi.c | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index d8b167c..42f07fa 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -64,18 +64,14 @@ static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state) + { + struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; + +- if (p && p->set_pwr) +- p->set_pwr(pdev, state); ++ p->set_pwr(pdev, state); + } + + static int sh_mobile_sdhi_get_cd(struct platform_device *pdev) + { + struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; + +- if (p && p->get_cd) +- return p->get_cd(pdev); +- else +- return -ENOSYS; ++ return p->get_cd(pdev); + } + + static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host) +@@ -153,8 +149,10 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + goto eclkget; + } + +- mmc_data->set_pwr = sh_mobile_sdhi_set_pwr; +- mmc_data->get_cd = sh_mobile_sdhi_get_cd; ++ if (p->set_pwr) ++ mmc_data->set_pwr = sh_mobile_sdhi_set_pwr; ++ if (p->get_cd) ++ mmc_data->get_cd = sh_mobile_sdhi_get_cd; + mmc_data->clk_enable = sh_mobile_sdhi_clk_enable; + mmc_data->clk_disable = sh_mobile_sdhi_clk_disable; + mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED; +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0077-mmc-add-a-function-to-get-regulators-supplying-card-.patch b/patches.marzen/0077-mmc-add-a-function-to-get-regulators-supplying-card-.patch new file mode 100644 index 0000000000000..983f2ae756636 --- /dev/null +++ b/patches.marzen/0077-mmc-add-a-function-to-get-regulators-supplying-card-.patch @@ -0,0 +1,112 @@ +From 23b39f743c1d33128add46201409eb6709b10a4f Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 20 Jun 2012 02:28:43 -0400 +Subject: mmc: add a function to get regulators, supplying card's power + +Add a function to get regulators, supplying card's Vdd and Vccq on a +specific host. If a Vdd supplying regulator is found, the function checks, +whether a valid OCR mask can be obtained from it. The Vccq regulator is +optional. A failure to get it is not fatal. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Reviwed-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +Acked-by: Ulf Hansson <ulf.hansson@linaro.org> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit e137788dd115dd9d21759a768dba5fff9685e587) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/core/core.c | 23 +++++++++++++++++++++++ + include/linux/mmc/host.h | 16 ++++++++++++++-- + 2 files changed, 37 insertions(+), 2 deletions(-) + +diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c +index ba821fe..1db77e7 100644 +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -1012,6 +1012,29 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc, + } + EXPORT_SYMBOL(mmc_regulator_set_ocr); + ++int mmc_regulator_get_supply(struct mmc_host *mmc) ++{ ++ struct device *dev = mmc_dev(mmc); ++ struct regulator *supply; ++ int ret; ++ ++ supply = devm_regulator_get(dev, "vmmc"); ++ mmc->supply.vmmc = supply; ++ mmc->supply.vqmmc = devm_regulator_get(dev, "vqmmc"); ++ ++ if (IS_ERR(supply)) ++ return PTR_ERR(supply); ++ ++ ret = mmc_regulator_get_ocrmask(supply); ++ if (ret > 0) ++ mmc->ocr_avail = ret; ++ else ++ dev_warn(mmc_dev(mmc), "Failed getting OCR mask: %d\n", ret); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(mmc_regulator_get_supply); ++ + #endif /* CONFIG_REGULATOR */ + + /* +diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h +index 0707d22..9deb725 100644 +--- a/include/linux/mmc/host.h ++++ b/include/linux/mmc/host.h +@@ -155,6 +155,13 @@ struct mmc_hotplug { + void *handler_priv; + }; + ++struct regulator; ++ ++struct mmc_supply { ++ struct regulator *vmmc; /* Card power supply */ ++ struct regulator *vqmmc; /* Optional Vccq supply */ ++}; ++ + struct mmc_host { + struct device *parent; + struct device class_dev; +@@ -309,6 +316,7 @@ struct mmc_host { + #ifdef CONFIG_REGULATOR + bool regulator_enabled; /* regulator state */ + #endif ++ struct mmc_supply supply; + + struct dentry *debugfs_root; + +@@ -357,13 +365,12 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host) + wake_up_process(host->sdio_irq_thread); + } + +-struct regulator; +- + #ifdef CONFIG_REGULATOR + int mmc_regulator_get_ocrmask(struct regulator *supply); + int mmc_regulator_set_ocr(struct mmc_host *mmc, + struct regulator *supply, + unsigned short vdd_bit); ++int mmc_regulator_get_supply(struct mmc_host *mmc); + #else + static inline int mmc_regulator_get_ocrmask(struct regulator *supply) + { +@@ -376,6 +383,11 @@ static inline int mmc_regulator_set_ocr(struct mmc_host *mmc, + { + return 0; + } ++ ++static inline int mmc_regulator_get_supply(struct mmc_host *mmc) ++{ ++ return 0; ++} + #endif + + int mmc_card_awake(struct mmc_host *host); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0078-mmc-tmio-add-regulator-support.patch b/patches.marzen/0078-mmc-tmio-add-regulator-support.patch new file mode 100644 index 0000000000000..7c18978e52d5f --- /dev/null +++ b/patches.marzen/0078-mmc-tmio-add-regulator-support.patch @@ -0,0 +1,95 @@ +From 2f82c1eaa54c5b6eb2d1bc04cd04add57ca9ad05 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 20 Jun 2012 19:10:33 +0200 +Subject: mmc: tmio: add regulator support + +Currently the TMIO MMC driver derives the OCR mask from the platform data +and uses a platform callback to turn card power on and off. This patch adds +regulator support to the driver. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Cc: Liam Girdwood <lrg@ti.com> +Cc: Mark Brown <broonie@opensource.wolfsonmicro.com> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit b958a67c6bbe0a886bebc618aac7a059cdbab418) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc_pio.c | 37 +++++++++++++++++++++++++++++-------- + 1 file changed, 29 insertions(+), 8 deletions(-) + +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index c6c0334..b5c32b4 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -768,6 +768,18 @@ static int tmio_mmc_clk_update(struct mmc_host *mmc) + return ret; + } + ++static void tmio_mmc_set_power(struct tmio_mmc_host *host, struct mmc_ios *ios) ++{ ++ struct mmc_host *mmc = host->mmc; ++ ++ if (host->set_pwr) ++ host->set_pwr(host->pdev, ios->power_mode != MMC_POWER_OFF); ++ if (!IS_ERR(mmc->supply.vmmc)) ++ /* Errors ignored... */ ++ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ++ ios->power_mode ? ios->vdd : 0); ++} ++ + /* Set MMC clock / power. + * Note: This controller uses a simple divider scheme therefore it cannot + * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as +@@ -820,13 +832,12 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + } + tmio_mmc_set_clock(host, ios->clock); + /* power up SD bus */ +- if (host->set_pwr) +- host->set_pwr(host->pdev, 1); ++ tmio_mmc_set_power(host, ios); + /* start bus clock */ + tmio_mmc_clk_start(host); + } else if (ios->power_mode != MMC_POWER_UP) { +- if (host->set_pwr && ios->power_mode == MMC_POWER_OFF) +- host->set_pwr(host->pdev, 0); ++ if (ios->power_mode == MMC_POWER_OFF) ++ tmio_mmc_set_power(host, ios); + if (host->power) { + struct tmio_mmc_data *pdata = host->pdata; + tmio_mmc_clk_stop(host); +@@ -888,6 +899,19 @@ static const struct mmc_host_ops tmio_mmc_ops = { + .enable_sdio_irq = tmio_mmc_enable_sdio_irq, + }; + ++static void tmio_mmc_init_ocr(struct tmio_mmc_host *host) ++{ ++ struct tmio_mmc_data *pdata = host->pdata; ++ struct mmc_host *mmc = host->mmc; ++ ++ mmc_regulator_get_supply(mmc); ++ ++ if (!mmc->ocr_avail) ++ mmc->ocr_avail = pdata->ocr_mask ? : MMC_VDD_32_33 | MMC_VDD_33_34; ++ else if (pdata->ocr_mask) ++ dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n"); ++} ++ + int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + struct platform_device *pdev, + struct tmio_mmc_data *pdata) +@@ -933,10 +957,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + mmc->max_segs; + mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; + mmc->max_seg_size = mmc->max_req_size; +- if (pdata->ocr_mask) +- mmc->ocr_avail = pdata->ocr_mask; +- else +- mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; ++ tmio_mmc_init_ocr(_host); + + _host->native_hotplug = !(pdata->flags & TMIO_MMC_USE_GPIO_CD || + mmc->caps & MMC_CAP_NEEDS_POLL || +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0079-mmc-tmio-remove-a-duplicated-comment-line.patch b/patches.marzen/0079-mmc-tmio-remove-a-duplicated-comment-line.patch new file mode 100644 index 0000000000000..e7c85da77123d --- /dev/null +++ b/patches.marzen/0079-mmc-tmio-remove-a-duplicated-comment-line.patch @@ -0,0 +1,29 @@ +From edc14a6a575b9ed664f5618b40bb720801514acc Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 20 Jun 2012 19:10:36 +0200 +Subject: mmc: tmio: remove a duplicated comment line + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 944640d0fffb2ee2961a24c3747b1fc87c4157a8) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc_pio.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index b5c32b4..b204012f 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -984,7 +984,6 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + * While we increment the runtime PM counter for all scenarios when + * the mmc core activates us by calling an appropriate set_ios(), we + * must additionally ensure that in case 2) the tmio mmc hardware stays +- * additionally ensure that in case 2) the tmio mmc hardware stays + * powered on during runtime for the card detection to work. + */ + if (_host->native_hotplug) +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0080-mmc-tmio-support-caps2-flags.patch b/patches.marzen/0080-mmc-tmio-support-caps2-flags.patch new file mode 100644 index 0000000000000..ce76873aba016 --- /dev/null +++ b/patches.marzen/0080-mmc-tmio-support-caps2-flags.patch @@ -0,0 +1,45 @@ +From 84ff72e8bc8a05f00821fa782bda46ba105ce831 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 23 May 2012 10:44:37 +0200 +Subject: mmc: tmio: support caps2 flags + +Allow tmio mmc glue drivers to pass mmc_host::caps2 flags down to +the mmc layer. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 02cb3221d5bb351ad9f7469453dcca7594a0fabf) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc_pio.c | 1 + + include/linux/mfd/tmio.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index b204012f..f8df021 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -951,6 +951,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, + + mmc->ops = &tmio_mmc_ops; + mmc->caps = MMC_CAP_4_BIT_DATA | pdata->capabilities; ++ mmc->caps2 = pdata->capabilities2; + mmc->max_segs = 32; + mmc->max_blk_size = 512; + mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) * +diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h +index b332c4c..d83af39 100644 +--- a/include/linux/mfd/tmio.h ++++ b/include/linux/mfd/tmio.h +@@ -101,6 +101,7 @@ struct tmio_mmc_host; + struct tmio_mmc_data { + unsigned int hclk; + unsigned long capabilities; ++ unsigned long capabilities2; + unsigned long flags; + u32 ocr_mask; /* available voltages */ + struct tmio_mmc_dma *dma; +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0081-mmc-sh_mobile_sdhi-support-caps2-flags.patch b/patches.marzen/0081-mmc-sh_mobile_sdhi-support-caps2-flags.patch new file mode 100644 index 0000000000000..d88c5291f99e5 --- /dev/null +++ b/patches.marzen/0081-mmc-sh_mobile_sdhi-support-caps2-flags.patch @@ -0,0 +1,44 @@ +From ab7669dbefddb9148fbda646fe4746a1a33f914f Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 23 May 2012 11:05:33 +0200 +Subject: mmc: sh_mobile_sdhi: support caps2 flags + +Let SDHI platforms specify mmc_host::caps2 flags in their platform data. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit d7d8d500bc03891c4a86da49858c46e2db256581) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mobile_sdhi.c | 1 + + include/linux/mmc/sh_mobile_sdhi.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index 42f07fa..1e7c5c4 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -162,6 +162,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + mmc_data->write16_hook = sh_mobile_sdhi_write16_hook; + mmc_data->ocr_mask = p->tmio_ocr_mask; + mmc_data->capabilities |= p->tmio_caps; ++ mmc_data->capabilities2 |= p->tmio_caps2; + mmc_data->cd_gpio = p->cd_gpio; + + if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) { +diff --git a/include/linux/mmc/sh_mobile_sdhi.h b/include/linux/mmc/sh_mobile_sdhi.h +index e94e620..b65679f 100644 +--- a/include/linux/mmc/sh_mobile_sdhi.h ++++ b/include/linux/mmc/sh_mobile_sdhi.h +@@ -23,6 +23,7 @@ struct sh_mobile_sdhi_info { + int dma_slave_rx; + unsigned long tmio_flags; + unsigned long tmio_caps; ++ unsigned long tmio_caps2; + u32 tmio_ocr_mask; /* available MMC voltages */ + unsigned int cd_gpio; + struct tmio_mmc_data *pdata; +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0082-mmc-sdhi-add-OF-support-make-platform-data-optional.patch b/patches.marzen/0082-mmc-sdhi-add-OF-support-make-platform-data-optional.patch new file mode 100644 index 0000000000000..ee219f323d7a5 --- /dev/null +++ b/patches.marzen/0082-mmc-sdhi-add-OF-support-make-platform-data-optional.patch @@ -0,0 +1,121 @@ +From a19323115f3cf3e2e7f0b56ce75752ed2e682bfb Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Tue, 1 May 2012 18:03:43 +0200 +Subject: mmc: sdhi: add OF support, make platform data optional + +Add primitive support for OF to the SDHI TMIO glue, which also makes it +necessary to be able to run without platform data. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit c7bb4487a3474c03986758595fcae1cfb771b3b0) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mobile_sdhi.c | 35 +++++++++++++++++++++++------------ + 1 file changed, 23 insertions(+), 12 deletions(-) + +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index 1e7c5c4..a842939 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -21,6 +21,7 @@ + #include <linux/kernel.h> + #include <linux/clk.h> + #include <linux/slab.h> ++#include <linux/mod_devicetable.h> + #include <linux/module.h> + #include <linux/platform_device.h> + #include <linux/mmc/host.h> +@@ -133,12 +134,14 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + } + + mmc_data = &priv->mmc_data; +- p->pdata = mmc_data; + +- if (p->init) { +- ret = p->init(pdev, &sdhi_ops); +- if (ret) +- goto einit; ++ if (p) { ++ p->pdata = mmc_data; ++ if (p->init) { ++ ret = p->init(pdev, &sdhi_ops); ++ if (ret) ++ goto einit; ++ } + } + + snprintf(clk_name, sizeof(clk_name), "sdhi%d", pdev->id); +@@ -149,10 +152,6 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + goto eclkget; + } + +- if (p->set_pwr) +- mmc_data->set_pwr = sh_mobile_sdhi_set_pwr; +- if (p->get_cd) +- mmc_data->get_cd = sh_mobile_sdhi_get_cd; + mmc_data->clk_enable = sh_mobile_sdhi_clk_enable; + mmc_data->clk_disable = sh_mobile_sdhi_clk_disable; + mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED; +@@ -164,6 +163,10 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + mmc_data->capabilities |= p->tmio_caps; + mmc_data->capabilities2 |= p->tmio_caps2; + mmc_data->cd_gpio = p->cd_gpio; ++ if (p->set_pwr) ++ mmc_data->set_pwr = sh_mobile_sdhi_set_pwr; ++ if (p->get_cd) ++ mmc_data->get_cd = sh_mobile_sdhi_get_cd; + + if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) { + priv->param_tx.slave_id = p->dma_slave_tx; +@@ -269,7 +272,7 @@ eirq_card_detect: + eprobe: + clk_put(priv->clk); + eclkget: +- if (p->cleanup) ++ if (p && p->cleanup) + p->cleanup(pdev); + einit: + kfree(priv); +@@ -284,7 +287,8 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev) + struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; + int i = 0, irq; + +- p->pdata = NULL; ++ if (p) ++ p->pdata = NULL; + + tmio_mmc_host_remove(host); + +@@ -297,7 +301,7 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev) + + clk_put(priv->clk); + +- if (p->cleanup) ++ if (p && p->cleanup) + p->cleanup(pdev); + + kfree(priv); +@@ -312,11 +316,18 @@ static const struct dev_pm_ops tmio_mmc_dev_pm_ops = { + .runtime_resume = tmio_mmc_host_runtime_resume, + }; + ++static const struct of_device_id sh_mobile_sdhi_of_match[] = { ++ { .compatible = "renesas,shmobile-sdhi" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match); ++ + static struct platform_driver sh_mobile_sdhi_driver = { + .driver = { + .name = "sh_mobile_sdhi", + .owner = THIS_MODULE, + .pm = &tmio_mmc_dev_pm_ops, ++ .of_match_table = sh_mobile_sdhi_of_match, + }, + .probe = sh_mobile_sdhi_probe, + .remove = __devexit_p(sh_mobile_sdhi_remove), +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0083-mmc-core-use-a-more-generic-name-for-slot-function-t.patch b/patches.marzen/0083-mmc-core-use-a-more-generic-name-for-slot-function-t.patch new file mode 100644 index 0000000000000..03ec82ddad882 --- /dev/null +++ b/patches.marzen/0083-mmc-core-use-a-more-generic-name-for-slot-function-t.patch @@ -0,0 +1,100 @@ +From 3383b414d84936e9695df242dbe081140e7b0fbd Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Tue, 1 May 2012 15:40:15 +0200 +Subject: mmc: core: use a more generic name for slot function types and fields + +struct mmc_host::hotplug is becoming a generic hook for slot functions. +Rename it accordingly. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 27410ee7e391ce650d6d0242805f080599be7ad7) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/core/host.c | 2 ++ + drivers/mmc/core/slot-gpio.c | 8 ++++---- + include/linux/mmc/host.h | 17 ++++++++++++++--- + 3 files changed, 20 insertions(+), 7 deletions(-) + +diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c +index 91c84c7..b8c5290 100644 +--- a/drivers/mmc/core/host.c ++++ b/drivers/mmc/core/host.c +@@ -327,6 +327,8 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) + + mmc_host_clk_init(host); + ++ host->slot.cd_irq = -EINVAL; ++ + spin_lock_init(&host->lock); + init_waitqueue_head(&host->wq); + INIT_DELAYED_WORK(&host->detect, mmc_rescan); +diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c +index 9796710..468e5a0 100644 +--- a/drivers/mmc/core/slot-gpio.c ++++ b/drivers/mmc/core/slot-gpio.c +@@ -56,8 +56,8 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) + goto eirqreq; + + ctx->cd_gpio = gpio; +- host->hotplug.irq = irq; +- host->hotplug.handler_priv = ctx; ++ host->slot.cd_irq = irq; ++ host->slot.handler_priv = ctx; + + return 0; + +@@ -71,12 +71,12 @@ EXPORT_SYMBOL(mmc_gpio_request_cd); + + void mmc_gpio_free_cd(struct mmc_host *host) + { +- struct mmc_gpio *ctx = host->hotplug.handler_priv; ++ struct mmc_gpio *ctx = host->slot.handler_priv; + + if (!ctx) + return; + +- free_irq(host->hotplug.irq, host); ++ free_irq(host->slot.cd_irq, host); + gpio_free(ctx->cd_gpio); + kfree(ctx); + } +diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h +index 9deb725..90b6a38 100644 +--- a/include/linux/mmc/host.h ++++ b/include/linux/mmc/host.h +@@ -150,8 +150,19 @@ struct mmc_async_req { + int (*err_check) (struct mmc_card *, struct mmc_async_req *); + }; + +-struct mmc_hotplug { +- unsigned int irq; ++/** ++ * struct mmc_slot - MMC slot functions ++ * ++ * @cd_irq: MMC/SD-card slot hotplug detection IRQ or -EINVAL ++ * @handler_priv: MMC/SD-card slot context ++ * ++ * Some MMC/SD host controllers implement slot-functions like card and ++ * write-protect detection natively. However, a large number of controllers ++ * leave these functions to the CPU. This struct provides a hook to attach ++ * such slot-function drivers. ++ */ ++struct mmc_slot { ++ int cd_irq; + void *handler_priv; + }; + +@@ -297,7 +308,7 @@ struct mmc_host { + + struct delayed_work detect; + int detect_change; /* card detect flag */ +- struct mmc_hotplug hotplug; ++ struct mmc_slot slot; + + const struct mmc_bus_ops *bus_ops; /* current bus driver */ + unsigned int bus_refs; /* reference counter */ +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0084-mmc-add-two-capability-flags-for-CD-and-WP-signal-po.patch b/patches.marzen/0084-mmc-add-two-capability-flags-for-CD-and-WP-signal-po.patch new file mode 100644 index 0000000000000..b0886e59d8b99 --- /dev/null +++ b/patches.marzen/0084-mmc-add-two-capability-flags-for-CD-and-WP-signal-po.patch @@ -0,0 +1,33 @@ +From ecce3df848ddf973eae9260a50fdd16cbb860f3f Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Tue, 1 May 2012 15:49:52 +0200 +Subject: mmc: add two capability flags for CD and WP signal polarity + +To handle CD and WP SD/MMC slot pins we need generic flags to specify their +polarity. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 5c08d7fae0815cd163a98e05c8d94fc0de77ff67) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + include/linux/mmc/host.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h +index 90b6a38..c1a03ee 100644 +--- a/include/linux/mmc/host.h ++++ b/include/linux/mmc/host.h +@@ -256,6 +256,8 @@ struct mmc_host { + #define MMC_CAP2_BROKEN_VOLTAGE (1 << 7) /* Use the broken voltage */ + #define MMC_CAP2_DETECT_ON_ERR (1 << 8) /* On I/O err check card removal */ + #define MMC_CAP2_HC_ERASE_SZ (1 << 9) /* High-capacity erase size */ ++#define MMC_CAP2_CD_ACTIVE_HIGH (1 << 10) /* Card-detect signal active high */ ++#define MMC_CAP2_RO_ACTIVE_HIGH (1 << 11) /* Write-protect signal active high */ + + mmc_pm_flag_t pm_caps; /* supported pm features */ + unsigned int power_notify_type; +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0085-mmc-add-CD-GPIO-polling-support-to-slot-functions.patch b/patches.marzen/0085-mmc-add-CD-GPIO-polling-support-to-slot-functions.patch new file mode 100644 index 0000000000000..4005a0deed78c --- /dev/null +++ b/patches.marzen/0085-mmc-add-CD-GPIO-polling-support-to-slot-functions.patch @@ -0,0 +1,141 @@ +From 2d3824e27d90f5cd81a034798596e8d6963c2b1f Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Tue, 1 May 2012 16:27:25 +0200 +Subject: mmc: add CD GPIO polling support to slot functions + +A simple extension of mmc slot functions add support for CD GPIO polling +for cases where the GPIO cannot produce interrupts, or where this is not +desired for some reason. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit befe4048d8d20483a62636e20f3dbffebf85a1c1) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/core/slot-gpio.c | 56 +++++++++++++++++++++++++++++++++---------- + include/linux/mmc/slot-gpio.h | 2 ++ + 2 files changed, 45 insertions(+), 13 deletions(-) + +diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c +index 468e5a0..92cba02 100644 +--- a/drivers/mmc/core/slot-gpio.c ++++ b/drivers/mmc/core/slot-gpio.c +@@ -18,7 +18,7 @@ + #include <linux/slab.h> + + struct mmc_gpio { +- unsigned int cd_gpio; ++ int cd_gpio; + char cd_label[0]; + }; + +@@ -29,6 +29,18 @@ static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) + return IRQ_HANDLED; + } + ++int mmc_gpio_get_cd(struct mmc_host *host) ++{ ++ struct mmc_gpio *ctx = host->slot.handler_priv; ++ ++ if (!ctx || !gpio_is_valid(ctx->cd_gpio)) ++ return -ENOSYS; ++ ++ return !gpio_get_value_cansleep(ctx->cd_gpio) ^ ++ !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH); ++} ++EXPORT_SYMBOL(mmc_gpio_get_cd); ++ + int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) + { + size_t len = strlen(dev_name(host->parent)) + 4; +@@ -36,9 +48,6 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) + int irq = gpio_to_irq(gpio); + int ret; + +- if (irq < 0) +- return irq; +- + ctx = kmalloc(sizeof(*ctx) + len, GFP_KERNEL); + if (!ctx) + return -ENOMEM; +@@ -49,20 +58,32 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) + if (ret < 0) + goto egpioreq; + +- ret = request_threaded_irq(irq, NULL, mmc_gpio_cd_irqt, ++ /* ++ * Even if gpio_to_irq() returns a valid IRQ number, the platform might ++ * still prefer to poll, e.g., because that IRQ number is already used ++ * by another unit and cannot be shared. ++ */ ++ if (irq >= 0 && host->caps & MMC_CAP_NEEDS_POLL) ++ irq = -EINVAL; ++ ++ if (irq >= 0) { ++ ret = request_threaded_irq(irq, NULL, mmc_gpio_cd_irqt, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + ctx->cd_label, host); +- if (ret < 0) +- goto eirqreq; ++ if (ret < 0) ++ irq = ret; ++ } + +- ctx->cd_gpio = gpio; + host->slot.cd_irq = irq; ++ ++ if (irq < 0) ++ host->caps |= MMC_CAP_NEEDS_POLL; ++ ++ ctx->cd_gpio = gpio; + host->slot.handler_priv = ctx; + + return 0; + +-eirqreq: +- gpio_free(gpio); + egpioreq: + kfree(ctx); + return ret; +@@ -72,12 +93,21 @@ EXPORT_SYMBOL(mmc_gpio_request_cd); + void mmc_gpio_free_cd(struct mmc_host *host) + { + struct mmc_gpio *ctx = host->slot.handler_priv; ++ int gpio; + +- if (!ctx) ++ if (!ctx || !gpio_is_valid(ctx->cd_gpio)) + return; + +- free_irq(host->slot.cd_irq, host); +- gpio_free(ctx->cd_gpio); ++ if (host->slot.cd_irq >= 0) { ++ free_irq(host->slot.cd_irq, host); ++ host->slot.cd_irq = -EINVAL; ++ } ++ ++ gpio = ctx->cd_gpio; ++ ctx->cd_gpio = -EINVAL; ++ ++ gpio_free(gpio); ++ host->slot.handler_priv = NULL; + kfree(ctx); + } + EXPORT_SYMBOL(mmc_gpio_free_cd); +diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h +index edfaa32..1a977d7 100644 +--- a/include/linux/mmc/slot-gpio.h ++++ b/include/linux/mmc/slot-gpio.h +@@ -12,6 +12,8 @@ + #define MMC_SLOT_GPIO_H + + struct mmc_host; ++ ++int mmc_gpio_get_cd(struct mmc_host *host); + int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio); + void mmc_gpio_free_cd(struct mmc_host *host); + +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0086-mmc-core-convert-slot-functions-to-managed-allocatio.patch b/patches.marzen/0086-mmc-core-convert-slot-functions-to-managed-allocatio.patch new file mode 100644 index 0000000000000..f55688e0b7e7d --- /dev/null +++ b/patches.marzen/0086-mmc-core-convert-slot-functions-to-managed-allocatio.patch @@ -0,0 +1,161 @@ +From 1acb00ed4e37416f9e71be4588be8fab3e03d1ee Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Tue, 1 May 2012 16:51:38 +0200 +Subject: mmc: core: convert slot functions to managed allocation + +This prepares for the addition of further slot functions. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit a7d1a1ebd8f5858a812ac3d5fbbc178b4959a63b) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/core/host.c | 2 ++ + drivers/mmc/core/slot-gpio.c | 51 +++++++++++++++++++++++++++++++++----------- + include/linux/mmc/host.h | 3 +++ + 3 files changed, 43 insertions(+), 13 deletions(-) + +diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c +index b8c5290..74cf29a 100644 +--- a/drivers/mmc/core/host.c ++++ b/drivers/mmc/core/host.c +@@ -32,6 +32,7 @@ + static void mmc_host_classdev_release(struct device *dev) + { + struct mmc_host *host = cls_dev_to_mmc_host(dev); ++ mutex_destroy(&host->slot.lock); + kfree(host); + } + +@@ -327,6 +328,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) + + mmc_host_clk_init(host); + ++ mutex_init(&host->slot.lock); + host->slot.cd_irq = -EINVAL; + + spin_lock_init(&host->lock); +diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c +index 92cba02..41689da 100644 +--- a/drivers/mmc/core/slot-gpio.c ++++ b/drivers/mmc/core/slot-gpio.c +@@ -29,6 +29,34 @@ static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) + return IRQ_HANDLED; + } + ++static int mmc_gpio_alloc(struct mmc_host *host) ++{ ++ size_t len = strlen(dev_name(host->parent)) + 4; ++ struct mmc_gpio *ctx; ++ ++ mutex_lock(&host->slot.lock); ++ ++ ctx = host->slot.handler_priv; ++ if (!ctx) { ++ /* ++ * devm_kzalloc() can be called after device_initialize(), even ++ * before device_add(), i.e., between mmc_alloc_host() and ++ * mmc_add_host() ++ */ ++ ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + len, ++ GFP_KERNEL); ++ if (ctx) { ++ snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent)); ++ ctx->cd_gpio = -EINVAL; ++ host->slot.handler_priv = ctx; ++ } ++ } ++ ++ mutex_unlock(&host->slot.lock); ++ ++ return ctx ? 0 : -ENOMEM; ++} ++ + int mmc_gpio_get_cd(struct mmc_host *host) + { + struct mmc_gpio *ctx = host->slot.handler_priv; +@@ -43,20 +71,24 @@ EXPORT_SYMBOL(mmc_gpio_get_cd); + + int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) + { +- size_t len = strlen(dev_name(host->parent)) + 4; + struct mmc_gpio *ctx; + int irq = gpio_to_irq(gpio); + int ret; + +- ctx = kmalloc(sizeof(*ctx) + len, GFP_KERNEL); +- if (!ctx) +- return -ENOMEM; ++ ret = mmc_gpio_alloc(host); ++ if (ret < 0) ++ return ret; + +- snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent)); ++ ctx = host->slot.handler_priv; + + ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->cd_label); + if (ret < 0) +- goto egpioreq; ++ /* ++ * don't bother freeing memory. It might still get used by other ++ * slot functions, in any case it will be freed, when the device ++ * is destroyed. ++ */ ++ return ret; + + /* + * Even if gpio_to_irq() returns a valid IRQ number, the platform might +@@ -80,13 +112,8 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) + host->caps |= MMC_CAP_NEEDS_POLL; + + ctx->cd_gpio = gpio; +- host->slot.handler_priv = ctx; + + return 0; +- +-egpioreq: +- kfree(ctx); +- return ret; + } + EXPORT_SYMBOL(mmc_gpio_request_cd); + +@@ -107,7 +134,5 @@ void mmc_gpio_free_cd(struct mmc_host *host) + ctx->cd_gpio = -EINVAL; + + gpio_free(gpio); +- host->slot.handler_priv = NULL; +- kfree(ctx); + } + EXPORT_SYMBOL(mmc_gpio_free_cd); +diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h +index c1a03ee..65c64ee 100644 +--- a/include/linux/mmc/host.h ++++ b/include/linux/mmc/host.h +@@ -11,6 +11,7 @@ + #define LINUX_MMC_HOST_H + + #include <linux/leds.h> ++#include <linux/mutex.h> + #include <linux/sched.h> + #include <linux/device.h> + #include <linux/fault-inject.h> +@@ -154,6 +155,7 @@ struct mmc_async_req { + * struct mmc_slot - MMC slot functions + * + * @cd_irq: MMC/SD-card slot hotplug detection IRQ or -EINVAL ++ * @lock: protect the @handler_priv pointer + * @handler_priv: MMC/SD-card slot context + * + * Some MMC/SD host controllers implement slot-functions like card and +@@ -163,6 +165,7 @@ struct mmc_async_req { + */ + struct mmc_slot { + int cd_irq; ++ struct mutex lock; + void *handler_priv; + }; + +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0087-mmc-core-add-WP-pin-handler-to-slot-functions.patch b/patches.marzen/0087-mmc-core-add-WP-pin-handler-to-slot-functions.patch new file mode 100644 index 0000000000000..dc21d563ab2e9 --- /dev/null +++ b/patches.marzen/0087-mmc-core-add-WP-pin-handler-to-slot-functions.patch @@ -0,0 +1,132 @@ +From e26593f54711c1135d3d1fd0994224e9dba0dee2 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Tue, 1 May 2012 16:59:38 +0200 +Subject: mmc: core: add WP pin handler to slot functions + +Card Write-Protect pin is often implemented, using a GPIO, which makes +it simple to provide a generic handler for it. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 5aa7dad305594ea30d21e23b3036565042adf50c) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/core/slot-gpio.c | 52 ++++++++++++++++++++++++++++++++++++++++++- + include/linux/mmc/slot-gpio.h | 4 ++++ + 2 files changed, 55 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c +index 41689da..0582429 100644 +--- a/drivers/mmc/core/slot-gpio.c ++++ b/drivers/mmc/core/slot-gpio.c +@@ -18,7 +18,9 @@ + #include <linux/slab.h> + + struct mmc_gpio { ++ int ro_gpio; + int cd_gpio; ++ char *ro_label; + char cd_label[0]; + }; + +@@ -43,11 +45,14 @@ static int mmc_gpio_alloc(struct mmc_host *host) + * before device_add(), i.e., between mmc_alloc_host() and + * mmc_add_host() + */ +- ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + len, ++ ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + 2 * len, + GFP_KERNEL); + if (ctx) { ++ ctx->ro_label = ctx->cd_label + len; + snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent)); ++ snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent)); + ctx->cd_gpio = -EINVAL; ++ ctx->ro_gpio = -EINVAL; + host->slot.handler_priv = ctx; + } + } +@@ -57,6 +62,18 @@ static int mmc_gpio_alloc(struct mmc_host *host) + return ctx ? 0 : -ENOMEM; + } + ++int mmc_gpio_get_ro(struct mmc_host *host) ++{ ++ struct mmc_gpio *ctx = host->slot.handler_priv; ++ ++ if (!ctx || !gpio_is_valid(ctx->ro_gpio)) ++ return -ENOSYS; ++ ++ return !gpio_get_value_cansleep(ctx->ro_gpio) ^ ++ !!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH); ++} ++EXPORT_SYMBOL(mmc_gpio_get_ro); ++ + int mmc_gpio_get_cd(struct mmc_host *host) + { + struct mmc_gpio *ctx = host->slot.handler_priv; +@@ -69,6 +86,24 @@ int mmc_gpio_get_cd(struct mmc_host *host) + } + EXPORT_SYMBOL(mmc_gpio_get_cd); + ++int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio) ++{ ++ struct mmc_gpio *ctx; ++ int ret; ++ ++ if (!gpio_is_valid(gpio)) ++ return -EINVAL; ++ ++ ret = mmc_gpio_alloc(host); ++ if (ret < 0) ++ return ret; ++ ++ ctx = host->slot.handler_priv; ++ ++ return gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label); ++} ++EXPORT_SYMBOL(mmc_gpio_request_ro); ++ + int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) + { + struct mmc_gpio *ctx; +@@ -117,6 +152,21 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) + } + EXPORT_SYMBOL(mmc_gpio_request_cd); + ++void mmc_gpio_free_ro(struct mmc_host *host) ++{ ++ struct mmc_gpio *ctx = host->slot.handler_priv; ++ int gpio; ++ ++ if (!ctx || !gpio_is_valid(ctx->ro_gpio)) ++ return; ++ ++ gpio = ctx->ro_gpio; ++ ctx->ro_gpio = -EINVAL; ++ ++ gpio_free(gpio); ++} ++EXPORT_SYMBOL(mmc_gpio_free_ro); ++ + void mmc_gpio_free_cd(struct mmc_host *host) + { + struct mmc_gpio *ctx = host->slot.handler_priv; +diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h +index 1a977d7..7d88d27 100644 +--- a/include/linux/mmc/slot-gpio.h ++++ b/include/linux/mmc/slot-gpio.h +@@ -13,6 +13,10 @@ + + struct mmc_host; + ++int mmc_gpio_get_ro(struct mmc_host *host); ++int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio); ++void mmc_gpio_free_ro(struct mmc_host *host); ++ + int mmc_gpio_get_cd(struct mmc_host *host); + int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio); + void mmc_gpio_free_cd(struct mmc_host *host); +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0088-mmc-tmio-use-generic-GPIO-CD-and-WP-handlers.patch b/patches.marzen/0088-mmc-tmio-use-generic-GPIO-CD-and-WP-handlers.patch new file mode 100644 index 0000000000000..6520920aace7a --- /dev/null +++ b/patches.marzen/0088-mmc-tmio-use-generic-GPIO-CD-and-WP-handlers.patch @@ -0,0 +1,45 @@ +From faee1eb43fa5fa4ab009588d46a5e5b4da3be529 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Tue, 1 May 2012 17:11:56 +0200 +Subject: mmc: tmio: use generic GPIO CD and WP handlers + +The tmio-mmc driver is already using the generic GPIO CD handler in IRQ +mode. This patch adds support for CD polling mode and also checks for +availability of a WP GPIO. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 3071cafb7f6f9cbb52b1b7eb308c8b45cae0dcf8) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/tmio_mmc_pio.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index f8df021..0d8a9bb 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -875,6 +875,9 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc) + { + struct tmio_mmc_host *host = mmc_priv(mmc); + struct tmio_mmc_data *pdata = host->pdata; ++ int ret = mmc_gpio_get_ro(mmc); ++ if (ret >= 0) ++ return ret; + + return !((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) || + (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)); +@@ -884,6 +887,9 @@ static int tmio_mmc_get_cd(struct mmc_host *mmc) + { + struct tmio_mmc_host *host = mmc_priv(mmc); + struct tmio_mmc_data *pdata = host->pdata; ++ int ret = mmc_gpio_get_cd(mmc); ++ if (ret >= 0) ++ return ret; + + if (!pdata->get_cd) + return -ENOSYS; +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0089-mmc-sh_mobile_sdhi-prepare-for-conversion-to-the-shd.patch b/patches.marzen/0089-mmc-sh_mobile_sdhi-prepare-for-conversion-to-the-shd.patch new file mode 100644 index 0000000000000..3486d84ee7bd3 --- /dev/null +++ b/patches.marzen/0089-mmc-sh_mobile_sdhi-prepare-for-conversion-to-the-shd.patch @@ -0,0 +1,37 @@ +From e4f6cf57b801d98e400bc52f4c3eb372b7703feb Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 9 May 2012 17:09:16 +0200 +Subject: mmc: sh_mobile_sdhi: prepare for conversion to the shdma base library + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Cc: Chris Ball <cjb@laptop.org> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit c471270d7a4161a8f1794202ad8338c0ec55759e) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mobile_sdhi.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index a842939..0bdc146 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -169,10 +169,10 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) + mmc_data->get_cd = sh_mobile_sdhi_get_cd; + + if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) { +- priv->param_tx.slave_id = p->dma_slave_tx; +- priv->param_rx.slave_id = p->dma_slave_rx; +- priv->dma_priv.chan_priv_tx = &priv->param_tx; +- priv->dma_priv.chan_priv_rx = &priv->param_rx; ++ priv->param_tx.shdma_slave.slave_id = p->dma_slave_tx; ++ priv->param_rx.shdma_slave.slave_id = p->dma_slave_rx; ++ priv->dma_priv.chan_priv_tx = &priv->param_tx.shdma_slave; ++ priv->dma_priv.chan_priv_rx = &priv->param_rx.shdma_slave; + priv->dma_priv.alignment_shift = 1; /* 2-byte alignment */ + mmc_data->dma = &priv->dma_priv; + } +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0090-mmc-sh_mmcif-remove-unneeded-struct-sh_mmcif_dma-pre.patch b/patches.marzen/0090-mmc-sh_mmcif-remove-unneeded-struct-sh_mmcif_dma-pre.patch new file mode 100644 index 0000000000000..bfc5b79456afc --- /dev/null +++ b/patches.marzen/0090-mmc-sh_mmcif-remove-unneeded-struct-sh_mmcif_dma-pre.patch @@ -0,0 +1,94 @@ +From 52ffe4e5679653a9bb539a438d6521768fd70e25 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Wed, 9 May 2012 17:09:15 +0200 +Subject: mmc: sh_mmcif: remove unneeded struct sh_mmcif_dma, prepare to shdma + conversion + +Now that all users have been updated to use the embedded in struct +sh_mmcif_plat_data DMA slave IDs, struct sh_mmcif_dma is no longer needed +and can be removed. This also makes preparation to the shdma base library +conversion easier. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Cc: Chris Ball <cjb@laptop.org> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit 916001fe33b7b4dc797f7b29ec8bc346c4369fa6) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 24 ++++++++++-------------- + include/linux/mmc/sh_mmcif.h | 8 +------- + 2 files changed, 11 insertions(+), 21 deletions(-) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index 724b35e..9e3b9b1 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -385,31 +385,27 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host, + host->dma_active = false; + + /* We can only either use DMA for both Tx and Rx or not use it at all */ +- if (pdata->dma) { +- dev_warn(&host->pd->dev, +- "Update your platform to use embedded DMA slave IDs\n"); +- tx = &pdata->dma->chan_priv_tx; +- rx = &pdata->dma->chan_priv_rx; +- } else { +- tx = &host->dma_slave_tx; +- tx->slave_id = pdata->slave_id_tx; +- rx = &host->dma_slave_rx; +- rx->slave_id = pdata->slave_id_rx; +- } +- if (tx->slave_id > 0 && rx->slave_id > 0) { ++ tx = &host->dma_slave_tx; ++ tx->shdma_slave.slave_id = pdata->slave_id_tx; ++ rx = &host->dma_slave_rx; ++ rx->shdma_slave.slave_id = pdata->slave_id_rx; ++ ++ if (tx->shdma_slave.slave_id > 0 && rx->shdma_slave.slave_id > 0) { + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + +- host->chan_tx = dma_request_channel(mask, sh_mmcif_filter, tx); ++ host->chan_tx = dma_request_channel(mask, sh_mmcif_filter, ++ &tx->shdma_slave); + dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__, + host->chan_tx); + + if (!host->chan_tx) + return; + +- host->chan_rx = dma_request_channel(mask, sh_mmcif_filter, rx); ++ host->chan_rx = dma_request_channel(mask, sh_mmcif_filter, ++ &rx->shdma_slave); + dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__, + host->chan_rx); + +diff --git a/include/linux/mmc/sh_mmcif.h b/include/linux/mmc/sh_mmcif.h +index 05f0e3d..c37956c 100644 +--- a/include/linux/mmc/sh_mmcif.h ++++ b/include/linux/mmc/sh_mmcif.h +@@ -32,17 +32,11 @@ + * 1111 : Peripheral clock (sup_pclk set '1') + */ + +-struct sh_mmcif_dma { +- struct sh_dmae_slave chan_priv_tx; +- struct sh_dmae_slave chan_priv_rx; +-}; +- + struct sh_mmcif_plat_data { + void (*set_pwr)(struct platform_device *pdev, int state); + void (*down_pwr)(struct platform_device *pdev); + int (*get_cd)(struct platform_device *pdef); +- struct sh_mmcif_dma *dma; /* Deprecated. Instead */ +- unsigned int slave_id_tx; /* use embedded slave_id_[tr]x */ ++ unsigned int slave_id_tx; /* embedded slave_id_[tr]x */ + unsigned int slave_id_rx; + u8 sup_pclk; /* 1 :SH7757, 0: SH7724/SH7372 */ + unsigned long caps; +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0091-mmc-sh_mmcif-switch-to-the-new-DMA-channel-allocatio.patch b/patches.marzen/0091-mmc-sh_mmcif-switch-to-the-new-DMA-channel-allocatio.patch new file mode 100644 index 0000000000000..02bbc7d068df1 --- /dev/null +++ b/patches.marzen/0091-mmc-sh_mmcif-switch-to-the-new-DMA-channel-allocatio.patch @@ -0,0 +1,138 @@ +From e528d448bb2c6e6b4c1ea80b809ffdc734806290 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 5 Jul 2012 12:29:43 +0200 +Subject: mmc: sh_mmcif: switch to the new DMA channel allocation and + configuration + +Using the "private" field from struct dma_chan is deprecated. The sh +dmaengine driver now also supports the preferred DMA channel allocation +and configuration method, using a standard filter function and a channel +configuration operation. This patch updates sh_mmcif to use this new +method. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Cc: Chris Ball <cjb@laptop.org> +Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com> +(cherry picked from commit 0e79f9ae1610c15f5e5959c39d7c39071619de97) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 82 ++++++++++++++++++++++++++------------------- + 1 file changed, 47 insertions(+), 35 deletions(-) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index 9e3b9b1..0f07d28 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -211,8 +211,6 @@ struct sh_mmcif_host { + struct mmc_host *mmc; + struct mmc_request *mrq; + struct platform_device *pd; +- struct sh_dmae_slave dma_slave_tx; +- struct sh_dmae_slave dma_slave_rx; + struct clk *hclk; + unsigned int clk; + int bus_width; +@@ -371,52 +369,66 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) + desc, cookie); + } + +-static bool sh_mmcif_filter(struct dma_chan *chan, void *arg) +-{ +- dev_dbg(chan->device->dev, "%s: slave data %p\n", __func__, arg); +- chan->private = arg; +- return true; +-} +- + static void sh_mmcif_request_dma(struct sh_mmcif_host *host, + struct sh_mmcif_plat_data *pdata) + { +- struct sh_dmae_slave *tx, *rx; ++ struct resource *res = platform_get_resource(host->pd, IORESOURCE_MEM, 0); ++ struct dma_slave_config cfg; ++ dma_cap_mask_t mask; ++ int ret; ++ + host->dma_active = false; + ++ if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0) ++ return; ++ + /* We can only either use DMA for both Tx and Rx or not use it at all */ +- tx = &host->dma_slave_tx; +- tx->shdma_slave.slave_id = pdata->slave_id_tx; +- rx = &host->dma_slave_rx; +- rx->shdma_slave.slave_id = pdata->slave_id_rx; ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ ++ host->chan_tx = dma_request_channel(mask, shdma_chan_filter, ++ (void *)pdata->slave_id_tx); ++ dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__, ++ host->chan_tx); + +- if (tx->shdma_slave.slave_id > 0 && rx->shdma_slave.slave_id > 0) { +- dma_cap_mask_t mask; ++ if (!host->chan_tx) ++ return; + +- dma_cap_zero(mask); +- dma_cap_set(DMA_SLAVE, mask); ++ cfg.slave_id = pdata->slave_id_tx; ++ cfg.direction = DMA_MEM_TO_DEV; ++ cfg.dst_addr = res->start + MMCIF_CE_DATA; ++ cfg.src_addr = 0; ++ ret = dmaengine_slave_config(host->chan_tx, &cfg); ++ if (ret < 0) ++ goto ecfgtx; + +- host->chan_tx = dma_request_channel(mask, sh_mmcif_filter, +- &tx->shdma_slave); +- dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__, +- host->chan_tx); ++ host->chan_rx = dma_request_channel(mask, shdma_chan_filter, ++ (void *)pdata->slave_id_rx); ++ dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__, ++ host->chan_rx); + +- if (!host->chan_tx) +- return; ++ if (!host->chan_rx) ++ goto erqrx; + +- host->chan_rx = dma_request_channel(mask, sh_mmcif_filter, +- &rx->shdma_slave); +- dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__, +- host->chan_rx); ++ cfg.slave_id = pdata->slave_id_rx; ++ cfg.direction = DMA_DEV_TO_MEM; ++ cfg.dst_addr = 0; ++ cfg.src_addr = res->start + MMCIF_CE_DATA; ++ ret = dmaengine_slave_config(host->chan_rx, &cfg); ++ if (ret < 0) ++ goto ecfgrx; + +- if (!host->chan_rx) { +- dma_release_channel(host->chan_tx); +- host->chan_tx = NULL; +- return; +- } ++ init_completion(&host->dma_complete); + +- init_completion(&host->dma_complete); +- } ++ return; ++ ++ecfgrx: ++ dma_release_channel(host->chan_rx); ++ host->chan_rx = NULL; ++erqrx: ++ecfgtx: ++ dma_release_channel(host->chan_tx); ++ host->chan_tx = NULL; + } + + static void sh_mmcif_release_dma(struct sh_mmcif_host *host) +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0092-mmc-sh_mmcif-Support-MMC_SLEEP_AWAKE-command.patch b/patches.marzen/0092-mmc-sh_mmcif-Support-MMC_SLEEP_AWAKE-command.patch new file mode 100644 index 0000000000000..ca047a2f6bca4 --- /dev/null +++ b/patches.marzen/0092-mmc-sh_mmcif-Support-MMC_SLEEP_AWAKE-command.patch @@ -0,0 +1,53 @@ +From a582cd28240bd5aca4462da1dacd8dd8e9ee0dbc Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Tue, 12 Jun 2012 22:56:09 +0200 +Subject: mmc: sh_mmcif: Support MMC_SLEEP_AWAKE command + +The MMC_SLEEP_AWAKE and SD_IO_SEND_OP_COND commands share the same +opcode. SD_IO_SEND_OP_COND isn't supported by the SH MMCIF, but +MMC_SLEEP_AWAKE is. Discriminate between the two commands using the +command flags, and reject SD_IO_SEND_OP_COND only. + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 7541ca98477862e2e9988c6c2ceadbdccefa9d77) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 14 ++++---------- + 1 file changed, 4 insertions(+), 10 deletions(-) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index 0f07d28..1eb23a7 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -900,21 +900,15 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) + + switch (mrq->cmd->opcode) { + /* MMCIF does not support SD/SDIO command */ +- case SD_IO_SEND_OP_COND: ++ case MMC_SLEEP_AWAKE: /* = SD_IO_SEND_OP_COND (5) */ ++ case MMC_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */ ++ if ((mrq->cmd->flags & MMC_CMD_MASK) != MMC_CMD_BCR) ++ break; + case MMC_APP_CMD: + host->state = STATE_IDLE; + mrq->cmd->error = -ETIMEDOUT; + mmc_request_done(mmc, mrq); + return; +- case MMC_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */ +- if (!mrq->data) { +- /* send_if_cond cmd (not support) */ +- host->state = STATE_IDLE; +- mrq->cmd->error = -ETIMEDOUT; +- mmc_request_done(mmc, mrq); +- return; +- } +- break; + default: + break; + } +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0093-mmc-sh_mmcif-simplify-and-use-meaningful-label-names.patch b/patches.marzen/0093-mmc-sh_mmcif-simplify-and-use-meaningful-label-names.patch new file mode 100644 index 0000000000000..e752b059a6ac6 --- /dev/null +++ b/patches.marzen/0093-mmc-sh_mmcif-simplify-and-use-meaningful-label-names.patch @@ -0,0 +1,126 @@ +From 31a4301b36511da303ad36da908f462f057f0e73 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 19 Apr 2012 16:15:52 +0200 +Subject: mmc: sh_mmcif: simplify and use meaningful label names in + error-handling + +A check for NULL platform data can be conveniently made in the very +beginning of probing. Replace numbered error-handling labels in .probe() +with meaningful names to make any future reorganisation simpler. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Reviewed-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit e1aae2eb3f7c446a2680a3a0ccd05aa50521b4e2) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 41 ++++++++++++++++++++--------------------- + 1 file changed, 20 insertions(+), 21 deletions(-) + +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -1253,11 +1253,16 @@ static int __devinit sh_mmcif_probe(stru + int ret = 0, irq[2]; + struct mmc_host *mmc; + struct sh_mmcif_host *host; +- struct sh_mmcif_plat_data *pd; ++ struct sh_mmcif_plat_data *pd = pdev->dev.platform_data; + struct resource *res; + void __iomem *reg; + char clk_name[8]; + ++ if (!pd) { ++ dev_err(&pdev->dev, "sh_mmcif plat data error.\n"); ++ return -ENXIO; ++ } ++ + irq[0] = platform_get_irq(pdev, 0); + irq[1] = platform_get_irq(pdev, 1); + if (irq[0] < 0 || irq[1] < 0) { +@@ -1274,16 +1279,11 @@ static int __devinit sh_mmcif_probe(stru + dev_err(&pdev->dev, "ioremap error.\n"); + return -ENOMEM; + } +- pd = pdev->dev.platform_data; +- if (!pd) { +- dev_err(&pdev->dev, "sh_mmcif plat data error.\n"); +- ret = -ENXIO; +- goto clean_up; +- } ++ + mmc = mmc_alloc_host(sizeof(struct sh_mmcif_host), &pdev->dev); + if (!mmc) { + ret = -ENOMEM; +- goto clean_up; ++ goto ealloch; + } + host = mmc_priv(mmc); + host->mmc = mmc; +@@ -1295,7 +1295,7 @@ static int __devinit sh_mmcif_probe(stru + if (IS_ERR(host->hclk)) { + dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); + ret = PTR_ERR(host->hclk); +- goto clean_up1; ++ goto eclkget; + } + clk_enable(host->hclk); + host->clk = clk_get_rate(host->hclk); +@@ -1325,7 +1325,7 @@ static int __devinit sh_mmcif_probe(stru + + ret = pm_runtime_resume(&pdev->dev); + if (ret < 0) +- goto clean_up2; ++ goto eresume; + + INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work); + +@@ -1334,17 +1334,17 @@ static int __devinit sh_mmcif_probe(stru + ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host); + if (ret) { + dev_err(&pdev->dev, "request_irq error (sh_mmc:error)\n"); +- goto clean_up3; ++ goto ereqirq0; + } + ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host); + if (ret) { + dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n"); +- goto clean_up4; ++ goto ereqirq1; + } + + ret = mmc_add_host(mmc); + if (ret < 0) +- goto clean_up5; ++ goto emmcaddh; + + dev_pm_qos_expose_latency_limit(&pdev->dev, 100); + +@@ -1353,20 +1353,19 @@ static int __devinit sh_mmcif_probe(stru + sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff); + return ret; + +-clean_up5: ++emmcaddh: + free_irq(irq[1], host); +-clean_up4: ++ereqirq1: + free_irq(irq[0], host); +-clean_up3: ++ereqirq0: + pm_runtime_suspend(&pdev->dev); +-clean_up2: ++eresume: + pm_runtime_disable(&pdev->dev); + clk_disable(host->hclk); +-clean_up1: ++eclkget: + mmc_free_host(mmc); +-clean_up: +- if (reg) +- iounmap(reg); ++ealloch: ++ iounmap(reg); + return ret; + } + diff --git a/patches.marzen/0094-mmc-sh_mmcif-fix-clock-management.patch b/patches.marzen/0094-mmc-sh_mmcif-fix-clock-management.patch new file mode 100644 index 0000000000000..a0a25c610d71f --- /dev/null +++ b/patches.marzen/0094-mmc-sh_mmcif-fix-clock-management.patch @@ -0,0 +1,160 @@ +From f504bc8e96b3633271ee5e623c35e026a6db62e7 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 19 Apr 2012 18:02:05 +0200 +Subject: mmc: sh_mmcif: fix clock management + +Regardless of whether the MMC bus clock is the same as the PM clock on +this specific interface, it has to be managed separately. Its proper +management should also include enabling and disabling of the clock, +whenever the interface is becoming active or going idle respectively. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Reviewed-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit b289174ff70a591545a054d52ae081a75a73f085) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 46 ++++++++++++++++++++++---------------------- + 1 file changed, 23 insertions(+), 23 deletions(-) + +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -950,6 +950,7 @@ static void sh_mmcif_set_ios(struct mmc_ + } + if (host->power) { + pm_runtime_put(&host->pd->dev); ++ clk_disable(host->hclk); + host->power = false; + if (p->down_pwr && ios->power_mode == MMC_POWER_OFF) + p->down_pwr(host->pd); +@@ -962,6 +963,7 @@ static void sh_mmcif_set_ios(struct mmc_ + if (!host->power) { + if (p->set_pwr) + p->set_pwr(host->pd, ios->power_mode); ++ clk_enable(host->hclk); + pm_runtime_get_sync(&host->pd->dev); + host->power = true; + sh_mmcif_sync_reset(host); +@@ -1290,22 +1292,11 @@ static int __devinit sh_mmcif_probe(stru + host->addr = reg; + host->timeout = 1000; + +- snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id); +- host->hclk = clk_get(&pdev->dev, clk_name); +- if (IS_ERR(host->hclk)) { +- dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); +- ret = PTR_ERR(host->hclk); +- goto eclkget; +- } +- clk_enable(host->hclk); +- host->clk = clk_get_rate(host->hclk); + host->pd = pdev; + + spin_lock_init(&host->lock); + + mmc->ops = &sh_mmcif_ops; +- mmc->f_max = host->clk / 2; +- mmc->f_min = host->clk / 512; + if (pd->ocr) + mmc->ocr_avail = pd->ocr; + mmc->caps = MMC_CAP_MMC_HIGHSPEED; +@@ -1317,18 +1308,30 @@ static int __devinit sh_mmcif_probe(stru + mmc->max_blk_count = mmc->max_req_size / mmc->max_blk_size; + mmc->max_seg_size = mmc->max_req_size; + +- sh_mmcif_sync_reset(host); + platform_set_drvdata(pdev, host); + + pm_runtime_enable(&pdev->dev); + host->power = false; + ++ snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id); ++ host->hclk = clk_get(&pdev->dev, clk_name); ++ if (IS_ERR(host->hclk)) { ++ ret = PTR_ERR(host->hclk); ++ dev_err(&pdev->dev, "cannot get clock \"%s\": %d\n", clk_name, ret); ++ goto eclkget; ++ } ++ clk_enable(host->hclk); ++ host->clk = clk_get_rate(host->hclk); ++ mmc->f_max = host->clk / 2; ++ mmc->f_min = host->clk / 512; ++ + ret = pm_runtime_resume(&pdev->dev); + if (ret < 0) + goto eresume; + + INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work); + ++ sh_mmcif_sync_reset(host); + sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); + + ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host); +@@ -1342,6 +1345,7 @@ static int __devinit sh_mmcif_probe(stru + goto ereqirq1; + } + ++ clk_disable(host->hclk); + ret = mmc_add_host(mmc); + if (ret < 0) + goto emmcaddh; +@@ -1360,9 +1364,10 @@ ereqirq1: + ereqirq0: + pm_runtime_suspend(&pdev->dev); + eresume: +- pm_runtime_disable(&pdev->dev); + clk_disable(host->hclk); ++ clk_put(host->hclk); + eclkget: ++ pm_runtime_disable(&pdev->dev); + mmc_free_host(mmc); + ealloch: + iounmap(reg); +@@ -1375,6 +1380,7 @@ static int __devexit sh_mmcif_remove(str + int irq[2]; + + host->dying = true; ++ clk_enable(host->hclk); + pm_runtime_get_sync(&pdev->dev); + + dev_pm_qos_hide_latency_limit(&pdev->dev); +@@ -1400,9 +1406,9 @@ static int __devexit sh_mmcif_remove(str + + platform_set_drvdata(pdev, NULL); + +- clk_disable(host->hclk); + mmc_free_host(host->mmc); + pm_runtime_put_sync(&pdev->dev); ++ clk_disable(host->hclk); + pm_runtime_disable(&pdev->dev); + + return 0; +@@ -1411,24 +1417,18 @@ static int __devexit sh_mmcif_remove(str + #ifdef CONFIG_PM + static int sh_mmcif_suspend(struct device *dev) + { +- struct platform_device *pdev = to_platform_device(dev); +- struct sh_mmcif_host *host = platform_get_drvdata(pdev); ++ struct sh_mmcif_host *host = dev_get_drvdata(dev); + int ret = mmc_suspend_host(host->mmc); + +- if (!ret) { ++ if (!ret) + sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); +- clk_disable(host->hclk); +- } + + return ret; + } + + static int sh_mmcif_resume(struct device *dev) + { +- struct platform_device *pdev = to_platform_device(dev); +- struct sh_mmcif_host *host = platform_get_drvdata(pdev); +- +- clk_enable(host->hclk); ++ struct sh_mmcif_host *host = dev_get_drvdata(dev); + + return mmc_resume_host(host->mmc); + } diff --git a/patches.marzen/0095-mmc-sh_mmcif-re-read-the-clock-frequency-every-time-.patch b/patches.marzen/0095-mmc-sh_mmcif-re-read-the-clock-frequency-every-time-.patch new file mode 100644 index 0000000000000..4752592f012ca --- /dev/null +++ b/patches.marzen/0095-mmc-sh_mmcif-re-read-the-clock-frequency-every-time-.patch @@ -0,0 +1,73 @@ +From 417f01ebd88111d61e507af5d9cab347ffa41861 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 19 Apr 2012 18:02:50 +0200 +Subject: mmc: sh_mmcif: re-read the clock frequency every time it is turned on + +With aggressive clock gating the clock can be disabled during interface +inactivity. During this time its frequency can be changed by another its +user. Therefore when the interface is activated again and the clock is +re-enabled, its frequency has to be re-read. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Reviewed-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit a6609267107ecc5598b79aa353036c1f57e7257e) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 23 ++++++++++++++++++----- + 1 file changed, 18 insertions(+), 5 deletions(-) + +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -918,6 +918,19 @@ static void sh_mmcif_request(struct mmc_ + sh_mmcif_start_cmd(host, mrq); + } + ++static int sh_mmcif_clk_update(struct sh_mmcif_host *host) ++{ ++ int ret = clk_enable(host->hclk); ++ ++ if (!ret) { ++ host->clk = clk_get_rate(host->hclk); ++ host->mmc->f_max = host->clk / 2; ++ host->mmc->f_min = host->clk / 512; ++ } ++ ++ return ret; ++} ++ + static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + { + struct sh_mmcif_host *host = mmc_priv(mmc); +@@ -963,7 +976,7 @@ static void sh_mmcif_set_ios(struct mmc_ + if (!host->power) { + if (p->set_pwr) + p->set_pwr(host->pd, ios->power_mode); +- clk_enable(host->hclk); ++ sh_mmcif_clk_update(host); + pm_runtime_get_sync(&host->pd->dev); + host->power = true; + sh_mmcif_sync_reset(host); +@@ -1320,10 +1333,9 @@ static int __devinit sh_mmcif_probe(stru + dev_err(&pdev->dev, "cannot get clock \"%s\": %d\n", clk_name, ret); + goto eclkget; + } +- clk_enable(host->hclk); +- host->clk = clk_get_rate(host->hclk); +- mmc->f_max = host->clk / 2; +- mmc->f_min = host->clk / 512; ++ ret = sh_mmcif_clk_update(host); ++ if (ret < 0) ++ goto eclkupdate; + + ret = pm_runtime_resume(&pdev->dev); + if (ret < 0) +@@ -1365,6 +1377,7 @@ ereqirq0: + pm_runtime_suspend(&pdev->dev); + eresume: + clk_disable(host->hclk); ++eclkupdate: + clk_put(host->hclk); + eclkget: + pm_runtime_disable(&pdev->dev); diff --git a/patches.marzen/0096-mmc-sh_mmcif-remove-redundant-.down_pwr-callback.patch b/patches.marzen/0096-mmc-sh_mmcif-remove-redundant-.down_pwr-callback.patch new file mode 100644 index 0000000000000..f30f7019bd8a8 --- /dev/null +++ b/patches.marzen/0096-mmc-sh_mmcif-remove-redundant-.down_pwr-callback.patch @@ -0,0 +1,39 @@ +From 57a9e156b943508dc6ee4ac85e43d90f0888985f Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Fri, 20 Apr 2012 09:01:05 +0200 +Subject: mmc: sh_mmcif: remove redundant .down_pwr() callback + +From the original version of sh_mmcif the .set_pwr() callback has only been +used to turn the card's power on, and the .down_pwr() callback has been +used to turn it off. .set_pwr() can be used for both these tasks, which is +also how it is implemented by the only user of this API: the SH7724 ecovec +board. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Reviewed-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit e2ee996eaad64c149cb7cfd344789c7e0c1577dc) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index 29d908a..10c5fcd 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -965,8 +965,8 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + pm_runtime_put(&host->pd->dev); + clk_disable(host->hclk); + host->power = false; +- if (p->down_pwr && ios->power_mode == MMC_POWER_OFF) +- p->down_pwr(host->pd); ++ if (p->set_pwr && ios->power_mode == MMC_POWER_OFF) ++ p->set_pwr(host->pd, 0); + } + host->state = STATE_IDLE; + return; +-- +1.8.0.197.g5a90748 + diff --git a/patches.marzen/0097-mmc-sh_mmcif-add-regulator-support.patch b/patches.marzen/0097-mmc-sh_mmcif-add-regulator-support.patch new file mode 100644 index 0000000000000..ccdff8ee4ba1e --- /dev/null +++ b/patches.marzen/0097-mmc-sh_mmcif-add-regulator-support.patch @@ -0,0 +1,108 @@ +From d573e549e130bfe6200b70a36ab44767943b52a2 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Fri, 20 Apr 2012 18:27:13 +0200 +Subject: mmc: sh_mmcif: add regulator support + +Add regulator support to the sh_mmcif driver, but also preserve the current +power-callback. + +Also note, that the card power is not switched off during clock gating +periods, hence there's no need to power it on every time the card is +re-activated. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Reviwed-by: Mark Brown <broonie@opensource.wolfsonmicro.com> +Reviewed-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit 7d17baa05da6a2e64ee15011cdf4319bd3e0ff61) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 38 +++++++++++++++++++++++++++++++------- + 1 file changed, 31 insertions(+), 7 deletions(-) + +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -931,10 +931,22 @@ static int sh_mmcif_clk_update(struct sh + return ret; + } + ++static void sh_mmcif_set_power(struct sh_mmcif_host *host, struct mmc_ios *ios) ++{ ++ struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data; ++ struct mmc_host *mmc = host->mmc; ++ ++ if (pd->set_pwr) ++ pd->set_pwr(host->pd, ios->power_mode != MMC_POWER_OFF); ++ if (!IS_ERR(mmc->supply.vmmc)) ++ /* Errors ignored... */ ++ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ++ ios->power_mode ? ios->vdd : 0); ++} ++ + static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + { + struct sh_mmcif_host *host = mmc_priv(mmc); +- struct sh_mmcif_plat_data *p = host->pd->dev.platform_data; + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); +@@ -952,6 +964,7 @@ static void sh_mmcif_set_ios(struct mmc_ + sh_mmcif_request_dma(host, host->pd->dev.platform_data); + host->card_present = true; + } ++ sh_mmcif_set_power(host, ios); + } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) { + /* clock stop */ + sh_mmcif_clock_control(host, 0); +@@ -965,8 +978,8 @@ static void sh_mmcif_set_ios(struct mmc_ + pm_runtime_put(&host->pd->dev); + clk_disable(host->hclk); + host->power = false; +- if (p->set_pwr && ios->power_mode == MMC_POWER_OFF) +- p->set_pwr(host->pd, 0); ++ if (ios->power_mode == MMC_POWER_OFF) ++ sh_mmcif_set_power(host, ios); + } + host->state = STATE_IDLE; + return; +@@ -974,8 +987,6 @@ static void sh_mmcif_set_ios(struct mmc_ + + if (ios->clock) { + if (!host->power) { +- if (p->set_pwr) +- p->set_pwr(host->pd, ios->power_mode); + sh_mmcif_clk_update(host); + pm_runtime_get_sync(&host->pd->dev); + host->power = true; +@@ -1263,6 +1274,19 @@ static void mmcif_timeout_work(struct wo + mmc_request_done(host->mmc, mrq); + } + ++static void sh_mmcif_init_ocr(struct sh_mmcif_host *host) ++{ ++ struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data; ++ struct mmc_host *mmc = host->mmc; ++ ++ mmc_regulator_get_supply(mmc); ++ ++ if (!mmc->ocr_avail) ++ mmc->ocr_avail = pd->ocr; ++ else if (pd->ocr) ++ dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n"); ++} ++ + static int __devinit sh_mmcif_probe(struct platform_device *pdev) + { + int ret = 0, irq[2]; +@@ -1310,8 +1334,8 @@ static int __devinit sh_mmcif_probe(stru + spin_lock_init(&host->lock); + + mmc->ops = &sh_mmcif_ops; +- if (pd->ocr) +- mmc->ocr_avail = pd->ocr; ++ sh_mmcif_init_ocr(host); ++ + mmc->caps = MMC_CAP_MMC_HIGHSPEED; + if (pd->caps) + mmc->caps |= pd->caps; diff --git a/patches.marzen/0098-mmc-sh-mmcif-add-OF-support-make-platform-data-optio.patch b/patches.marzen/0098-mmc-sh-mmcif-add-OF-support-make-platform-data-optio.patch new file mode 100644 index 0000000000000..6d3bd0133abf0 --- /dev/null +++ b/patches.marzen/0098-mmc-sh-mmcif-add-OF-support-make-platform-data-optio.patch @@ -0,0 +1,127 @@ +From 7feedc26deff116af14317bfba8356724b71a362 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Tue, 1 May 2012 18:18:16 +0200 +Subject: mmc: sh-mmcif: add OF support, make platform data optional + +Add primitive OF support to the sh-mmcif driver, which also makes it +necessary to be able to run without platform data. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit bf68a812f06ca40bccfa2e792055141f2c3948c7) + +Conflicts: + drivers/mmc/host/sh_mmcif.c + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 29 ++++++++++++++++++++--------- + 1 file changed, 20 insertions(+), 9 deletions(-) + +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -54,6 +54,7 @@ + #include <linux/mmc/mmc.h> + #include <linux/mmc/sdio.h> + #include <linux/mmc/sh_mmcif.h> ++#include <linux/mod_devicetable.h> + #include <linux/pagemap.h> + #include <linux/platform_device.h> + #include <linux/pm_qos.h> +@@ -379,6 +380,9 @@ static void sh_mmcif_request_dma(struct + + host->dma_active = false; + ++ if (!pdata) ++ return; ++ + if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0) + return; + +@@ -452,13 +456,14 @@ static void sh_mmcif_release_dma(struct + static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk) + { + struct sh_mmcif_plat_data *p = host->pd->dev.platform_data; ++ bool sup_pclk = p ? p->sup_pclk : false; + + sh_mmcif_bitclr(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE); + sh_mmcif_bitclr(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR); + + if (!clk) + return; +- if (p->sup_pclk && clk == host->clk) ++ if (sup_pclk && clk == host->clk) + sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK); + else + sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR & +@@ -936,7 +941,7 @@ static void sh_mmcif_set_power(struct sh + struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data; + struct mmc_host *mmc = host->mmc; + +- if (pd->set_pwr) ++ if (pd && pd->set_pwr) + pd->set_pwr(host->pd, ios->power_mode != MMC_POWER_OFF); + if (!IS_ERR(mmc->supply.vmmc)) + /* Errors ignored... */ +@@ -1004,7 +1009,7 @@ static int sh_mmcif_get_cd(struct mmc_ho + struct sh_mmcif_host *host = mmc_priv(mmc); + struct sh_mmcif_plat_data *p = host->pd->dev.platform_data; + +- if (!p->get_cd) ++ if (!p || !p->get_cd) + return -ENOSYS; + else + return p->get_cd(host->pd); +@@ -1281,6 +1286,9 @@ static void sh_mmcif_init_ocr(struct sh_ + + mmc_regulator_get_supply(mmc); + ++ if (!pd) ++ return; ++ + if (!mmc->ocr_avail) + mmc->ocr_avail = pd->ocr; + else if (pd->ocr) +@@ -1297,11 +1305,6 @@ static int __devinit sh_mmcif_probe(stru + void __iomem *reg; + char clk_name[8]; + +- if (!pd) { +- dev_err(&pdev->dev, "sh_mmcif plat data error.\n"); +- return -ENXIO; +- } +- + irq[0] = platform_get_irq(pdev, 0); + irq[1] = platform_get_irq(pdev, 1); + if (irq[0] < 0 || irq[1] < 0) { +@@ -1337,7 +1340,7 @@ static int __devinit sh_mmcif_probe(stru + sh_mmcif_init_ocr(host); + + mmc->caps = MMC_CAP_MMC_HIGHSPEED; +- if (pd->caps) ++ if (pd && pd->caps) + mmc->caps |= pd->caps; + mmc->max_segs = 32; + mmc->max_blk_size = 512; +@@ -1474,6 +1477,12 @@ static int sh_mmcif_resume(struct device + #define sh_mmcif_resume NULL + #endif /* CONFIG_PM */ + ++static const struct of_device_id mmcif_of_match[] = { ++ { .compatible = "renesas,sh-mmcif" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, mmcif_of_match); ++ + static const struct dev_pm_ops sh_mmcif_dev_pm_ops = { + .suspend = sh_mmcif_suspend, + .resume = sh_mmcif_resume, +@@ -1485,6 +1494,8 @@ static struct platform_driver sh_mmcif_d + .driver = { + .name = DRIVER_NAME, + .pm = &sh_mmcif_dev_pm_ops, ++ .owner = THIS_MODULE, ++ .of_match_table = mmcif_of_match, + }, + }; + diff --git a/patches.marzen/0099-mmc-sh_mmcif-support-generic-card-detection.patch b/patches.marzen/0099-mmc-sh_mmcif-support-generic-card-detection.patch new file mode 100644 index 0000000000000..613690cff8889 --- /dev/null +++ b/patches.marzen/0099-mmc-sh_mmcif-support-generic-card-detection.patch @@ -0,0 +1,92 @@ +From 4156a922e2e32baccd17cb76ba388cecb1790299 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Date: Thu, 14 Jun 2012 14:24:35 +0200 +Subject: mmc: sh_mmcif: support generic card-detection + +Extend the sh_mmcif driver to support GPIO card detection, provided by the +slot function module. The original .get_cd() platform callback is also +preserved for now. + +Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> +Signed-off-by: Chris Ball <cjb@laptop.org> +(cherry picked from commit e480606ad43bb72fd82a9bd99cdcf21829a6e9c0) + +Signed-off-by: Simon Horman <horms@verge.net.au> +--- + drivers/mmc/host/sh_mmcif.c | 18 ++++++++++++++++++ + include/linux/mmc/sh_mmcif.h | 2 ++ + 2 files changed, 20 insertions(+) + +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -54,6 +54,7 @@ + #include <linux/mmc/mmc.h> + #include <linux/mmc/sdio.h> + #include <linux/mmc/sh_mmcif.h> ++#include <linux/mmc/slot-gpio.h> + #include <linux/mod_devicetable.h> + #include <linux/pagemap.h> + #include <linux/platform_device.h> +@@ -1008,6 +1009,10 @@ static int sh_mmcif_get_cd(struct mmc_ho + { + struct sh_mmcif_host *host = mmc_priv(mmc); + struct sh_mmcif_plat_data *p = host->pd->dev.platform_data; ++ int ret = mmc_gpio_get_cd(mmc); ++ ++ if (ret >= 0) ++ return ret; + + if (!p || !p->get_cd) + return -ENOSYS; +@@ -1384,6 +1389,12 @@ static int __devinit sh_mmcif_probe(stru + goto ereqirq1; + } + ++ if (pd && pd->use_cd_gpio) { ++ ret = mmc_gpio_request_cd(mmc, pd->cd_gpio); ++ if (ret < 0) ++ goto erqcd; ++ } ++ + clk_disable(host->hclk); + ret = mmc_add_host(mmc); + if (ret < 0) +@@ -1397,6 +1408,9 @@ static int __devinit sh_mmcif_probe(stru + return ret; + + emmcaddh: ++ if (pd && pd->use_cd_gpio) ++ mmc_gpio_free_cd(mmc); ++erqcd: + free_irq(irq[1], host); + ereqirq1: + free_irq(irq[0], host); +@@ -1417,6 +1431,7 @@ ealloch: + static int __devexit sh_mmcif_remove(struct platform_device *pdev) + { + struct sh_mmcif_host *host = platform_get_drvdata(pdev); ++ struct sh_mmcif_plat_data *pd = pdev->dev.platform_data; + int irq[2]; + + host->dying = true; +@@ -1425,6 +1440,9 @@ static int __devexit sh_mmcif_remove(str + + dev_pm_qos_hide_latency_limit(&pdev->dev); + ++ if (pd && pd->use_cd_gpio) ++ mmc_gpio_free_cd(host->mmc); ++ + mmc_remove_host(host->mmc); + sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); + +--- a/include/linux/mmc/sh_mmcif.h ++++ b/include/linux/mmc/sh_mmcif.h +@@ -38,6 +38,8 @@ struct sh_mmcif_plat_data { + int (*get_cd)(struct platform_device *pdef); + unsigned int slave_id_tx; /* embedded slave_id_[tr]x */ + unsigned int slave_id_rx; ++ bool use_cd_gpio : 1; ++ unsigned int cd_gpio; + u8 sup_pclk; /* 1 :SH7757, 0: SH7724/SH7372 */ + unsigned long caps; + u32 ocr; @@ -81,3 +81,211 @@ patches.pramfs/16-pramfs-ioctl-operations.patch patches.pramfs/17-pramfs-makefile-and-kconfig.patch +patches.marzen/0001-sh-clkfwk-Support-variable-size-accesses-for-MSTP-cl.patch +patches.marzen/0002-sh-clkfwk-Support-variable-size-accesses-for-div4-di.patch +patches.marzen/0003-sh-clkfwk-Move-to-common-clk_div_table-accessors-for.patch +patches.marzen/0004-sh-clkfwk-Introduce-a-div_mask-for-variable-div-type.patch +patches.marzen/0005-sh-clkfwk-Use-shared-sh_clk_div_recalc.patch +patches.marzen/0006-sh-clkfwk-Use-shared-sh_clk_div_set_rate.patch +patches.marzen/0007-sh-clkfwk-Use-shared-sh_clk_div_enable-disable.patch +patches.marzen/0008-sh-clkfwk-Consolidate-div6-div4-clk_ops-definitions.patch +patches.marzen/0009-sh-clkfwk-Consolidate-div-clk-registration-helper.patch +patches.marzen/0010-irqdomain-Support-removal-of-IRQ-domains.patch +patches.marzen/0011-irqdomain-Export-remaining-public-API-symbols.patch +patches.marzen/0012-irqdomain-Make-irq_domain_simple_map-static.patch +patches.marzen/0013-irqdomain-Kill-off-duplicate-definitions.patch +patches.marzen/0014-irqdomain-trivial-pr_fmt-conversion.patch +patches.marzen/0015-irqdomain-Document-size-parameter-of-irq_domain_add_.patch +patches.marzen/0016-devicetree-add-helper-inline-for-retrieving-a-node-s.patch +patches.marzen/0017-irqdomain-Simple-NUMA-awareness.patch +patches.marzen/0018-irqdomain-Remove-unnecessary-test-for-IRQ_DOMAIN_MAP.patch +patches.marzen/0019-irqdomain-Make-ops-map-hook-optional.patch +patches.marzen/0020-irq_domain-Standardise-legacy-linear-domain-selectio.patch +patches.marzen/0021-irq_domain-correct-a-minor-wrong-comment-for-linear-.patch +patches.marzen/0022-irqdomain-Always-update-revmap-when-setting-up-a-vir.patch +patches.marzen/0023-irqdomain-Split-disassociating-code-into-separate-fu.patch +patches.marzen/0024-irqdomain-Support-for-static-IRQ-mapping-and-associa.patch +patches.marzen/0025-irqdomain-Eliminate-dedicated-radix-lookup-functions.patch +patches.marzen/0026-irqdomain-Fix-irq_create_direct_mapping-to-test-irq_.patch +patches.marzen/0027-irqdomain-eliminate-slow-path-revmap-lookups.patch +patches.marzen/0028-irqdomain-Improve-diagnostics-when-a-domain-mapping-.patch +patches.marzen/0029-ARM-mach-shmobile-Introduce-INTC_IRQ_PINS_16H.patch +patches.marzen/0030-sh-intc-Kill-off-special-reservation-interface.patch +patches.marzen/0031-sh-intc-Allocate-subgroup-virq-backing-desc-directly.patch +patches.marzen/0032-sh-intc-initial-irqdomain-support.patch +patches.marzen/0033-sh-intc-Handle-domain-association-for-sparseirq-pre-.patch +patches.marzen/0034-sh-intc-Fix-up-multi-evt-irq-association.patch +patches.marzen/0035-ARM-mach-shmobile-Introduce-shmobile_setup_delay.patch +patches.marzen/0036-ARM-mach-shmobile-Use-0x3400-as-INTCS-vector-offset.patch +patches.marzen/0037-ARM-provide-a-late_initcall-hook-for-platform-initia.patch +patches.marzen/0038-ARM-shmobile-use-machine-specific-hook-for-late-init.patch +patches.marzen/0039-ARM-mach-shmobile-Use-preset_lpj-with-calibrate_dela.patch +patches.marzen/0040-ARM-shmobile-r8a7740-add-MERAM-work-around.patch +patches.marzen/0041-ARM-shmobile-add-common-extra-gpio-functions.patch +patches.marzen/0042-ARM-mach-shmobile-add-fixed-voltage-regulators-to-ma.patch +patches.marzen/0043-ARM-shmobile-marzen-fixup-smsc911x-id-for-regulator.patch +patches.marzen/0044-ARM-shmobile-r8a7779-Route-all-interrupts-to-ARM.patch +patches.marzen/0045-dmaengine-Fixup-dmaengine_prep_slave_single-to-be-ac.patch +patches.marzen/0046-dma-dmaengine-add-slave-req-id-in-slave_config.patch +patches.marzen/0047-dmaengine-Add-wrapper-for-device_tx_status-callback.patch +patches.marzen/0048-dma-move-shdma-driver-to-an-own-directory.patch +patches.marzen/0049-dmaengine-add-an-shdma-base-library.patch +patches.marzen/0050-dma-shdma-prepare-for-conversion-to-the-shdma-base-l.patch +patches.marzen/0051-ASoC-fsi-prepare-for-conversion-to-the-shdma-base-li.patch +patches.marzen/0052-usb-renesas_usbhs-prepare-for-conversion-to-the-shdm.patch +patches.marzen/0053-dma-shdma-convert-to-the-shdma-base-library.patch +patches.marzen/0054-dmaengine-shdma-prepare-to-stop-using-struct-dma_cha.patch +patches.marzen/0055-dmaengine-shdma-cosmetic-simplify-a-static-function.patch +patches.marzen/0056-dma-sh-use-an-integer-slave-ID-to-improve-API-compat.patch +patches.marzen/0057-dma-sh-provide-a-migration-path-for-slave-drivers-to.patch +patches.marzen/0058-dmaengine-shdma-restore-partial-transfer-calculation.patch +patches.marzen/0059-serial-sh-sci-modify-sci_break_ctl.patch +patches.marzen/0060-serial-sh-sci-Update-break_ctl-handling-for-all-SCSP.patch +patches.marzen/0061-serial-sh-sci-Fix-for-port-types-without-BRI-interru.patch +patches.marzen/0062-serial-sh-sci-Fix-probe-error-paths.patch +patches.marzen/0063-serial-sh-sci-Make-probe-fail-for-ports-that-exceed-.patch +patches.marzen/0064-serial-sh-sci-prepare-for-conversion-to-the-shdma-ba.patch +patches.marzen/0065-serial-sh-sci-fix-compilation-breakage-when-DMA-is-e.patch +patches.marzen/0066-net-smsc911x-Repair-broken-failure-paths.patch +patches.marzen/0067-smsc911x.c-encapsulate-enable-irq-calls.patch +patches.marzen/0068-clocksource-sh_tmu-Convert-timer-lock-to-raw-spinloc.patch +patches.marzen/0069-mmc-tmio-use-MMC-opcode-defines-instead-of-numbers.patch +patches.marzen/0070-mmc-cd-gpio-pass-IRQF_ONESHOT-to-request_threaded_ir.patch +patches.marzen/0071-mmc-extend-and-rename-cd-gpio-helpers-to-handle-more.patch +patches.marzen/0072-mmc-tmio-Don-t-access-hardware-registers-after-stopp.patch +patches.marzen/0073-mmc-tmio-don-t-needlessly-enable-interrupts-during-p.patch +patches.marzen/0074-mmc-sdhi-implement-tmio-mmc-clock-enable-update-and-.patch +patches.marzen/0075-mmc-tmio-add-callbacks-to-enable-update-and-disable-.patch +patches.marzen/0076-mmc-sdhi-do-not-install-dummy-callbacks.patch +patches.marzen/0077-mmc-add-a-function-to-get-regulators-supplying-card-.patch +patches.marzen/0078-mmc-tmio-add-regulator-support.patch +patches.marzen/0079-mmc-tmio-remove-a-duplicated-comment-line.patch +patches.marzen/0080-mmc-tmio-support-caps2-flags.patch +patches.marzen/0081-mmc-sh_mobile_sdhi-support-caps2-flags.patch +patches.marzen/0082-mmc-sdhi-add-OF-support-make-platform-data-optional.patch +patches.marzen/0083-mmc-core-use-a-more-generic-name-for-slot-function-t.patch +patches.marzen/0084-mmc-add-two-capability-flags-for-CD-and-WP-signal-po.patch +patches.marzen/0085-mmc-add-CD-GPIO-polling-support-to-slot-functions.patch +patches.marzen/0086-mmc-core-convert-slot-functions-to-managed-allocatio.patch +patches.marzen/0087-mmc-core-add-WP-pin-handler-to-slot-functions.patch +patches.marzen/0088-mmc-tmio-use-generic-GPIO-CD-and-WP-handlers.patch +patches.marzen/0089-mmc-sh_mobile_sdhi-prepare-for-conversion-to-the-shd.patch +patches.marzen/0090-mmc-sh_mmcif-remove-unneeded-struct-sh_mmcif_dma-pre.patch +patches.marzen/0091-mmc-sh_mmcif-switch-to-the-new-DMA-channel-allocatio.patch +patches.marzen/0092-mmc-sh_mmcif-Support-MMC_SLEEP_AWAKE-command.patch +patches.marzen/0093-mmc-sh_mmcif-simplify-and-use-meaningful-label-names.patch +patches.marzen/0094-mmc-sh_mmcif-fix-clock-management.patch +patches.marzen/0095-mmc-sh_mmcif-re-read-the-clock-frequency-every-time-.patch +patches.marzen/0096-mmc-sh_mmcif-remove-redundant-.down_pwr-callback.patch +patches.marzen/0097-mmc-sh_mmcif-add-regulator-support.patch +patches.marzen/0098-mmc-sh-mmcif-add-OF-support-make-platform-data-optio.patch +patches.marzen/0099-mmc-sh_mmcif-support-generic-card-detection.patch + + +patches.armadillo800/0001-ARM-shmobile-add-common-DMAEngine-definitions.patch +patches.armadillo800/0002-ARM-shmobile-soc-core-add-R-mobile-PM-domain-common-.patch +patches.armadillo800/0003-media-V4L2-sh_mobile_ceu-manage-lower-8bit-bus.patch +patches.armadillo800/0004-regulator-support-multiple-dummy-fixed-regulators.patch +patches.armadillo800/0005-regulator-extend-the-fixed-dummy-voltage-regulator-t.patch +patches.armadillo800/0006-Input-gpio_keys-remove-useless-reinitialization-of-p.patch +patches.armadillo800/0007-Input-st1232-add-device-tree-support.patch +patches.armadillo800/0008-Input-st1232-switch-to-using-SIMPLE_DEV_PM_OPS.patch +patches.armadillo800/0009-net-sh_eth-add-support-R8A7740.patch +patches.armadillo800/0010-net-sh_eth-fix-the-rxdesc-pointer-when-rx-descriptor.patch +patches.armadillo800/0011-net-sh_eth-fix-the-condition-to-fix-the-cur_tx-dirty.patch +patches.armadillo800/0012-net-sh-eth-Add-support-selecting-MII-function-for-SH.patch +patches.armadillo800/0013-net-sh-eth-Check-return-value-of-sh_eth_reset-when-c.patch +patches.armadillo800/0014-net-sh_eth-remove-unnecessary-function.patch +patches.armadillo800/0015-net-sh_eth-remove-unnecessary-members-definitions.patch +patches.armadillo800/0016-net-sh_eth-fix-up-the-buffer-pointers.patch +patches.armadillo800/0017-net-sh_eth-add-support-for-set_ringparam-get_ringpar.patch +patches.armadillo800/0018-net-sh_eth-Add-eth-support-for-R8A7779-device.patch +patches.armadillo800/0019-ASoC-add-generic-simple-card-support.patch +patches.armadillo800/0020-ASoC-sh-fsi-use-simple-card-instead-of-fsi-ak4642.patch +patches.armadillo800/0021-ASoC-sh-fsi-use-simple-card-instead-of-fsi-hdmi.patch +patches.armadillo800/0022-ASoC-sh-fsi-use-simple-card-instead-of-fsi-da7210.patch +patches.armadillo800/0023-ASoC-sh-fsi-use-register-field-macro-name-on-IN-OUT_.patch +patches.armadillo800/0024-ASoC-sh-fsi-add-fsi_version-and-removed-meaningless-.patch +patches.armadillo800/0025-ASoC-sh-fsi-use-same-format-for-IN-OUT.patch +patches.armadillo800/0026-ASoC-sh-fsi-call-fsi_hw_startup-shutdown-from-fsi_da.patch +patches.armadillo800/0027-ASoC-sh-fsi-enable-chip-specific-data-transfer-mode.patch +patches.armadillo800/0028-ASoC-fsi-bugfix-enable-master-clock-control-on-DMA-s.patch +patches.armadillo800/0029-ASoC-fsi-bugfix-correct-dma-area.patch +patches.armadillo800/0030-ASoC-fsi-bugfix-ensure-dma-is-terminated.patch +patches.armadillo800/0031-ASoC-fsi-use-dmaengine-helper-functions.patch +patches.armadillo800/0032-ASoC-fsi-use-PIO-handler-if-DMA-handler-was-invalid.patch +#patches.armadillo800/0033-ASoC-fsi-prepare-for-conversion-to-the-shdma-base-li.patch +patches.armadillo800/0034-fbdev-sh_mobile_hdmi-add-hdmi_bit_set-function.patch +patches.armadillo800/0035-fbdev-sh_mobile_hdmi-add-interrupt-output-option.patch +patches.armadillo800/0036-fbdev-sh_mobile_hdmi-32bit-register-access-support.patch +patches.armadillo800/0037-fbdev-sh_mobile_hdmi-add-HDMI-Control-Register-suppo.patch +patches.armadillo800/0038-fbdev-sh_mipi_dsi-fix-a-section-mismatch.patch +patches.armadillo800/0039-fbdev-sh_mobile_lcdc-Constify-sh_mobile_lcdc_fix-str.patch +patches.armadillo800/0040-fbdev-sh_mobile_lcdc-Rename-fb-operation-handlers-wi.patch +patches.armadillo800/0041-fbdev-sh_mobile_lcdc-Implement-overlays-support.patch +patches.armadillo800/0042-sh_mobile_meram-Rename-operations-to-cache_-alloc-fr.patch +patches.armadillo800/0043-sh_mobile_meram-Use-direct-function-calls-for-the-pu.patch +patches.armadillo800/0044-sh_mobile_meram-Add-direct-MERAM-allocation-API.patch +patches.armadillo800/0045-fbdev-sh_mobile_lcdc-Destroy-mutex-at-remove-time.patch +patches.armadillo800/0046-fbdev-sh_mobile_lcdc-Fix-line-pitch-computation.patch +patches.armadillo800/0047-fbdev-sh_mobile_lcdc-Use-channel-configuration-to-in.patch +patches.armadillo800/0048-fbdev-sh_mobile_lcdc-Support-horizontal-panning.patch +patches.armadillo800/0049-fbdev-sh_mobile_lcdc-Fix-overlay-registers-update-du.patch +patches.armadillo800/0050-fbdev-sh_mobile_lcdc-Fix-pan-offset-computation-in-Y.patch +patches.armadillo800/0051-fbdev-sh_mobile_lcdc-Fix-vertical-panning-step.patch +patches.armadillo800/0052-ARM-mach-shmobile-r8a7740-add-gpio_irq-support.patch +patches.armadillo800/0053-ARM-mach-shmobile-r8a7740-cleanup-I2C-workaround-met.patch +patches.armadillo800/0054-ARM-mach-shmobile-clock-r8a7740-add-FSI-clock.patch +patches.armadillo800/0055-ARM-mach-shmobile-clock-r8a7740-add-USB-clock.patch +patches.armadillo800/0056-ARM-mach-shmobile-clock-r8a7740-add-SDHI-clock.patch +patches.armadillo800/0057-ARM-mach-shmobile-clock-r8a7740-add-MMCIF-clock.patch +patches.armadillo800/0058-ARM-mach-shmobile-clock-r8a7740-use-followparent_rec.patch +patches.armadillo800/0059-ARM-mach-shmobile-add-armadillo800eva-board-support.patch +patches.armadillo800/0060-ARM-mach-shmobile-armadillo800eva-add-defconfig.patch +patches.armadillo800/0061-ARM-mach-shmobile-armadillo800eva-add-support-LCDC0.patch +patches.armadillo800/0062-ARM-mach-shmobile-armadillo800eva-add-support-gpio_k.patch +patches.armadillo800/0063-ARM-mach-shmobile-armadillo800eva-add-support-sh_eth.patch +patches.armadillo800/0064-ARM-mach-shmobile-armadillo800eva-add-support-ST1232.patch +patches.armadillo800/0065-ARM-mach-shmobile-armadillo800eva-add-USB-function-s.patch +patches.armadillo800/0066-ARM-mach-shmobile-armadillo800eva-add-SDHI0-support.patch +patches.armadillo800/0067-ARM-mach-shmobile-armadillo800eva-add-SDHI1-support.patch +patches.armadillo800/0068-ARM-mach-shmobile-armadillo800eva-add-MMCIF-support.patch +patches.armadillo800/0069-ARM-mach-shmobile-r8a7740-reserve-DMA-memory-for-the.patch +patches.armadillo800/0070-ARM-mach-shmobile-clock-r8a7740-add-sh-eth-clock.patch +patches.armadillo800/0071-ARM-mach-shmobile-armadillo800eva-defconfig-update.patch +patches.armadillo800/0072-ARM-mach-shmobile-Use-DT_MACHINE-for-armadillo-800-e.patch +patches.armadillo800/0073-ARM-shmobile-r8a7740-add-HDMI-interrupt-support.patch +patches.armadillo800/0074-ARM-shmobile-r8a7740-add-HDMI-clock-support.patch +patches.armadillo800/0075-ARM-shmobile-r8a7740-add-HDMI-GPIO-support.patch +patches.armadillo800/0076-ARM-shmobile-r8a7740-add-MERAM-work-around.patch +patches.armadillo800/0077-ARM-shmobile-r8a7740-add-CEU-clock-support.patch +patches.armadillo800/0078-ARM-shmobile-r8a7740-add-FSI-parent-clock-support.patch +patches.armadillo800/0079-ARM-shmobile-r8a7740-add-FSI-B-for-HDMI-GPIO-support.patch +patches.armadillo800/0080-ARM-shmobile-armadillo800eva-enable-HDMI.patch +patches.armadillo800/0081-ARM-mach-shmobile-armadillo800eva-Use-late-init-mach.patch +patches.armadillo800/0082-ARM-shmobile-armadillo800eva-enable-camera.patch +patches.armadillo800/0083-ARM-shmobile-r8a7740-add-DMAEngine-support-for-FSI.patch +patches.armadillo800/0084-ARM-shmobile-r8a7740-add-DMAEngine-support-for-SDHI.patch +patches.armadillo800/0085-ARM-shmobile-r8a7740-add-DMAEngine-support-for-USB.patch +patches.armadillo800/0086-ARM-shmobile-use-common-DMAEngine-definitions-on-r8a.patch +patches.armadillo800/0087-ARM-shmobile-armadillo800eva-enable-FSI-WM8978-sound.patch +patches.armadillo800/0088-ARM-shmobile-armadillo800eva-enable-FSI-HDMI-sound.patch +patches.armadillo800/0089-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-FSI.patch +patches.armadillo800/0090-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-SDH.patch +patches.armadillo800/0091-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-USB.patch +patches.armadillo800/0092-ARM-shmobile-use-common-extra-gpio-functions-on-arma.patch +patches.armadillo800/0093-ARM-mach-shmobile-add-fixed-voltage-regulators-to-ar.patch +patches.armadillo800/0094-ARM-mach-shmobile-Convert-sh_clk_mstp32_register-to-.patch +patches.armadillo800/0095-ARM-shmobile-r8a7740-fixup-MSEL1CR-7bit-control.patch +patches.armadillo800/0096-ARM-shmobile-r8a7740-add-A4S-pm-domain-support.patch +patches.armadillo800/0097-ARM-shmobile-r8a7740-add-A3SP-pm-domain-support.patch +patches.armadillo800/0098-ARM-shmobile-r8a7740-add-A4LC-pm-domain-support.patch +patches.armadillo800/0099-ARM-shmobile-armadillo800eva-USB-Func-enables-extern.patch +patches.armadillo800/0100-ARM-shmobile-armadillo800eva-A4LC-domain-includes-LC.patch +patches.armadillo800/0101-ARM-shmobile-armadillo800eva-A3SP-domain-includes-US.patch +patches.armadillo800/0102-ARM-mach-shmobile-r8a7740-generic-board-support-via-.patch +patches.armadillo800/0103-ARM-mach-shmobile-armadillo800eva-defconfig-Allow-us.patch +patches.armadillo800/0104-ARM-mach-shmobile-armadillo800eva-Fix-GPIO-buttons-d.patch +patches.armadillo800/0105-ARM-mach-shmobile-armadillo800eva-Enable-power-butto.patch +patches.armadillo800/0106-ARM-shmobile-armadillo800eva-fixup-sound-card-detect.patch +patches.armadillo800/0107-ARM-shmobile-armadillo800eva-enable-rw-rootfs-mount.patch |