* [PATCH v5 1/7] drm: sunxi: Add a basic DRM driver for Allwinner DE2
From: Daniel Vetter @ 2016-10-25 6:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161025064422.4jua6qmpr7zu3ijt@phenom.ffwll.local>
On Tue, Oct 25, 2016 at 08:44:22AM +0200, Daniel Vetter wrote:
> On Fri, Oct 21, 2016 at 09:26:18AM +0200, Jean-Francois Moine wrote:
> > +static int de2_drm_bind(struct device *dev)
> > +{
> > + struct drm_device *drm;
> > + struct priv *priv;
> > + int ret;
> > +
> > + drm = drm_dev_alloc(&de2_drm_driver, dev);
Oh and you might want to look into drm_dev_init, allows you to use
subclassing instead of pointer chasing for your driver-private data.
-Daniel
> > + if (!drm)
> > + return -ENOMEM;
> > +
> > + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> > + if (!priv) {
> > + dev_err(dev, "failed to allocate private area\n");
> > + ret = -ENOMEM;
> > + goto out1;
> > + }
> > +
> > + dev_set_drvdata(dev, drm);
> > + drm->dev_private = priv;
> > +
> > + drm_mode_config_init(drm);
> > + drm->mode_config.min_width = 32; /* needed for cursor */
> > + drm->mode_config.min_height = 32;
> > + drm->mode_config.max_width = 1920;
> > + drm->mode_config.max_height = 1080;
> > + drm->mode_config.funcs = &de2_mode_config_funcs;
> > +
> > + drm->irq_enabled = true;
> > +
> > + /* initialize the display engine */
> > + priv->soc_type = (int) of_match_device(de2_drm_of_match, dev)->data;
> > + ret = de2_de_init(priv, dev);
> > + if (ret)
> > + goto out2;
> > +
> > + /* start the subdevices */
> > + ret = component_bind_all(dev, drm);
> > + if (ret < 0)
> > + goto out2;
> > +
> > + ret = drm_dev_register(drm, 0);
>
> This needs to be the very last step in your driver load sequence.
> Kerneldoc explains why. Similar, but inverted for unloading:
> drm_dev_unregister is the very first thing you must call.
> -Daniel
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
^ permalink raw reply
* [PATCH] nvmem: sunxi-sid: SID content is not a valid source of randomness
From: Jean-Francois Moine @ 2016-10-25 7:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161025053855.GA901@Red>
On Tue, 25 Oct 2016 07:38:55 +0200
LABBE Corentin <clabbe.montjoie@gmail.com> wrote:
> > On Sat, Oct 22, 2016 at 03:53:28PM +0200, Corentin Labbe wrote:
> > > Since SID's content is constant over reboot,
> >
> > That's not true, at least not across all the Allwinner SoCs, and
> > especially not on the A10 and A20 that this driver supports.
> >
>
> On my cubieboard2 (A20)
> hexdump -C /sys/devices/platform/soc\@01c00000/1c23800.eeprom/sunxi-sid0/nvmem
> 00000000 16 51 66 83 80 48 50 72 56 54 48 48 03 c2 75 72 |.Qf..HPrVTHH..ur|
> 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
> *
> 00000100 16 51 66 83 80 48 50 72 56 54 48 48 03 c2 75 72 |.Qf..HPrVTHH..ur|
> 00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
> *
> 00000200
> cubiedev ~ # reboot
> cubiedev ~ # hexdump -C /sys/devices/platform/soc\@01c00000/1c23800.eeprom/sunxi-sid0/nvmem
> 00000000 16 51 66 83 80 48 50 72 56 54 48 48 03 c2 75 72 |.Qf..HPrVTHH..ur|
> 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
> *
> 00000100 16 51 66 83 80 48 50 72 56 54 48 48 03 c2 75 72 |.Qf..HPrVTHH..ur|
> 00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
> *
> 00000200
>
> So clearly for me its constant.
Even after power off/power on?
--
Ken ar c'henta? | ** Breizh ha Linux atav! **
Jef | http://moinejf.free.fr/
^ permalink raw reply
* [PATCH 0/5] Switch to the DT cpufreq policy on the Integrator
From: Linus Walleij @ 2016-10-25 7:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAJZ5v0gb8XTTrSgQzT==7=tLiAyy3RemmVnDYfm-kNULw0_uZQ@mail.gmail.com>
On Mon, Oct 24, 2016 at 10:15 PM, Rafael J. Wysocki <rafael@kernel.org> wrote:
> On Mon, Oct 24, 2016 at 9:28 PM, Linus Walleij <linus.walleij@linaro.org> wrote:
>> On Wed, Oct 19, 2016 at 12:14 PM, Arnd Bergmann <arnd@arndb.de> wrote:
>>
>>> I don't see any hard dependency here, so I'd suggest to merge the
>>> two cpufreq patches through the subsystem tree, and the ARM patches
>>> through arm-soc.
>>
>> That's right, Viresh can you merge patches 1 and 5 to the
>> cpufreq tree please?
>
> Well, that would be me.
>
> Can you please resend the two as a separate series, with all tags
> collected so far if any?
Sure no problem.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH RESEND 1/2] dt: bindings: add allwinner,otg-routed property for phy-sun4i-usb
From: Maxime Ripard @ 2016-10-25 7:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161025041139.46454-1-icenowy@aosc.xyz>
Hi,
On Tue, Oct 25, 2016 at 12:11:38PM +0800, Icenowy Zheng wrote:
> On some newer Allwinner SoCs (H3 or A64), the PHY0 can be either routed to
> the MUSB controller (which is an OTG controller) or the OHCI/EHCI pair
> (which is a Host-only controller, but more stable and easy to implement).
>
> This property marks whether on a certain board which controller should be
> attached to the PHY.
>
> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
Didn't Hans reject this already? Why are you resending it?
Thanks,
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161025/027156a6/attachment.sig>
^ permalink raw reply
* [PATCH 1/2] cpufreq: enable the DT cpufreq driver on the Integrators
From: Linus Walleij @ 2016-10-25 7:21 UTC (permalink / raw)
To: linux-arm-kernel
This enables the generic DT and OPP-based cpufreq driver on the
ARM Integrator/AP and Integrator/CP.
Cc: Rafael J. Wysocki <rafael@kernel.org>
Cc: Russell King <linux@armlinux.org.uk>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
drivers/cpufreq/cpufreq-dt-platdev.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index 71267626456b..142a6f615e52 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -26,6 +26,9 @@ static const struct of_device_id machines[] __initconst = {
{ .compatible = "allwinner,sun8i-a83t", },
{ .compatible = "allwinner,sun8i-h3", },
+ { .compatible = "arm,integrator-ap", },
+ { .compatible = "arm,integrator-cp", },
+
{ .compatible = "hisilicon,hi6220", },
{ .compatible = "fsl,imx27", },
--
2.7.4
^ permalink raw reply related
* [PATCH 2/2] cpufreq: retire the Integrator cpufreq driver
From: Linus Walleij @ 2016-10-25 7:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477380085-6929-1-git-send-email-linus.walleij@linaro.org>
After switching the core module clocks controlling the Integrator
clock frequencies to the common clock framework, defining the
operating points in the device tree, and activating the generic
DT-based CPUfreq driver, we can retire the old Integrator
cpufreq driver.
Cc: Rafael J. Wysocki <rafael@kernel.org>
Cc: Russell King <linux@armlinux.org.uk>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
drivers/cpufreq/Kconfig.arm | 8 --
drivers/cpufreq/Makefile | 1 -
drivers/cpufreq/integrator-cpufreq.c | 239 -----------------------------------
3 files changed, 248 deletions(-)
delete mode 100644 drivers/cpufreq/integrator-cpufreq.c
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index d89b8afe23b6..fdbc630272b3 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -60,14 +60,6 @@ config ARM_IMX6Q_CPUFREQ
If in doubt, say N.
-config ARM_INTEGRATOR
- tristate "CPUfreq driver for ARM Integrator CPUs"
- depends on ARCH_INTEGRATOR
- default y
- help
- This enables the CPUfreq driver for ARM Integrator CPUs.
- If in doubt, say Y.
-
config ARM_KIRKWOOD_CPUFREQ
def_bool MACH_KIRKWOOD
help
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 0a9b6a093646..7dde82179d62 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -56,7 +56,6 @@ obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o
obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o
obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o
-obj-$(CONFIG_ARM_INTEGRATOR) += integrator-cpufreq.o
obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o
obj-$(CONFIG_ARM_MT8173_CPUFREQ) += mt8173-cpufreq.o
obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o
diff --git a/drivers/cpufreq/integrator-cpufreq.c b/drivers/cpufreq/integrator-cpufreq.c
deleted file mode 100644
index 79e3ff2771a6..000000000000
--- a/drivers/cpufreq/integrator-cpufreq.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2001-2002 Deep Blue Solutions Ltd.
- *
- * 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.
- *
- * CPU support functions
- */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/cpufreq.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-
-#include <asm/mach-types.h>
-#include <asm/hardware/icst.h>
-
-static void __iomem *cm_base;
-/* The cpufreq driver only use the OSC register */
-#define INTEGRATOR_HDR_OSC_OFFSET 0x08
-#define INTEGRATOR_HDR_LOCK_OFFSET 0x14
-
-static struct cpufreq_driver integrator_driver;
-
-static const struct icst_params lclk_params = {
- .ref = 24000000,
- .vco_max = ICST525_VCO_MAX_5V,
- .vco_min = ICST525_VCO_MIN,
- .vd_min = 8,
- .vd_max = 132,
- .rd_min = 24,
- .rd_max = 24,
- .s2div = icst525_s2div,
- .idx2s = icst525_idx2s,
-};
-
-static const struct icst_params cclk_params = {
- .ref = 24000000,
- .vco_max = ICST525_VCO_MAX_5V,
- .vco_min = ICST525_VCO_MIN,
- .vd_min = 12,
- .vd_max = 160,
- .rd_min = 24,
- .rd_max = 24,
- .s2div = icst525_s2div,
- .idx2s = icst525_idx2s,
-};
-
-/*
- * Validate the speed policy.
- */
-static int integrator_verify_policy(struct cpufreq_policy *policy)
-{
- struct icst_vco vco;
-
- cpufreq_verify_within_cpu_limits(policy);
-
- vco = icst_hz_to_vco(&cclk_params, policy->max * 1000);
- policy->max = icst_hz(&cclk_params, vco) / 1000;
-
- vco = icst_hz_to_vco(&cclk_params, policy->min * 1000);
- policy->min = icst_hz(&cclk_params, vco) / 1000;
-
- cpufreq_verify_within_cpu_limits(policy);
- return 0;
-}
-
-
-static int integrator_set_target(struct cpufreq_policy *policy,
- unsigned int target_freq,
- unsigned int relation)
-{
- cpumask_t cpus_allowed;
- int cpu = policy->cpu;
- struct icst_vco vco;
- struct cpufreq_freqs freqs;
- u_int cm_osc;
-
- /*
- * Save this threads cpus_allowed mask.
- */
- cpus_allowed = current->cpus_allowed;
-
- /*
- * Bind to the specified CPU. When this call returns,
- * we should be running on the right CPU.
- */
- set_cpus_allowed_ptr(current, cpumask_of(cpu));
- BUG_ON(cpu != smp_processor_id());
-
- /* get current setting */
- cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET);
-
- if (machine_is_integrator())
- vco.s = (cm_osc >> 8) & 7;
- else if (machine_is_cintegrator())
- vco.s = 1;
- vco.v = cm_osc & 255;
- vco.r = 22;
- freqs.old = icst_hz(&cclk_params, vco) / 1000;
-
- /* icst_hz_to_vco rounds down -- so we need the next
- * larger freq in case of CPUFREQ_RELATION_L.
- */
- if (relation == CPUFREQ_RELATION_L)
- target_freq += 999;
- if (target_freq > policy->max)
- target_freq = policy->max;
- vco = icst_hz_to_vco(&cclk_params, target_freq * 1000);
- freqs.new = icst_hz(&cclk_params, vco) / 1000;
-
- if (freqs.old == freqs.new) {
- set_cpus_allowed_ptr(current, &cpus_allowed);
- return 0;
- }
-
- cpufreq_freq_transition_begin(policy, &freqs);
-
- cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET);
-
- if (machine_is_integrator()) {
- cm_osc &= 0xfffff800;
- cm_osc |= vco.s << 8;
- } else if (machine_is_cintegrator()) {
- cm_osc &= 0xffffff00;
- }
- cm_osc |= vco.v;
-
- __raw_writel(0xa05f, cm_base + INTEGRATOR_HDR_LOCK_OFFSET);
- __raw_writel(cm_osc, cm_base + INTEGRATOR_HDR_OSC_OFFSET);
- __raw_writel(0, cm_base + INTEGRATOR_HDR_LOCK_OFFSET);
-
- /*
- * Restore the CPUs allowed mask.
- */
- set_cpus_allowed_ptr(current, &cpus_allowed);
-
- cpufreq_freq_transition_end(policy, &freqs, 0);
-
- return 0;
-}
-
-static unsigned int integrator_get(unsigned int cpu)
-{
- cpumask_t cpus_allowed;
- unsigned int current_freq;
- u_int cm_osc;
- struct icst_vco vco;
-
- cpus_allowed = current->cpus_allowed;
-
- set_cpus_allowed_ptr(current, cpumask_of(cpu));
- BUG_ON(cpu != smp_processor_id());
-
- /* detect memory etc. */
- cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET);
-
- if (machine_is_integrator())
- vco.s = (cm_osc >> 8) & 7;
- else
- vco.s = 1;
- vco.v = cm_osc & 255;
- vco.r = 22;
-
- current_freq = icst_hz(&cclk_params, vco) / 1000; /* current freq */
-
- set_cpus_allowed_ptr(current, &cpus_allowed);
-
- return current_freq;
-}
-
-static int integrator_cpufreq_init(struct cpufreq_policy *policy)
-{
-
- /* set default policy and cpuinfo */
- policy->max = policy->cpuinfo.max_freq = 160000;
- policy->min = policy->cpuinfo.min_freq = 12000;
- policy->cpuinfo.transition_latency = 1000000; /* 1 ms, assumed */
-
- return 0;
-}
-
-static struct cpufreq_driver integrator_driver = {
- .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK,
- .verify = integrator_verify_policy,
- .target = integrator_set_target,
- .get = integrator_get,
- .init = integrator_cpufreq_init,
- .name = "integrator",
-};
-
-static int __init integrator_cpufreq_probe(struct platform_device *pdev)
-{
- struct resource *res;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
- cm_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- if (!cm_base)
- return -ENODEV;
-
- return cpufreq_register_driver(&integrator_driver);
-}
-
-static int __exit integrator_cpufreq_remove(struct platform_device *pdev)
-{
- return cpufreq_unregister_driver(&integrator_driver);
-}
-
-static const struct of_device_id integrator_cpufreq_match[] = {
- { .compatible = "arm,core-module-integrator"},
- { },
-};
-
-MODULE_DEVICE_TABLE(of, integrator_cpufreq_match);
-
-static struct platform_driver integrator_cpufreq_driver = {
- .driver = {
- .name = "integrator-cpufreq",
- .of_match_table = integrator_cpufreq_match,
- },
- .remove = __exit_p(integrator_cpufreq_remove),
-};
-
-module_platform_driver_probe(integrator_cpufreq_driver,
- integrator_cpufreq_probe);
-
-MODULE_AUTHOR("Russell M. King");
-MODULE_DESCRIPTION("cpufreq driver for ARM Integrator CPUs");
-MODULE_LICENSE("GPL");
--
2.7.4
^ permalink raw reply related
* [PATCH/RFT v2 11/17] USB: OHCI: make ohci-da8xx a separate driver
From: Axel Haslam @ 2016-10-25 7:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <403743d8-dff2-3389-105b-1082b674b0b8@lechnology.com>
On Tue, Oct 25, 2016 at 2:38 AM, David Lechner <david@lechnology.com> wrote:
> On 10/24/2016 11:46 AM, ahaslam at baylibre.com wrote:
>>
>> From: Manjunath Goudar <manjunath.goudar@linaro.org>
>>
>> Separate the Davinci OHCI host controller driver from ohci-hcd
>> host code so that it can be built as a separate driver module.
>> This work is part of enabling multi-platform kernels on ARM;
>> it would be nice to have in 3.11.
>
>
> No need for comment about kernel 3.11.
yes, ok.
>
>>
>> Signed-off-by: Manjunath Goudar <manjunath.goudar@linaro.org>
>> ---
>> drivers/usb/host/Kconfig | 2 +-
>> drivers/usb/host/Makefile | 1 +
>> drivers/usb/host/ohci-da8xx.c | 185
>> +++++++++++++++++-------------------------
>> drivers/usb/host/ohci-hcd.c | 18 ----
>> 4 files changed, 76 insertions(+), 130 deletions(-)
>>
>> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
>> index 83b6cec..642c6fe8 100644
>> --- a/drivers/usb/host/Kconfig
>> +++ b/drivers/usb/host/Kconfig
>> @@ -479,7 +479,7 @@ config USB_OHCI_HCD_OMAP3
>> OMAP3 and later chips.
>>
>> config USB_OHCI_HCD_DAVINCI
>> - bool "OHCI support for TI DaVinci DA8xx"
>> + tristate "OHCI support for TI DaVinci DA8xx"
>> depends on ARCH_DAVINCI_DA8XX
>> depends on USB_OHCI_HCD=y
>
>
> Need to drop the "=y" here, otherwise you still can't compile this as a
> module.
Im able to complile it as a module, but ok ill remove it.
>
>> select PHY_DA8XX_USB
>> diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
>> index 6ef785b..2644537 100644
>> --- a/drivers/usb/host/Makefile
>> +++ b/drivers/usb/host/Makefile
>> @@ -61,6 +61,7 @@ obj-$(CONFIG_USB_OHCI_HCD_AT91) += ohci-at91.o
>> obj-$(CONFIG_USB_OHCI_HCD_S3C2410) += ohci-s3c2410.o
>> obj-$(CONFIG_USB_OHCI_HCD_LPC32XX) += ohci-nxp.o
>> obj-$(CONFIG_USB_OHCI_HCD_PXA27X) += ohci-pxa27x.o
>> +obj-$(CONFIG_USB_OHCI_HCD_DAVINCI) += ohci-da8xx.o
>>
>> obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o
>> obj-$(CONFIG_USB_FHCI_HCD) += fhci.o
>> diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
>> index e98066d..5585d9e 100644
>> --- a/drivers/usb/host/ohci-da8xx.c
>> +++ b/drivers/usb/host/ohci-da8xx.c
>> @@ -11,16 +11,31 @@
>> * kind, whether express or implied.
>> */
>>
>> +#include <linux/clk.h>
>> +#include <linux/io.h>
>> #include <linux/interrupt.h>
>> #include <linux/jiffies.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> #include <linux/platform_device.h>
>> -#include <linux/clk.h>
>> #include <linux/phy/phy.h>
>> #include <linux/platform_data/usb-davinci.h>
>> +#include <linux/platform_device.h>
>
>
> linux/platform_device.h is listed twice
>
>> +#include <linux/usb.h>
>> +#include <linux/usb/hcd.h>
>> +#include <asm/unaligned.h>
>>
>> -#ifndef CONFIG_ARCH_DAVINCI_DA8XX
>> -#error "This file is DA8xx bus glue. Define CONFIG_ARCH_DAVINCI_DA8XX."
>> -#endif
>> +#include "ohci.h"
>> +
>> +#define DRIVER_DESC "OHCI DA8XX driver"
>> +
>> +static const char hcd_name[] = "ohci-da8xx";
>
>
> why static const char instead of #define? This is only used one time in a
> pr_info, so it seems kind of pointless anyway.
Other drivers are using static const for the same variable.
i think static const is preferred over #define because #define doet give a type.
If you dont mind ill keep it static const.
>
>> +
>> +static struct hc_driver __read_mostly ohci_da8xx_hc_driver;
>> +
>> +static int (*orig_ohci_hub_control)(struct usb_hcd *hcd, u16 typeReq,
>> + u16 wValue, u16 wIndex, char *buf, u16 wLength);
>> +static int (*orig_ohci_hub_status_data)(struct usb_hcd *hcd, char *buf);
>>
>> static struct clk *usb11_clk;
>> static struct phy *usb11_phy;
>> @@ -73,7 +88,7 @@ static void ohci_da8xx_ocic_handler(struct
>> da8xx_ohci_root_hub *hub)
>> hub->set_power(0);
>> }
>>
>> -static int ohci_da8xx_init(struct usb_hcd *hcd)
>> +static int ohci_da8xx_reset(struct usb_hcd *hcd)
>> {
>> struct device *dev = hcd->self.controller;
>> struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
>> @@ -93,7 +108,7 @@ static int ohci_da8xx_init(struct usb_hcd *hcd)
>> */
>> ohci->num_ports = 1;
>>
>> - result = ohci_init(ohci);
>> + result = ohci_setup(hcd);
>> if (result < 0) {
>> ohci_da8xx_disable();
>> return result;
>> @@ -121,30 +136,12 @@ static int ohci_da8xx_init(struct usb_hcd *hcd)
>> return result;
>> }
>>
>> -static void ohci_da8xx_stop(struct usb_hcd *hcd)
>> -{
>> - ohci_stop(hcd);
>> - ohci_da8xx_disable();
>> -}
>> -
>> -static int ohci_da8xx_start(struct usb_hcd *hcd)
>> -{
>> - struct ohci_hcd *ohci = hcd_to_ohci(hcd);
>> - int result;
>> -
>> - result = ohci_run(ohci);
>> - if (result < 0)
>> - ohci_da8xx_stop(hcd);
>> -
>> - return result;
>> -}
>> -
>> /*
>> * Update the status data from the hub with the over-current indicator
>> change.
>> */
>> static int ohci_da8xx_hub_status_data(struct usb_hcd *hcd, char *buf)
>> {
>> - int length = ohci_hub_status_data(hcd, buf);
>> + int length = orig_ohci_hub_status_data(hcd, buf);
>>
>> /* See if we have OCIC flag set */
>> if (ocic_flag) {
>> @@ -226,66 +223,13 @@ static int ohci_da8xx_hub_control(struct usb_hcd
>> *hcd, u16 typeReq, u16 wValue,
>> }
>> }
>>
>> - return ohci_hub_control(hcd, typeReq, wValue, wIndex, buf,
>> wLength);
>> + return orig_ohci_hub_control(hcd, typeReq, wValue,
>> + wIndex, buf, wLength);
>> }
>>
>> -static const struct hc_driver ohci_da8xx_hc_driver = {
>> - .description = hcd_name,
>> - .product_desc = "DA8xx OHCI",
>> - .hcd_priv_size = sizeof(struct ohci_hcd),
>> -
>> - /*
>> - * generic hardware linkage
>> - */
>> - .irq = ohci_irq,
>> - .flags = HCD_USB11 | HCD_MEMORY,
>> -
>> - /*
>> - * basic lifecycle operations
>> - */
>> - .reset = ohci_da8xx_init,
>> - .start = ohci_da8xx_start,
>> - .stop = ohci_da8xx_stop,
>> - .shutdown = ohci_shutdown,
>> -
>> - /*
>> - * managing i/o requests and associated device resources
>> - */
>> - .urb_enqueue = ohci_urb_enqueue,
>> - .urb_dequeue = ohci_urb_dequeue,
>> - .endpoint_disable = ohci_endpoint_disable,
>> -
>> - /*
>> - * scheduling support
>> - */
>> - .get_frame_number = ohci_get_frame,
>> -
>> - /*
>> - * root hub support
>> - */
>> - .hub_status_data = ohci_da8xx_hub_status_data,
>> - .hub_control = ohci_da8xx_hub_control,
>> -
>> -#ifdef CONFIG_PM
>> - .bus_suspend = ohci_bus_suspend,
>> - .bus_resume = ohci_bus_resume,
>> -#endif
>> - .start_port_reset = ohci_start_port_reset,
>> -};
>> -
>>
>> /*-------------------------------------------------------------------------*/
>>
>> -
>> -/**
>> - * usb_hcd_da8xx_probe - initialize DA8xx-based HCDs
>> - * Context: !in_interrupt()
>> - *
>> - * Allocates basic resources for this USB host controller, and
>> - * then invokes the start() method for the HCD associated with it
>> - * through the hotplug entry's driver_data.
>> - */
>> -static int usb_hcd_da8xx_probe(const struct hc_driver *driver,
>> - struct platform_device *pdev)
>> +static int ohci_da8xx_probe(struct platform_device *pdev)
>> {
>> struct da8xx_ohci_root_hub *hub = dev_get_platdata(&pdev->dev);
>> struct usb_hcd *hcd;
>> @@ -295,6 +239,11 @@ static int usb_hcd_da8xx_probe(const struct hc_driver
>> *driver,
>> if (hub == NULL)
>> return -ENODEV;
>>
>> + hcd = usb_create_hcd(&ohci_da8xx_hc_driver, &pdev->dev,
>> + dev_name(&pdev->dev));
>> + if (!hcd)
>> + return -ENOMEM;
>> +
>
>
> Won't this leak hdc if there is an error later?
>
>> usb11_clk = devm_clk_get(&pdev->dev, "usb11");
>> if (IS_ERR(usb11_clk)) {
>> if (PTR_ERR(usb11_clk) != -EPROBE_DEFER)
>> @@ -309,9 +258,6 @@ static int usb_hcd_da8xx_probe(const struct hc_driver
>> *driver,
>> return PTR_ERR(usb11_phy);
>> }
>>
>> - hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
>> - if (!hcd)
>> - return -ENOMEM;
>
>
> Why does this need to be moved?
>
it should not have moved this, will fix.
>>
>> mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> hcd->regs = devm_ioremap_resource(&pdev->dev, mem);
>> @@ -323,13 +269,12 @@ static int usb_hcd_da8xx_probe(const struct
>> hc_driver *driver,
>> hcd->rsrc_start = mem->start;
>> hcd->rsrc_len = resource_size(mem);
>>
>> - ohci_hcd_init(hcd_to_ohci(hcd));
>> -
>> irq = platform_get_irq(pdev, 0);
>> if (irq < 0) {
>> error = -ENODEV;
>> goto err;
>> }
>> +
>> error = usb_add_hcd(hcd, irq, 0);
>> if (error)
>> goto err;
>> @@ -348,35 +293,14 @@ static int usb_hcd_da8xx_probe(const struct
>> hc_driver *driver,
>> return error;
>> }
>>
>> -/**
>> - * usb_hcd_da8xx_remove - shutdown processing for DA8xx-based HCDs
>> - * @dev: USB Host Controller being removed
>> - * Context: !in_interrupt()
>> - *
>> - * Reverses the effect of usb_hcd_da8xx_probe(), first invoking
>> - * the HCD's stop() method. It is always called from a thread
>> - * context, normally "rmmod", "apmd", or something similar.
>> - */
>> -static inline void
>> -usb_hcd_da8xx_remove(struct usb_hcd *hcd, struct platform_device *pdev)
>> +static int ohci_da8xx_remove(struct platform_device *pdev)
>> {
>> + struct usb_hcd *hcd = platform_get_drvdata(pdev);
>> struct da8xx_ohci_root_hub *hub = dev_get_platdata(&pdev->dev);
>>
>> hub->ocic_notify(NULL);
>> usb_remove_hcd(hcd);
>> usb_put_hcd(hcd);
>> -}
>> -
>> -static int ohci_hcd_da8xx_drv_probe(struct platform_device *dev)
>> -{
>> - return usb_hcd_da8xx_probe(&ohci_da8xx_hc_driver, dev);
>> -}
>> -
>> -static int ohci_hcd_da8xx_drv_remove(struct platform_device *dev)
>> -{
>> - struct usb_hcd *hcd = platform_get_drvdata(dev);
>> -
>> - usb_hcd_da8xx_remove(hcd, dev);
>>
>> return 0;
>> }
>> @@ -426,12 +350,16 @@ static int ohci_da8xx_resume(struct platform_device
>> *dev)
>> }
>> #endif
>>
>> +static const struct ohci_driver_overrides da8xx_overrides __initconst = {
>> + .reset = ohci_da8xx_reset
>> +};
>> +
>> /*
>> * Driver definition to register with platform structure.
>> */
>> static struct platform_driver ohci_hcd_da8xx_driver = {
>> - .probe = ohci_hcd_da8xx_drv_probe,
>> - .remove = ohci_hcd_da8xx_drv_remove,
>> + .probe = ohci_da8xx_probe,
>> + .remove = ohci_da8xx_remove,
>> .shutdown = usb_hcd_platform_shutdown,
>> #ifdef CONFIG_PM
>> .suspend = ohci_da8xx_suspend,
>
>
> It would probably be a good idea to change the driver name here. Currently
> it is "ohci". Although this would be better in a separate patch if the name
> has to be changed to match in other files as well.
>
ok, ill do a separate patch for that.
>> @@ -442,4 +370,39 @@ static int ohci_da8xx_resume(struct platform_device
>> *dev)
>> },
>> };
>>
>> +static int __init ohci_da8xx_init(void)
>> +{
>> +
>> + if (usb_disabled())
>> + return -ENODEV;
>> +
>> + pr_info("%s: " DRIVER_DESC "\n", hcd_name);
>> + ohci_init_driver(&ohci_da8xx_hc_driver, &da8xx_overrides);
>> +
>> + /*
>> + * The Davinci da8xx HW has some unusual quirks, which require
>> + * da8xx-specific workarounds. We override certain hc_driver
>> + * functions here to achieve that. We explicitly do not enhance
>> + * ohci_driver_overrides to allow this more easily, since this
>> + * is an unusual case, and we don't want to encourage others to
>> + * override these functions by making it too easy.
>> + */
>> +
>> + orig_ohci_hub_control = ohci_da8xx_hc_driver.hub_control;
>> + orig_ohci_hub_status_data = ohci_da8xx_hc_driver.hub_status_data;
>> +
>> + ohci_da8xx_hc_driver.hub_status_data =
>> ohci_da8xx_hub_status_data;
>> + ohci_da8xx_hc_driver.hub_control = ohci_da8xx_hub_control;
>> +
>> + return platform_driver_register(&ohci_hcd_da8xx_driver);
>> +}
>> +module_init(ohci_da8xx_init);
>> +
>> +static void __exit ohci_da8xx_cleanup(void)
>
>
> ohci_da8xx_exit would be a better name
>
ok.
>> +{
>> + platform_driver_unregister(&ohci_hcd_da8xx_driver);
>> +}
>> +module_exit(ohci_da8xx_cleanup);
>> +MODULE_DESCRIPTION(DRIVER_DESC);
>> +MODULE_LICENSE("GPL");
>> MODULE_ALIAS("platform:ohci");
>
>
> this will need to be changed too if you change the driver name
>
>> diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
>> index 1700908..8de174a 100644
>> --- a/drivers/usb/host/ohci-hcd.c
>> +++ b/drivers/usb/host/ohci-hcd.c
>> @@ -1219,11 +1219,6 @@ void ohci_init_driver(struct hc_driver *drv,
>> #define SA1111_DRIVER ohci_hcd_sa1111_driver
>> #endif
>>
>> -#ifdef CONFIG_USB_OHCI_HCD_DAVINCI
>> -#include "ohci-da8xx.c"
>> -#define DAVINCI_PLATFORM_DRIVER ohci_hcd_da8xx_driver
>> -#endif
>> -
>> #ifdef CONFIG_USB_OHCI_HCD_PPC_OF
>> #include "ohci-ppc-of.c"
>> #define OF_PLATFORM_DRIVER ohci_hcd_ppc_of_driver
>> @@ -1303,19 +1298,9 @@ static int __init ohci_hcd_mod_init(void)
>> goto error_tmio;
>> #endif
>>
>> -#ifdef DAVINCI_PLATFORM_DRIVER
>> - retval = platform_driver_register(&DAVINCI_PLATFORM_DRIVER);
>> - if (retval < 0)
>> - goto error_davinci;
>> -#endif
>> -
>> return retval;
>>
>> /* Error path */
>> -#ifdef DAVINCI_PLATFORM_DRIVER
>> - platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER);
>> - error_davinci:
>> -#endif
>> #ifdef TMIO_OHCI_DRIVER
>> platform_driver_unregister(&TMIO_OHCI_DRIVER);
>> error_tmio:
>> @@ -1351,9 +1336,6 @@ static int __init ohci_hcd_mod_init(void)
>>
>> static void __exit ohci_hcd_mod_exit(void)
>> {
>> -#ifdef DAVINCI_PLATFORM_DRIVER
>> - platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER);
>> -#endif
>> #ifdef TMIO_OHCI_DRIVER
>> platform_driver_unregister(&TMIO_OHCI_DRIVER);
>> #endif
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH] ARM: sti: stih410-clocks: Add PROC_STFE as a critical clock
From: Lee Jones @ 2016-10-25 7:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161024134416.GB10440@griffinp-ThinkPad-X1-Carbon-2nd>
On Mon, 24 Oct 2016, Peter Griffin wrote:
> Hi Lee,
>
> On Mon, 24 Oct 2016, Lee Jones wrote:
> > On Tue, 18 Oct 2016, Peter Griffin wrote:
> >
> > > Once the ST frontend demux HW IP has been enabled, the clock can't
> > > be disabled otherwise the system will hang and the board will
> > > be unserviceable.
> > >
> > > To allow balanced clock enable/disable calls in the driver we use
> > > the critical clock infrastructure to take an extra reference on the
> > > clock so the clock will never actually be disabled.
> >
> > This is an abuse of the critical-clocks framework, and is exactly the
> > type of hack I promised the clk guys I'd try to prevent.
>
> I expect the best way to do this would be to write some documentation on the
> clock-critical DT binding and/or CRITICAL_CLK flag. The only documentation I can
> find currently is with the initial patch series [1] and the comment in
> clk-provider.h of
>
> #define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */
>
> Or the patch decription
>
> "Critical clocks are those which must not be gated, else undefined
> or catastrophic failure would occur. Here we have chosen to
> ensure the prepare/enable counts are correctly incremented, so as
> not to confuse users with enabled clocks with no visible users."
>
> Which is the functionality I want for this clock.
No, that's not the functionality you want. You want for the clock not
to be RE-gated (big difference). Currently, the STFE clock will never
be gated, even when a) it's not used and b) can actually be disabled.
You're needlessly wasting power here.
Also, in your use-case there is a visible user, and the prepare/enable
counts will be correct.
> > If this, or
> > any other IP has some quirks (i.e. once enabled, if this clock is
> > subsequently disabled it will have a catastrophic effect on the
> > platform), then they should be worked around in the driver.
> >
> > The correct thing to do here is craft a clk-keep-on flag and ensure it
> > is set to true for the effected platform(s)' platform data.
>
> I'm always wary of creating a driver specific flag, especially when its
> purpose is to do the same thing as an existing mechanism provided by the
> subsystem of not gating the clock.
Using existing sub-system supplied mechanisms in the way they were not
intended is sub-optimal (read "hacky").
> I can see a couple of problems with what you propose:
>
> 1) You have to put the clk-keep-on flag in every driver which consumes the
> clock. IMO it is much better to have this knowledge in the SoC's
> clock driver so every consumer of the clock automatically benefits.
That would also be fine(ish). The issue is that this problem is
board specific, so the platform clock driver would have to contain
board level knowledge. Also, if you were to implement this, it would
too mess up reference counting in the core.
> 2) You don't benefit from the CLK_IS_CRITICAL reference counting logic in
> clk.c. So then each driver has to also work around that to get sensible reference
> counts. e.g.
>
> if (!__clk_is_enabled(clk) && pdata->clk-keep-on)
> clk_enable(clk)
>
> Which seems to me to be fighting against the subsystem. Given that the only use of
> _clk_is_enabled() outside drivers/clk is in an old arch/arm/mach-omap2/pm24xx.c
> driver I suspect its use is frowned upon, and it shouldn't really be an EXPORTED_SYMBOL.
In this instance, since the STFE clock is only used by this IP, I
would choose to handle it in the driver. This can be done using a
single flag stored in pdata which should be fetched using
of_match_device(). This way there is no need for any more API abuse;
either by incorrectly identifying the STFE clock as critical OR
invoking any internal __clk_*() calls.
Enable the clock once in .probe(), which you already do.
Then, whenever you do any power saving do:
suspend()
{
if (!ddata->enable_clk_once)
clk_disable(clk);
}
resume()
{
if (!ddata->enable_clk_once)
clk_enable(clk);
}
However, looking at your driver, I think this point might even be
moot, since you don't have any power saving. The only time you
disable the clock is in the error path. Just replace that with a
comment about the platform's unfortunate errata.
> [1] https://lkml.org/lkml/2016/1/18/272
I'm glad you mentioned this. Let's take a look:
> Some platforms contain clocks which if gated, will cause undefined or
> catastrophic behaviours. As such they are not to be turned off, ever.
Not the case here.
This clock *can* be gated and can be turned off *sometimes*.
> Many of these such clocks do not have devices, thus device drivers
> where clocks may be enabled and references taken to ensure they stay
> enabled do not exist. Therefore, we must handle these such cases in
> the core.
This clock *does* have a driver and correct references *can* be
taken.
[...]
All I'm saying is, and it's the same thing I've said many times; these
types of issues do not exhibit the same set of symptoms as a critical
clock by definition. Critical clocks are those which references can
not be taken by any other means. Think of the critical clock
framework as a mechanism to circumvent the requirement of writing a
special driver which would *only* handle clocks i.e. an interconnect
driver in the ST case.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* [PATCH 3/5] staging/vchi: Fix some pointer math for 64-bit.
From: Greg Kroah-Hartman @ 2016-10-25 7:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161017194406.1080-4-eric@anholt.net>
On Mon, Oct 17, 2016 at 12:44:04PM -0700, Eric Anholt wrote:
> These were throwing warnings on aarch64, and all are trivially
> converted to longs.
>
> Signed-off-by: Eric Anholt <eric@anholt.net>
> ---
> drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 6 +++---
> drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c | 5 +++--
> 2 files changed, 6 insertions(+), 5 deletions(-)
This didnt apply anymore as I think I took the other fixups, sorry.
greg k-h
^ permalink raw reply
* [PATCH/RFT v2 17/17] ARM: dts: da850: add usb device node
From: Axel Haslam @ 2016-10-25 8:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <59ca6a1f-6db9-eed2-8e8a-77657c7febac@lechnology.com>
On Tue, Oct 25, 2016 at 2:48 AM, David Lechner <david@lechnology.com> wrote:
> On 10/24/2016 11:46 AM, ahaslam at baylibre.com wrote:
>>
>> From: Axel Haslam <ahaslam@baylibre.com>
>>
>> This adds the usb (ohci) device node for the da850 soc.
>> Also it enables it for the lcdk board
>>
>> Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
>> ---
>> arch/arm/boot/dts/da850-lcdk.dts | 8 ++++++++
>> arch/arm/boot/dts/da850.dtsi | 8 ++++++++
>> 2 files changed, 16 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/da850-lcdk.dts
>> b/arch/arm/boot/dts/da850-lcdk.dts
>> index 7b8ab21..fa91339 100644
>> --- a/arch/arm/boot/dts/da850-lcdk.dts
>> +++ b/arch/arm/boot/dts/da850-lcdk.dts
>> @@ -86,6 +86,14 @@
>> };
>> };
>>
>> +&usb_phy {
>> + status = "okay";
>> +};
>> +
>> +&usb {
>> + status = "okay";
>
>
> Don't you need to specify a regulator here using the vbus-supply property?
its is not mandatory, the regulator framework is giving a dummy supply
on regulator_get if it does not find a regulator on device tree. That is
what i could understand from: _regulator_get in regulator/core.c
Also, in the case of platform based boot, if the board init calls
regulator_has_full_constraints which is anyways needed for the phy to probe
correctly it will also return a dummy regulator.
>
>> +};
>> +
>> &serial2 {
>> pinctrl-names = "default";
>> pinctrl-0 = <&serial2_rxtx_pins>;
>> diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
>> index 33fcdce..ec2cec3 100644
>> --- a/arch/arm/boot/dts/da850.dtsi
>> +++ b/arch/arm/boot/dts/da850.dtsi
>> @@ -381,6 +381,14 @@
>> #phy-cells = <1>;
>> status = "disabled";
>> };
>> + usb: usb at 0225000 {
>
>
> Don't need the leading 0 on usb at 225000
>
> The alias (usb:) might need to be more specific since there is a second usb
> device that will be added later for musb. (The comments in the previous
> review only referred to the "usb" in "usb@", not the alias.)
ok.
>
>> + compatible = "ti,da830-ohci";
>> + reg = <0x225000 0x1000>;
>> + interrupts = <59>;
>> + phys = <&usb_phy 1>;
>> + phy-names = "usb-phy";
>> + status = "disabled";
>> + };
>> gpio: gpio at 226000 {
>> compatible = "ti,dm6441-gpio";
>> gpio-controller;
>>
>
^ permalink raw reply
* [PATCH v2 1/8] drm/bridge: rgb-to-vga: Support an enable GPIO
From: Archit Taneja @ 2016-10-25 8:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161020034344.14154-2-wens@csie.org>
Hi,
On 10/20/2016 09:13 AM, Chen-Yu Tsai wrote:
> Some rgb-to-vga bridges have an enable GPIO, either directly tied to
> an enable pin on the bridge IC, or indirectly controlling a power
> switch.
>
> Add support for it.
Does the bridge on your platform have an active/passive DAC, or is it a
smarter encoder chip that is capable of doing more? If so, it might be
good to have a separate DT compatible string to it, like what's done
in the patch titled:
drm: bridge: vga-dac: Add adi,adv7123 compatible string
so that we can switch to a different driver later if needed.
Thanks,
Archit
>
> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
> ---
> .../bindings/display/bridge/dumb-vga-dac.txt | 2 ++
> drivers/gpu/drm/bridge/dumb-vga-dac.c | 28 ++++++++++++++++++++++
> 2 files changed, 30 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
> index 003bc246a270..d3484822bf77 100644
> --- a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
> +++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
> @@ -16,6 +16,8 @@ graph bindings specified in Documentation/devicetree/bindings/graph.txt.
> - Video port 0 for RGB input
> - Video port 1 for VGA output
>
> +Optional properties:
> +- enable-gpios: GPIO pin to enable or disable the bridge
>
> Example
> -------
> diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
> index afec232185a7..b487e5e9b56d 100644
> --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
> +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
> @@ -10,6 +10,7 @@
> * the License, or (at your option) any later version.
> */
>
> +#include <linux/gpio/consumer.h>
> #include <linux/module.h>
> #include <linux/of_graph.h>
>
> @@ -23,6 +24,7 @@ struct dumb_vga {
> struct drm_connector connector;
>
> struct i2c_adapter *ddc;
> + struct gpio_desc *enable_gpio;
> };
>
> static inline struct dumb_vga *
> @@ -124,8 +126,26 @@ static int dumb_vga_attach(struct drm_bridge *bridge)
> return 0;
> }
>
> +static void dumb_vga_enable(struct drm_bridge *bridge)
> +{
> + struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
> +
> + if (vga->enable_gpio)
> + gpiod_set_value_cansleep(vga->enable_gpio, 1);
> +}
> +
> +static void dumb_vga_disable(struct drm_bridge *bridge)
> +{
> + struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
> +
> + if (vga->enable_gpio)
> + gpiod_set_value_cansleep(vga->enable_gpio, 0);
> +}
> +
> static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {
> .attach = dumb_vga_attach,
> + .enable = dumb_vga_enable,
> + .disable = dumb_vga_disable,
> };
>
> static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
> @@ -169,6 +189,14 @@ static int dumb_vga_probe(struct platform_device *pdev)
> return -ENOMEM;
> platform_set_drvdata(pdev, vga);
>
> + vga->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
> + GPIOD_OUT_LOW);
> + if (IS_ERR(vga->enable_gpio)) {
> + ret = PTR_ERR(vga->enable_gpio);
> + dev_err(&pdev->dev, "failed to request GPIO: %d\n", ret);
> + return ret;
> + }
> +
> vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev);
> if (IS_ERR(vga->ddc)) {
> if (PTR_ERR(vga->ddc) == -ENODEV) {
>
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* [PATCH/RFT v2 16/17] USB: ohci-da8xx: Allow probing from DT
From: Axel Haslam @ 2016-10-25 8:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a32c58db-d3f8-2a1b-53b3-ae78e342c5e7@lechnology.com>
On Tue, Oct 25, 2016 at 2:53 AM, David Lechner <david@lechnology.com> wrote:
> On 10/24/2016 11:46 AM, ahaslam at baylibre.com wrote:
>>
>> From: Axel Haslam <ahaslam@baylibre.com>
>>
>> This adds the compatible string to the ohci driver
>> to be able to probe from DT
>>
>> Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
>> ---
>> drivers/usb/host/ohci-da8xx.c | 8 ++++++++
>> 1 file changed, 8 insertions(+)
>>
>> diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
>> index bebc3f0..1a8db25 100644
>> --- a/drivers/usb/host/ohci-da8xx.c
>> +++ b/drivers/usb/host/ohci-da8xx.c
>> @@ -273,6 +273,13 @@ static int ohci_da8xx_hub_control(struct usb_hcd
>> *hcd, u16 typeReq, u16 wValue,
>> }
>>
>>
>> /*-------------------------------------------------------------------------*/
>> +#ifdef CONFIG_OF
>
>
> #ifdef CONFIG_OF is probably not needed here...
>
>> +static const struct of_device_id da8xx_ohci_ids[] = {
>> + { .compatible = "ti,da830-ohci" },
>> + { }
>> +};
>> +MODULE_DEVICE_TABLE(of, da8xx_ohci_ids);
>> +#endif
>>
>> static int ohci_da8xx_probe(struct platform_device *pdev)
>> {
>> @@ -421,6 +428,7 @@ static int ohci_da8xx_resume(struct platform_device
>> *dev)
>> #endif
>> .driver = {
>> .name = "ohci",
>> + .of_match_table = da8xx_ohci_ids,
>
>
> ...otherwise, da8xx_ohci_ids will not be defined here
this should be .of_match_table = of_match_ptr(da8xx_ohci_ids),
will fix.
>
>> },
>> };
>>
>>
>
^ permalink raw reply
* [PATCH/RFT v2 02/17] ARM: davinci: da8xx: Add CFGCHIP syscon platform declaration.
From: Sekhar Nori @ 2016-10-25 8:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161024164634.4330-3-ahaslam@baylibre.com>
On Monday 24 October 2016 10:16 PM, ahaslam at baylibre.com wrote:
> From: David Lechner <david@lechnology.com>
>
> The CFGCHIP registers are used by a number of devices, so using a syscon
> device to share them. The first consumer of this will by the phy-da8xx-usb
> driver.
>
> Signed-off-by: David Lechner <david@lechnology.com>
> [Axel: minor fix: change id to -1]
Can you please clarify this change? There could be other syscon devices
on the chip for other common registers. Why use the singular device-id?
> Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
Thanks,
Sekhar
^ permalink raw reply
* [PATCH v2 8/8] ARM: dts: sun6i: hummingbird-a31: Enable display output through VGA bridge
From: Archit Taneja @ 2016-10-25 8:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161020034344.14154-9-wens@csie.org>
On 10/20/2016 09:13 AM, Chen-Yu Tsai wrote:
> The Hummingbird A31 board has a RGB-to-VGA bridge which converts RGB
> output from the LCD interface to VGA signals.
>
> Enable this part of the display pipeline.
I couldn't find the enable-gpios binding for the bridge that you
introduced in the previous patch. Is that intentional?
Thanks,
Archit
>
> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
> ---
> arch/arm/boot/dts/sun6i-a31-hummingbird.dts | 56 +++++++++++++++++++++++++++++
> 1 file changed, 56 insertions(+)
>
> diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
> index 9a74637f677f..05a49b2147f1 100644
> --- a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
> +++ b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
> @@ -63,6 +63,49 @@
> stdout-path = "serial0:115200n8";
> };
>
> + bridge {
> + compatible = "dumb-vga-dac";
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + port at 0 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0>;
> +
> + vga_bridge_in: endpoint at 0 {
> + reg = <0>;
> + remote-endpoint = <&tcon0_out_vga>;
> + };
> + };
> +
> + port at 1 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <1>;
> +
> + vga_bridge_out: endpoint at 0 {
> + reg = <0>;
> + remote-endpoint = <&vga_con_in>;
> + };
> + };
> + };
> + };
> +
> + vga {
> + compatible = "vga-connector";
> +
> + port {
> + vga_con_in: endpoint {
> + remote-endpoint = <&vga_bridge_out>;
> + };
> + };
> + };
> +
> wifi_pwrseq: wifi_pwrseq {
> compatible = "mmc-pwrseq-simple";
> reset-gpios = <&pio 6 10 GPIO_ACTIVE_LOW>; /* PG10 */
> @@ -245,6 +288,19 @@
> status = "okay";
> };
>
> +&tcon0 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&lcd0_rgb888_pins>;
> + status = "okay";
> +};
> +
> +&tcon0_out {
> + tcon0_out_vga: endpoint at 0 {
> + reg = <0>;
> + remote-endpoint = <&vga_bridge_in>;
> + };
> +};
> +
> &uart0 {
> pinctrl-names = "default";
> pinctrl-0 = <&uart0_pins_a>;
>
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* [PATCH/RFT v2 12/17] USB: ochi-da8xx: Use a regulator for vbus/overcurrent
From: Axel Haslam @ 2016-10-25 8:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <672c1f1a-58b7-6947-7fb2-acd38fab8597@lechnology.com>
On Tue, Oct 25, 2016 at 3:39 AM, David Lechner <david@lechnology.com> wrote:
> On 10/24/2016 11:46 AM, ahaslam at baylibre.com wrote:
>>
>> From: Axel Haslam <ahaslam@baylibre.com>
>>
>> Currently, the da8xx ohci driver uses a set of gpios and callbacks in
>> board files to handle vbus and overcurrent irqs form the power supply.
>> However, this does not play nice when moving to a DT based boot were
>> we wont have board files.
>>
>> Instead of requesting and handling the gpio, use the regulator framework
>> to take care of enabling and disabling vbus power.
>> This has the benefit
>> that we dont need to pass any more platform data to the driver:
>>
>> These will be handled by the regulator framework:
>> set_power -> regulator_enable/regulator_disable
>> get_power -> regulator_is_enabled
>> get_oci -> regulator_get_mode
>> ocic_notify -> regulator notification
>>
>> We can keep the default potpgt and use the regulator start delay instead:
>> potpgt -> regulator startup delay time
>>
>> The hawk board does not have a GPIO/OVERCURRENT gpio to control vbus,
>> (they should not have been decleared/reserved) so, just remove those
>> definitions from the hwk board file.
>>
>> Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
>> ---
>
>
>
> How do you recover after an overcurrent event?
>
> I have configured a fixed-regulator using device-tree, but similar to the
> configuration in the board files here. However, when I shorted out the VBUS
> and caused an overcurrent event, I see nothing in the kernel log saying that
> there was an overcurrent event and after I remove the short, the regulator
> is never turned back on.
>
>
You should have the patch to fix gpiolib, and you should declare the
over current gpio on the regulator as such:
(if the pin is enabled high you should add oc-active-high);
vbus_fixed: fixed-regulator-vbus {
compatible = "regulator-fixed";
gpio = <&gpio 109 0>;
oc-gpio = <&gpio 36 0>;
regulator-boot-on;
enable-active-high;
regulator-name = "vbus";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
};
Question: Do you see that the over current gpio was requested
in debugfs/gpio? and, do you see the interrupt in /proc/interrupts?
If you unplug and plug in back the usb device it should work again.
also you can unbind and bind it should also start to work:
something like:
echo usb1 >/sys/bus/usb/drivers/usb/unbind
echo usb1 >/sys/bus/usb/drivers/usb/bind
>
>> @@ -163,7 +198,6 @@ static int ohci_da8xx_hub_control(struct usb_hcd *hcd,
>> u16 typeReq, u16 wValue,
>> u16 wIndex, char *buf, u16 wLength)
>> {
>> struct device *dev = hcd->self.controller;
>> - struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
>
>
> nit: unnecessary whitespace change
>
>> int temp;
>>
>> switch (typeReq) {
>
>
^ permalink raw reply
* Disabling an interrupt in the handler locks the system up
From: Sebastian Frias @ 2016-10-25 8:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.20.1610241847580.5002@nanos>
Hi Thomas,
On 10/24/2016 06:55 PM, Thomas Gleixner wrote:
> On Mon, 24 Oct 2016, Mason wrote:
>>
>> For the record, setting the IRQ_DISABLE_UNLAZY flag for this device
>> makes the system lock-up disappear.
>
> The way how lazy irq disabling works is:
>
> 1) Interrupt is marked disabled in software, but the hardware is not masked
>
> 2) If the interrupt fires befor the interrupt is reenabled, then it's
> masked at the hardware level in the low level interrupt flow handler.
>
Would you mind explaining what is the intention behind?
Because it does not seem obvious why there isn't a direct map between
"disable_irq*()" and "mask_irq()"
Thanks in advance.
Best regards,
Sebastian
^ permalink raw reply
* Disabling an interrupt in the handler locks the system up
From: Mason @ 2016-10-25 8:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <580F17E7.5060603@laposte.net>
On 25/10/2016 10:29, Sebastian Frias wrote:
> On 10/24/2016 06:55 PM, Thomas Gleixner wrote:
>
>> On Mon, 24 Oct 2016, Mason wrote:
>>
>>> For the record, setting the IRQ_DISABLE_UNLAZY flag for this device
>>> makes the system lock-up disappear.
>>
>> The way how lazy irq disabling works is:
>>
>> 1) Interrupt is marked disabled in software, but the hardware is not masked
>>
>> 2) If the interrupt fires befor the interrupt is reenabled, then it's
>> masked at the hardware level in the low level interrupt flow handler.
>
> Would you mind explaining what is the intention behind?
> Because it does not seem obvious why there isn't a direct map between
> "disable_irq*()" and "mask_irq()"
I had a similar, but slightly different question:
What is the difference between struct irq_chip's
* @irq_shutdown: shut down the interrupt (defaults to ->disable if NULL)
* @irq_disable: disable the interrupt
* @irq_mask: mask an interrupt source
(enable seems to default to unmask, but disable does not default to mask)
Regards.
^ permalink raw reply
* [PATCH v2] char: hw_random: atmel-rng: disable TRNG during suspend
From: Nicolas Ferre @ 2016-10-25 8:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477356993-27778-1-git-send-email-wenyou.yang@atmel.com>
Le 25/10/2016 ? 02:56, Wenyou Yang a ?crit :
> To fix the over consumption on the VDDCore due to the TRNG enabled,
> disable the TRNG during suspend, not only disable the user interface
> clock (which is controlled by PMC). Because the user interface clock
> is independent from any clock that may be used in the entropy source
> logic circuitry.
>
> Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Thanks
> ---
>
> Changes in v2:
> - Enable the user interface first, then enable the internal clock
> when resume.
>
> drivers/char/hw_random/atmel-rng.c | 24 +++++++++++++++++++++---
> 1 file changed, 21 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c
> index 0fcc9e6..ae7cae5 100644
> --- a/drivers/char/hw_random/atmel-rng.c
> +++ b/drivers/char/hw_random/atmel-rng.c
> @@ -48,6 +48,16 @@ static int atmel_trng_read(struct hwrng *rng, void *buf, size_t max,
> return 0;
> }
>
> +static void atmel_trng_enable(struct atmel_trng *trng)
> +{
> + writel(TRNG_KEY | 1, trng->base + TRNG_CR);
> +}
> +
> +static void atmel_trng_disable(struct atmel_trng *trng)
> +{
> + writel(TRNG_KEY, trng->base + TRNG_CR);
> +}
> +
> static int atmel_trng_probe(struct platform_device *pdev)
> {
> struct atmel_trng *trng;
> @@ -71,7 +81,7 @@ static int atmel_trng_probe(struct platform_device *pdev)
> if (ret)
> return ret;
>
> - writel(TRNG_KEY | 1, trng->base + TRNG_CR);
> + atmel_trng_enable(trng);
> trng->rng.name = pdev->name;
> trng->rng.read = atmel_trng_read;
>
> @@ -94,7 +104,7 @@ static int atmel_trng_remove(struct platform_device *pdev)
>
> hwrng_unregister(&trng->rng);
>
> - writel(TRNG_KEY, trng->base + TRNG_CR);
> + atmel_trng_disable(trng);
> clk_disable_unprepare(trng->clk);
>
> return 0;
> @@ -105,6 +115,7 @@ static int atmel_trng_suspend(struct device *dev)
> {
> struct atmel_trng *trng = dev_get_drvdata(dev);
>
> + atmel_trng_disable(trng);
> clk_disable_unprepare(trng->clk);
>
> return 0;
> @@ -113,8 +124,15 @@ static int atmel_trng_suspend(struct device *dev)
> static int atmel_trng_resume(struct device *dev)
> {
> struct atmel_trng *trng = dev_get_drvdata(dev);
> + int ret;
> +
> + ret = clk_prepare_enable(trng->clk);
> + if (ret)
> + return ret;
>
> - return clk_prepare_enable(trng->clk);
> + atmel_trng_enable(trng);
> +
> + return 0;
> }
>
> static const struct dev_pm_ops atmel_trng_pm_ops = {
>
--
Nicolas Ferre
^ permalink raw reply
* [PATCH v2 8/8] ARM: dts: sun6i: hummingbird-a31: Enable display output through VGA bridge
From: Chen-Yu Tsai @ 2016-10-25 8:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <bac9a59f-df97-245b-f349-bed57dec6aad@codeaurora.org>
On Tue, Oct 25, 2016 at 4:13 PM, Archit Taneja <architt@codeaurora.org> wrote:
>
>
> On 10/20/2016 09:13 AM, Chen-Yu Tsai wrote:
>>
>> The Hummingbird A31 board has a RGB-to-VGA bridge which converts RGB
>> output from the LCD interface to VGA signals.
>>
>> Enable this part of the display pipeline.
>
>
> I couldn't find the enable-gpios binding for the bridge that you
> introduced in the previous patch. Is that intentional?
Error on my part. Thanks for spotting that.
ChenYu
>
> Thanks,
> Archit
>
>
>>
>> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
>> ---
>> arch/arm/boot/dts/sun6i-a31-hummingbird.dts | 56
>> +++++++++++++++++++++++++++++
>> 1 file changed, 56 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
>> b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
>> index 9a74637f677f..05a49b2147f1 100644
>> --- a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
>> +++ b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
>> @@ -63,6 +63,49 @@
>> stdout-path = "serial0:115200n8";
>> };
>>
>> + bridge {
>> + compatible = "dumb-vga-dac";
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> +
>> + ports {
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> +
>> + port at 0 {
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> + reg = <0>;
>> +
>> + vga_bridge_in: endpoint at 0 {
>> + reg = <0>;
>> + remote-endpoint =
>> <&tcon0_out_vga>;
>> + };
>> + };
>> +
>> + port at 1 {
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> + reg = <1>;
>> +
>> + vga_bridge_out: endpoint at 0 {
>> + reg = <0>;
>> + remote-endpoint = <&vga_con_in>;
>> + };
>> + };
>> + };
>> + };
>> +
>> + vga {
>> + compatible = "vga-connector";
>> +
>> + port {
>> + vga_con_in: endpoint {
>> + remote-endpoint = <&vga_bridge_out>;
>> + };
>> + };
>> + };
>> +
>> wifi_pwrseq: wifi_pwrseq {
>> compatible = "mmc-pwrseq-simple";
>> reset-gpios = <&pio 6 10 GPIO_ACTIVE_LOW>; /* PG10 */
>> @@ -245,6 +288,19 @@
>> status = "okay";
>> };
>>
>> +&tcon0 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&lcd0_rgb888_pins>;
>> + status = "okay";
>> +};
>> +
>> +&tcon0_out {
>> + tcon0_out_vga: endpoint at 0 {
>> + reg = <0>;
>> + remote-endpoint = <&vga_bridge_in>;
>> + };
>> +};
>> +
>> &uart0 {
>> pinctrl-names = "default";
>> pinctrl-0 = <&uart0_pins_a>;
>>
>
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
^ permalink raw reply
* [PATCH v3 0/5] Add runtime PM support for clocks (on Exynos SoC example)
From: Marek Szyprowski @ 2016-10-25 8:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477311130-6534-1-git-send-email-m.szyprowski@samsung.com>
Dear All,
On 2016-10-24 14:12, Marek Szyprowski wrote:
> This patchset adds runtime PM support to common clock framework. This is an
> attempt to implement support for clock controllers, which belongs to a power
> domain. This approach works surprisingly well on Exynos 4412 and 5433 SoCs,
> what allowed us to solve various freeze/crash issues related to power
> management.
>
> The main idea behind this patchset is to keep clock's controller power domain
> enabled every time when at least one of its clock is enabled or access to its
> registers is being made. Clock controller driver (clock provider) can
> supply a struct device pointer, which is the used by clock core for tracking and
> managing clock's controller runtime pm state. Each clk_prepare() operation will
> first call pm_runtime_get_sync() on the supplied device, while clk_unprepare()
> will do pm_runtime_put() at the end.
>
> This runtime PM feature has been tested with Exynos4412 and Exynos5433 clocks
> drivers. Both have some clocks, which belongs to respective power domains and
> need special handling during power on/off procedures. Till now it wasn't handled
> at all, what caused various problems.
>
> Patches for exynos 4412 and 5433 clocks drivers change the way the clock
> provider is initialized. Instead of CLK_OF_DECLARE based initialization, a
> complete platform device driver infrastructure is being used. This is needed to
> let driver to use runtime pm feature and integrate with generic power domains.
> The side-effect of this change is a delay in clock provider registeration
> during system boot, so early initialized drivers might get EPROBEDEFER error
> when requesting their clocks. This is an issue for IOMMU drivers, so
> this patchset will be fully functional once the deferred probe for IOMMU
> will be merged.
>
> The side-effect of this patchset is the one can finally read
> /sys/kernel/debug/clk/clk_summary on all Exynos4412 boards without any freeze.
>
> If one wants to test this patchset (on Exynos4412 Trats2 device with FIMC-IS
> driver), I've provided a branch with all needed patches (fixes for Exynos,
> FIMC-IS driver and IOMMU deferred probe):
> https://git.linaro.org/people/marek.szyprowski/linux-srpol.git v4.9-clocks-pm-v3
>
> Patches are based on vanilla v4.9-rc1 kernel.
If one want to test this patchset together with my recently posted
Exynos IOMMU
runtime PM patches (V5:
http://www.mail-archive.com/linux-kernel at vger.kernel.org/msg1253432.html),
I prepared a single branch with both patchsets and all their prerequisites:
https://git.linaro.org/people/marek.szyprowski/linux-srpol.git v4.9-iommu-pm-v5-clocks-pm-v3
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply
* [PATCH v2 1/8] drm/bridge: rgb-to-vga: Support an enable GPIO
From: Chen-Yu Tsai @ 2016-10-25 8:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <0b5fbe8e-e51b-c874-e1a3-0b88dc65e361@codeaurora.org>
On Tue, Oct 25, 2016 at 4:09 PM, Archit Taneja <architt@codeaurora.org> wrote:
> Hi,
>
> On 10/20/2016 09:13 AM, Chen-Yu Tsai wrote:
>>
>> Some rgb-to-vga bridges have an enable GPIO, either directly tied to
>> an enable pin on the bridge IC, or indirectly controlling a power
>> switch.
>>
>> Add support for it.
>
>
> Does the bridge on your platform have an active/passive DAC, or is it a
> smarter encoder chip that is capable of doing more? If so, it might be
> good to have a separate DT compatible string to it, like what's done
> in the patch titled:
>
> drm: bridge: vga-dac: Add adi,adv7123 compatible string
>
> so that we can switch to a different driver later if needed.
The chip is GM7123. It is not configurable. It just takes the LCD RGB/SYNC
signals and converts them to analog. The only things you can change are
putting it into sleep mode and tweaking the output drive strength by
changing the external reference resistor. The latter would be a hardware
design decision. I would say this qualifies as "dumb".
I revisited the board schematics, and the enable GPIO actually toggles
an external LDO regulator. So this might be better modeled as a regulator
supply?
Thanks
ChenYu
>
> Thanks,
> Archit
>
>
>>
>> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
>> ---
>> .../bindings/display/bridge/dumb-vga-dac.txt | 2 ++
>> drivers/gpu/drm/bridge/dumb-vga-dac.c | 28
>> ++++++++++++++++++++++
>> 2 files changed, 30 insertions(+)
>>
>> diff --git
>> a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>> b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>> index 003bc246a270..d3484822bf77 100644
>> --- a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>> +++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>> @@ -16,6 +16,8 @@ graph bindings specified in
>> Documentation/devicetree/bindings/graph.txt.
>> - Video port 0 for RGB input
>> - Video port 1 for VGA output
>>
>> +Optional properties:
>> +- enable-gpios: GPIO pin to enable or disable the bridge
>>
>> Example
>> -------
>> diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c
>> b/drivers/gpu/drm/bridge/dumb-vga-dac.c
>> index afec232185a7..b487e5e9b56d 100644
>> --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
>> +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
>> @@ -10,6 +10,7 @@
>> * the License, or (at your option) any later version.
>> */
>>
>> +#include <linux/gpio/consumer.h>
>> #include <linux/module.h>
>> #include <linux/of_graph.h>
>>
>> @@ -23,6 +24,7 @@ struct dumb_vga {
>> struct drm_connector connector;
>>
>> struct i2c_adapter *ddc;
>> + struct gpio_desc *enable_gpio;
>> };
>>
>> static inline struct dumb_vga *
>> @@ -124,8 +126,26 @@ static int dumb_vga_attach(struct drm_bridge *bridge)
>> return 0;
>> }
>>
>> +static void dumb_vga_enable(struct drm_bridge *bridge)
>> +{
>> + struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
>> +
>> + if (vga->enable_gpio)
>> + gpiod_set_value_cansleep(vga->enable_gpio, 1);
>> +}
>> +
>> +static void dumb_vga_disable(struct drm_bridge *bridge)
>> +{
>> + struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
>> +
>> + if (vga->enable_gpio)
>> + gpiod_set_value_cansleep(vga->enable_gpio, 0);
>> +}
>> +
>> static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {
>> .attach = dumb_vga_attach,
>> + .enable = dumb_vga_enable,
>> + .disable = dumb_vga_disable,
>> };
>>
>> static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
>> @@ -169,6 +189,14 @@ static int dumb_vga_probe(struct platform_device
>> *pdev)
>> return -ENOMEM;
>> platform_set_drvdata(pdev, vga);
>>
>> + vga->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
>> + GPIOD_OUT_LOW);
>> + if (IS_ERR(vga->enable_gpio)) {
>> + ret = PTR_ERR(vga->enable_gpio);
>> + dev_err(&pdev->dev, "failed to request GPIO: %d\n", ret);
>> + return ret;
>> + }
>> +
>> vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev);
>> if (IS_ERR(vga->ddc)) {
>> if (PTR_ERR(vga->ddc) == -ENODEV) {
>>
>
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
^ permalink raw reply
* [PATCH 1/3 v2] mmc: mmci: clean up header defines
From: Linus Walleij @ 2016-10-25 9:06 UTC (permalink / raw)
To: linux-arm-kernel
There was some confusion in the CPSM (Command Path State Machine)
and DPSM (Data Path State Machine) regarding the naming of the
registers, clarify the meaning of this acronym so the naming is
understandable, and consistently use BIT() to define these fields.
Consequently name the register bit defines MCI_[C|D]PSM_* and
adjust the driver as well.
Include new definitions for a few bits found in a patch from
Srinivas Kandagatla.
Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v1->v2:
- Use more consequent register naming.
---
drivers/mmc/host/mmci.c | 16 ++++++------
drivers/mmc/host/mmci.h | 69 +++++++++++++++++++++++++++----------------------
2 files changed, 46 insertions(+), 39 deletions(-)
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index df990bb8c873..6a8ea9c633d4 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -137,7 +137,7 @@ static struct variant_data variant_u300 = {
.clkreg_enable = MCI_ST_U300_HWFCEN,
.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
.datalength_bits = 16,
- .datactrl_mask_sdio = MCI_ST_DPSM_SDIOEN,
+ .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.st_sdio = true,
.pwrreg_powerup = MCI_PWR_ON,
.f_max = 100000000,
@@ -152,7 +152,7 @@ static struct variant_data variant_nomadik = {
.clkreg = MCI_CLK_ENABLE,
.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
.datalength_bits = 24,
- .datactrl_mask_sdio = MCI_ST_DPSM_SDIOEN,
+ .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.st_sdio = true,
.st_clkdiv = true,
.pwrreg_powerup = MCI_PWR_ON,
@@ -170,7 +170,7 @@ static struct variant_data variant_ux500 = {
.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
.clkreg_neg_edge_enable = MCI_ST_UX500_NEG_EDGE,
.datalength_bits = 24,
- .datactrl_mask_sdio = MCI_ST_DPSM_SDIOEN,
+ .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.st_sdio = true,
.st_clkdiv = true,
.pwrreg_powerup = MCI_PWR_ON,
@@ -188,9 +188,9 @@ static struct variant_data variant_ux500v2 = {
.clkreg_enable = MCI_ST_UX500_HWFCEN,
.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
.clkreg_neg_edge_enable = MCI_ST_UX500_NEG_EDGE,
- .datactrl_mask_ddrmode = MCI_ST_DPSM_DDRMODE,
+ .datactrl_mask_ddrmode = MCI_DPSM_ST_DDRMODE,
.datalength_bits = 24,
- .datactrl_mask_sdio = MCI_ST_DPSM_SDIOEN,
+ .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.st_sdio = true,
.st_clkdiv = true,
.blksz_datactrl16 = true,
@@ -210,7 +210,7 @@ static struct variant_data variant_qcom = {
MCI_QCOM_CLK_SELECT_IN_FBCLK,
.clkreg_8bit_bus_enable = MCI_QCOM_CLK_WIDEBUS_8,
.datactrl_mask_ddrmode = MCI_QCOM_CLK_SELECT_IN_DDR_MODE,
- .data_cmd_enable = MCI_QCOM_CSPM_DATCMD,
+ .data_cmd_enable = MCI_CPSM_QCOM_DATCMD,
.blksz_datactrl4 = true,
.datalength_bits = 24,
.pwrreg_powerup = MCI_PWR_UP,
@@ -295,7 +295,7 @@ static void mmci_write_pwrreg(struct mmci_host *host, u32 pwr)
static void mmci_write_datactrlreg(struct mmci_host *host, u32 datactrl)
{
/* Keep ST Micro busy mode if enabled */
- datactrl |= host->datactrl_reg & MCI_ST_DPSM_BUSYMODE;
+ datactrl |= host->datactrl_reg & MCI_DPSM_ST_BUSYMODE;
if (host->datactrl_reg != datactrl) {
host->datactrl_reg = datactrl;
@@ -1614,7 +1614,7 @@ static int mmci_probe(struct amba_device *dev,
if (variant->busy_detect) {
mmci_ops.card_busy = mmci_card_busy;
- mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE);
+ mmci_write_datactrlreg(host, MCI_DPSM_ST_BUSYMODE);
mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
mmc->max_busy_timeout = 0;
}
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index a1f5e4f49e2a..7cabf270050b 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -51,25 +51,27 @@
#define MCI_QCOM_CLK_SELECT_IN_DDR_MODE (BIT(14) | BIT(15))
#define MMCIARGUMENT 0x008
-#define MMCICOMMAND 0x00c
-#define MCI_CPSM_RESPONSE (1 << 6)
-#define MCI_CPSM_LONGRSP (1 << 7)
-#define MCI_CPSM_INTERRUPT (1 << 8)
-#define MCI_CPSM_PENDING (1 << 9)
-#define MCI_CPSM_ENABLE (1 << 10)
-/* Argument flag extenstions in the ST Micro versions */
-#define MCI_ST_SDIO_SUSP (1 << 11)
-#define MCI_ST_ENCMD_COMPL (1 << 12)
-#define MCI_ST_NIEN (1 << 13)
-#define MCI_ST_CE_ATACMD (1 << 14)
-/* Modified on Qualcomm Integrations */
-#define MCI_QCOM_CSPM_DATCMD BIT(12)
-#define MCI_QCOM_CSPM_MCIABORT BIT(13)
-#define MCI_QCOM_CSPM_CCSENABLE BIT(14)
-#define MCI_QCOM_CSPM_CCSDISABLE BIT(15)
-#define MCI_QCOM_CSPM_AUTO_CMD19 BIT(16)
-#define MCI_QCOM_CSPM_AUTO_CMD21 BIT(21)
+/* The command register controls the Command Path State Machine (CPSM) */
+#define MMCICOMMAND 0x00c
+#define MCI_CPSM_RESPONSE BIT(6)
+#define MCI_CPSM_LONGRSP BIT(7)
+#define MCI_CPSM_INTERRUPT BIT(8)
+#define MCI_CPSM_PENDING BIT(9)
+#define MCI_CPSM_ENABLE BIT(10)
+/* Command register flag extenstions in the ST Micro versions */
+#define MCI_CPSM_ST_SDIO_SUSP BIT(11)
+#define MCI_CPSM_ST_ENCMD_COMPL BIT(12)
+#define MCI_CPSM_ST_NIEN BIT(13)
+#define MCI_CPSM_ST_CE_ATACMD BIT(14)
+/* Command register flag extensions in the Qualcomm versions */
+#define MCI_CPSM_QCOM_PROGENA BIT(11)
+#define MCI_CPSM_QCOM_DATCMD BIT(12)
+#define MCI_CPSM_QCOM_MCIABORT BIT(13)
+#define MCI_CPSM_QCOM_CCSENABLE BIT(14)
+#define MCI_CPSM_QCOM_CCSDISABLE BIT(15)
+#define MCI_CPSM_QCOM_AUTO_CMD19 BIT(16)
+#define MCI_CPSM_QCOM_AUTO_CMD21 BIT(21)
#define MMCIRESPCMD 0x010
#define MMCIRESPONSE0 0x014
@@ -78,22 +80,27 @@
#define MMCIRESPONSE3 0x020
#define MMCIDATATIMER 0x024
#define MMCIDATALENGTH 0x028
+
+/* The data control register controls the Data Path State Machine (DPSM) */
#define MMCIDATACTRL 0x02c
-#define MCI_DPSM_ENABLE (1 << 0)
-#define MCI_DPSM_DIRECTION (1 << 1)
-#define MCI_DPSM_MODE (1 << 2)
-#define MCI_DPSM_DMAENABLE (1 << 3)
-#define MCI_DPSM_BLOCKSIZE (1 << 4)
+#define MCI_DPSM_ENABLE BIT(0)
+#define MCI_DPSM_DIRECTION BIT(1)
+#define MCI_DPSM_MODE BIT(2)
+#define MCI_DPSM_DMAENABLE BIT(3)
+#define MCI_DPSM_BLOCKSIZE BIT(4)
/* Control register extensions in the ST Micro U300 and Ux500 versions */
-#define MCI_ST_DPSM_RWSTART (1 << 8)
-#define MCI_ST_DPSM_RWSTOP (1 << 9)
-#define MCI_ST_DPSM_RWMOD (1 << 10)
-#define MCI_ST_DPSM_SDIOEN (1 << 11)
+#define MCI_DPSM_ST_RWSTART BIT(8)
+#define MCI_DPSM_ST_RWSTOP BIT(9)
+#define MCI_DPSM_ST_RWMOD BIT(10)
+#define MCI_DPSM_ST_SDIOEN BIT(11)
/* Control register extensions in the ST Micro Ux500 versions */
-#define MCI_ST_DPSM_DMAREQCTL (1 << 12)
-#define MCI_ST_DPSM_DBOOTMODEEN (1 << 13)
-#define MCI_ST_DPSM_BUSYMODE (1 << 14)
-#define MCI_ST_DPSM_DDRMODE (1 << 15)
+#define MCI_DPSM_ST_DMAREQCTL BIT(12)
+#define MCI_DPSM_ST_DBOOTMODEEN BIT(13)
+#define MCI_DPSM_ST_BUSYMODE BIT(14)
+#define MCI_DPSM_ST_DDRMODE BIT(15)
+/* Control register extensions in the Qualcomm versions */
+#define MCI_DPSM_QCOM_DATA_PEND BIT(17)
+#define MCI_DPSM_QCOM_RX_DATA_PEND BIT(20)
#define MMCIDATACNT 0x030
#define MMCISTATUS 0x034
--
2.7.4
^ permalink raw reply related
* [PATCH 2/3 v2] mmc: mmci: refactor ST Micro busy detection
From: Linus Walleij @ 2016-10-25 9:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477386367-18514-1-git-send-email-linus.walleij@linaro.org>
The ST Micro-specific busy detection was made after the assumption
that only this variant supports busy detection. So when doing busy
detection, the host immediately tries to use some ST-specific
register bits.
Since the qualcomm variant also supports some busy detection
schemes, encapsulate the variant flags better in the variant struct
and prepare to add more variants by just providing some bitmasks
to the logic.
Put the entire busy detection logic within an if()-clause in the
mmci_cmd_irq() function so the code is only executed when busy
detection is enabled, and so that it is kept in (almost) one
place, and add comments describing what is going on so the
code can be understood.
Tested on the Ux500 by introducing some prints in the busy
detection path and noticing how the IRQ is enabled, used and
disabled successfully.
Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v1->v2:
- Rebase on new register naming.
---
drivers/mmc/host/mmci.c | 113 +++++++++++++++++++++++++++++++++++-------------
drivers/mmc/host/mmci.h | 2 +-
2 files changed, 85 insertions(+), 30 deletions(-)
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 6a8ea9c633d4..7f68fa7a961e 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -71,7 +71,12 @@ static unsigned int fmax = 515633;
* @f_max: maximum clk frequency supported by the controller.
* @signal_direction: input/out direction of bus signals can be indicated
* @pwrreg_clkgate: MMCIPOWER register must be used to gate the clock
- * @busy_detect: true if busy detection on dat0 is supported
+ * @busy_detect: true if the variant supports busy detection on DAT0.
+ * @busy_dpsm_flag: bitmask enabling busy detection in the DPSM
+ * @busy_detect_flag: bitmask identifying the bit in the MMCISTATUS register
+ * indicating that the card is busy
+ * @busy_detect_mask: bitmask identifying the bit in the MMCIMASK0 to mask for
+ * getting busy end detection interrupts
* @pwrreg_nopower: bits in MMCIPOWER don't controls ext. power supply
* @explicit_mclk_control: enable explicit mclk control in driver.
* @qcom_fifo: enables qcom specific fifo pio read logic.
@@ -98,6 +103,9 @@ struct variant_data {
bool signal_direction;
bool pwrreg_clkgate;
bool busy_detect;
+ u32 busy_dpsm_flag;
+ u32 busy_detect_flag;
+ u32 busy_detect_mask;
bool pwrreg_nopower;
bool explicit_mclk_control;
bool qcom_fifo;
@@ -178,6 +186,9 @@ static struct variant_data variant_ux500 = {
.signal_direction = true,
.pwrreg_clkgate = true,
.busy_detect = true,
+ .busy_dpsm_flag = MCI_DPSM_ST_BUSYMODE,
+ .busy_detect_flag = MCI_ST_CARDBUSY,
+ .busy_detect_mask = MCI_ST_BUSYENDMASK,
.pwrreg_nopower = true,
};
@@ -199,6 +210,9 @@ static struct variant_data variant_ux500v2 = {
.signal_direction = true,
.pwrreg_clkgate = true,
.busy_detect = true,
+ .busy_dpsm_flag = MCI_DPSM_ST_BUSYMODE,
+ .busy_detect_flag = MCI_ST_CARDBUSY,
+ .busy_detect_mask = MCI_ST_BUSYENDMASK,
.pwrreg_nopower = true,
};
@@ -220,6 +234,7 @@ static struct variant_data variant_qcom = {
.qcom_dml = true,
};
+/* Busy detection for the ST Micro variant */
static int mmci_card_busy(struct mmc_host *mmc)
{
struct mmci_host *host = mmc_priv(mmc);
@@ -227,7 +242,7 @@ static int mmci_card_busy(struct mmc_host *mmc)
int busy = 0;
spin_lock_irqsave(&host->lock, flags);
- if (readl(host->base + MMCISTATUS) & MCI_ST_CARDBUSY)
+ if (readl(host->base + MMCISTATUS) & host->variant->busy_detect_flag)
busy = 1;
spin_unlock_irqrestore(&host->lock, flags);
@@ -294,8 +309,8 @@ static void mmci_write_pwrreg(struct mmci_host *host, u32 pwr)
*/
static void mmci_write_datactrlreg(struct mmci_host *host, u32 datactrl)
{
- /* Keep ST Micro busy mode if enabled */
- datactrl |= host->datactrl_reg & MCI_DPSM_ST_BUSYMODE;
+ /* Keep busy mode in DPSM if enabled */
+ datactrl |= host->datactrl_reg & host->variant->busy_dpsm_flag;
if (host->datactrl_reg != datactrl) {
host->datactrl_reg = datactrl;
@@ -973,37 +988,66 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
unsigned int status)
{
void __iomem *base = host->base;
- bool sbc, busy_resp;
+ bool sbc;
if (!cmd)
return;
sbc = (cmd == host->mrq->sbc);
- busy_resp = host->variant->busy_detect && (cmd->flags & MMC_RSP_BUSY);
- if (!((status|host->busy_status) & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|
- MCI_CMDSENT|MCI_CMDRESPEND)))
+ /*
+ * We need to be one of these interrupts to be considered worth
+ * handling. Note that we tag on any latent IRQs postponed
+ * due to waiting for busy status.
+ */
+ if (!((status|host->busy_status) &
+ (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND)))
return;
- /* Check if we need to wait for busy completion. */
- if (host->busy_status && (status & MCI_ST_CARDBUSY))
- return;
+ /*
+ * ST Micro variant: handle busy detection.
+ */
+ if (host->variant->busy_detect) {
+ bool busy_resp = !!(cmd->flags & MMC_RSP_BUSY);
- /* Enable busy completion if needed and supported. */
- if (!host->busy_status && busy_resp &&
- !(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) &&
- (readl(base + MMCISTATUS) & MCI_ST_CARDBUSY)) {
- writel(readl(base + MMCIMASK0) | MCI_ST_BUSYEND,
- base + MMCIMASK0);
- host->busy_status = status & (MCI_CMDSENT|MCI_CMDRESPEND);
- return;
- }
+ /* We are busy with a command, return */
+ if (host->busy_status &&
+ (status & host->variant->busy_detect_flag))
+ return;
+
+ /*
+ * We were not busy, but we now got a busy response on
+ * something that was not an error, and we double-check
+ * that the special busy status bit is still set before
+ * proceeding.
+ */
+ if (!host->busy_status && busy_resp &&
+ !(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) &&
+ (readl(base + MMCISTATUS) & host->variant->busy_detect_flag)) {
+ /* Unmask the busy IRQ */
+ writel(readl(base + MMCIMASK0) |
+ host->variant->busy_detect_mask,
+ base + MMCIMASK0);
+ /*
+ * Now cache the last response status code (until
+ * the busy bit goes low), and return.
+ */
+ host->busy_status =
+ status & (MCI_CMDSENT|MCI_CMDRESPEND);
+ return;
+ }
- /* At busy completion, mask the IRQ and complete the request. */
- if (host->busy_status) {
- writel(readl(base + MMCIMASK0) & ~MCI_ST_BUSYEND,
- base + MMCIMASK0);
- host->busy_status = 0;
+ /*
+ * At this point we are not busy with a command, we have
+ * not recieved a new busy request, mask the busy IRQ and
+ * fall through to process the IRQ.
+ */
+ if (host->busy_status) {
+ writel(readl(base + MMCIMASK0) &
+ ~host->variant->busy_detect_mask,
+ base + MMCIMASK0);
+ host->busy_status = 0;
+ }
}
host->cmd = NULL;
@@ -1257,9 +1301,11 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
mmci_data_irq(host, host->data, status);
}
- /* Don't poll for busy completion in irq context. */
- if (host->busy_status)
- status &= ~MCI_ST_CARDBUSY;
+ /*
+ * Don't poll for busy completion in irq context.
+ */
+ if (host->variant->busy_detect && host->busy_status)
+ status &= ~host->variant->busy_detect_flag;
ret = 1;
} while (status);
@@ -1612,9 +1658,18 @@ static int mmci_probe(struct amba_device *dev,
/* We support these capabilities. */
mmc->caps |= MMC_CAP_CMD23;
+ /*
+ * Enable busy detection.
+ */
if (variant->busy_detect) {
mmci_ops.card_busy = mmci_card_busy;
- mmci_write_datactrlreg(host, MCI_DPSM_ST_BUSYMODE);
+ /*
+ * Not all variants have a flag to enable busy detection
+ * in the DPSM, but if they do, set it here.
+ */
+ if (variant->busy_dpsm_flag)
+ mmci_write_datactrlreg(host,
+ host->variant->busy_dpsm_flag);
mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
mmc->max_busy_timeout = 0;
}
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 7cabf270050b..56322c6afba4 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -174,7 +174,7 @@
/* Extended status bits for the ST Micro variants */
#define MCI_ST_SDIOITMASK (1 << 22)
#define MCI_ST_CEATAENDMASK (1 << 23)
-#define MCI_ST_BUSYEND (1 << 24)
+#define MCI_ST_BUSYENDMASK (1 << 24)
#define MMCIMASK1 0x040
#define MMCIFIFOCNT 0x048
--
2.7.4
^ permalink raw reply related
* [PATCH 3/3 v2] RFC: mmc: mmci: add qcom specific program end support
From: Linus Walleij @ 2016-10-25 9:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477386367-18514-1-git-send-email-linus.walleij@linaro.org>
From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
This patch adds support to programend interrupt which is very
specific to QCOM integration. This interrupt is use as busy signal
when a command forces the card to enter into programming state
like CMD6 writing to ext_csd registers.
Hopefully, this also fixes the __mmc_switch timeout issue reproted
with latest versions of the eMMC used on DB600c board.
This patch is based on a WIP patch from Srinivas Kandagatla and
augmented by Linus Walleij for another approach.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v1->v2:
- Rebase on new register naming.
Srinivas: please test to see if this fixes your problems. Sadly
it does *NOT* solve my APQ8060 issues, but it would be nice if
the common code path works for the busy detection on your
DB600c.
---
drivers/mmc/host/mmci.c | 21 +++++++++++++++++++--
drivers/mmc/host/mmci.h | 6 ++++++
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 7f68fa7a961e..580ca89d33dc 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -72,7 +72,10 @@ static unsigned int fmax = 515633;
* @signal_direction: input/out direction of bus signals can be indicated
* @pwrreg_clkgate: MMCIPOWER register must be used to gate the clock
* @busy_detect: true if the variant supports busy detection on DAT0.
- * @busy_dpsm_flag: bitmask enabling busy detection in the DPSM
+ * @busy_cpsm_flag: bitmask enabling busy detection in the CPSM (command
+ * path state machine)
+ * @busy_dpsm_flag: bitmask enabling busy detection in the DPSM (data path
+ * state machine)
* @busy_detect_flag: bitmask identifying the bit in the MMCISTATUS register
* indicating that the card is busy
* @busy_detect_mask: bitmask identifying the bit in the MMCIMASK0 to mask for
@@ -103,6 +106,7 @@ struct variant_data {
bool signal_direction;
bool pwrreg_clkgate;
bool busy_detect;
+ u32 busy_cpsm_flag;
u32 busy_dpsm_flag;
u32 busy_detect_flag;
u32 busy_detect_mask;
@@ -229,6 +233,10 @@ static struct variant_data variant_qcom = {
.datalength_bits = 24,
.pwrreg_powerup = MCI_PWR_UP,
.f_max = 208000000,
+ .busy_detect = true,
+ .busy_cpsm_flag = MCI_CPSM_QCOM_PROGENA,
+ .busy_detect_flag = MCI_QCOM_PROGDONE,
+ .busy_detect_mask = MCI_QCOM_PROGDONEMASK,
.explicit_mclk_control = true,
.qcom_fifo = true,
.qcom_dml = true,
@@ -903,6 +911,15 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
if (/*interrupt*/0)
c |= MCI_CPSM_INTERRUPT;
+ /*
+ * Enable the program end interrupt for specific commands
+ * used for busy detection.
+ */
+ if (host->variant->busy_detect &&
+ (cmd->flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
+ c |= host->variant->busy_cpsm_flag;
+ }
+
if (mmc_cmd_type(cmd) == MMC_CMD_ADTC)
c |= host->variant->data_cmd_enable;
@@ -1005,7 +1022,7 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
return;
/*
- * ST Micro variant: handle busy detection.
+ * ST Micro and Qualcomm variants: handle busy detection.
*/
if (host->variant->busy_detect) {
bool busy_resp = !!(cmd->flags & MMC_RSP_BUSY);
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 56322c6afba4..355259b0a24b 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -130,6 +130,8 @@
#define MCI_ST_SDIOIT (1 << 22)
#define MCI_ST_CEATAEND (1 << 23)
#define MCI_ST_CARDBUSY (1 << 24)
+/* Extended status bits for the QCOM variants */
+#define MCI_QCOM_PROGDONE (1 << 23)
#define MMCICLEAR 0x038
#define MCI_CMDCRCFAILCLR (1 << 0)
@@ -147,6 +149,8 @@
#define MCI_ST_SDIOITC (1 << 22)
#define MCI_ST_CEATAENDC (1 << 23)
#define MCI_ST_BUSYENDC (1 << 24)
+/* Extended status bits for the QCOM variants */
+#define MCI_QCOM_PROGDONECLR (1 << 23)
#define MMCIMASK0 0x03c
#define MCI_CMDCRCFAILMASK (1 << 0)
@@ -175,6 +179,8 @@
#define MCI_ST_SDIOITMASK (1 << 22)
#define MCI_ST_CEATAENDMASK (1 << 23)
#define MCI_ST_BUSYENDMASK (1 << 24)
+/* Extended status bits for the Qualcomm variants */
+#define MCI_QCOM_PROGDONEMASK (1 << 23)
#define MMCIMASK1 0x040
#define MMCIFIFOCNT 0x048
--
2.7.4
^ permalink raw reply related
* [PATCH 2/3] ARM: convert to generated system call tables
From: Michael Cree @ 2016-10-25 9:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <3851270.xZRcP9hae0@wuerfel>
On Fri, Oct 21, 2016 at 03:06:45PM +0200, Arnd Bergmann wrote:
> I see your point, but I think there are serious issues with the current
> approach as well:
>
> - a lot of the less common architectures just don't get updated
> in time, out of 22 architectures that don't use asm-generic/unistd.h,
> only 12 have pwritev2 in linux-next, and only three have pkey_mprotect
>
> - some architectures that add all syscalls sometimes make a mistake
> and forget one, e.g. alpha apparently never added __NR_bpf, but it
> did add the later __NR_execveat.
__NR_bpf was not forgotten on Alpha. It was not wired up because
extra architecture support is needed which has not been implemented.
But maybe we should just wire it up to sys_ni_syscall in the meantime
so a syscall number is reserved for it, and user space can call it to
get -ENOSYS returned.
Cheers
Michael.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox