* [PATCH v3 1/2] mfd: pm8xxx: add support to pm8821
From: Srinivas Kandagatla @ 2016-11-15 12:01 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds support to PM8821 PMIC and interrupt support.
PM8821 is companion device that supplements primary PMIC PM8921 IC.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Acked-by: Rob Herring <robh@kernel.org>
---
Changes since v2:
- removed few empty lines spotted by Bjorn
- rephrased some debug prints suggested by Bjorn
.../devicetree/bindings/mfd/qcom-pm8xxx.txt | 1 +
drivers/mfd/qcom-pm8xxx.c | 231 ++++++++++++++++++++-
2 files changed, 222 insertions(+), 10 deletions(-)
diff --git a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
index 37a088f..9e5eba4 100644
--- a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
+++ b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
@@ -10,6 +10,7 @@ voltages and other various functionality to Qualcomm SoCs.
Value type: <string>
Definition: must be one of:
"qcom,pm8058"
+ "qcom,pm8821"
"qcom,pm8921"
- #address-cells:
diff --git a/drivers/mfd/qcom-pm8xxx.c b/drivers/mfd/qcom-pm8xxx.c
index 7f9620e..f08758f 100644
--- a/drivers/mfd/qcom-pm8xxx.c
+++ b/drivers/mfd/qcom-pm8xxx.c
@@ -39,6 +39,20 @@
#define SSBI_REG_ADDR_IRQ_CONFIG (SSBI_REG_ADDR_IRQ_BASE + 7)
#define SSBI_REG_ADDR_IRQ_RT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 8)
+#define PM8821_SSBI_REG_ADDR_IRQ_BASE 0x100
+#define PM8821_SSBI_REG_ADDR_IRQ_MASTER0 (PM8821_SSBI_REG_ADDR_IRQ_BASE + 0x30)
+#define PM8821_SSBI_REG_ADDR_IRQ_MASTER1 (PM8821_SSBI_REG_ADDR_IRQ_BASE + 0xb0)
+#define PM8821_SSBI_REG(m, b, offset) \
+ ((m == 0) ? \
+ (PM8821_SSBI_REG_ADDR_IRQ_MASTER0 + b + offset) : \
+ (PM8821_SSBI_REG_ADDR_IRQ_MASTER1 + b + offset))
+#define PM8821_SSBI_ADDR_IRQ_ROOT(m, b) PM8821_SSBI_REG(m, b, 0x0)
+#define PM8821_SSBI_ADDR_IRQ_CLEAR(m, b) PM8821_SSBI_REG(m, b, 0x01)
+#define PM8821_SSBI_ADDR_IRQ_MASK(m, b) PM8821_SSBI_REG(m, b, 0x08)
+#define PM8821_SSBI_ADDR_IRQ_RT_STATUS(m, b) PM8821_SSBI_REG(m, b, 0x0f)
+
+#define PM8821_BLOCKS_PER_MASTER 7
+
#define PM_IRQF_LVL_SEL 0x01 /* level select */
#define PM_IRQF_MASK_FE 0x02 /* mask falling edge */
#define PM_IRQF_MASK_RE 0x04 /* mask rising edge */
@@ -54,6 +68,7 @@
#define REG_HWREV_2 0x0E8 /* PMIC4 revision 2 */
#define PM8XXX_NR_IRQS 256
+#define PM8821_NR_IRQS 112
struct pm_irq_chip {
struct regmap *regmap;
@@ -65,6 +80,12 @@ struct pm_irq_chip {
u8 config[0];
};
+struct pm_irq_data {
+ int num_irqs;
+ const struct irq_domain_ops *irq_domain_ops;
+ void (*irq_handler)(struct irq_desc *desc);
+};
+
static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp,
unsigned int *ip)
{
@@ -182,6 +203,78 @@ static void pm8xxx_irq_handler(struct irq_desc *desc)
chained_irq_exit(irq_chip, desc);
}
+static void pm8821_irq_block_handler(struct pm_irq_chip *chip,
+ int master, int block)
+{
+ int pmirq, irq, i, ret;
+ unsigned int bits;
+
+ ret = regmap_read(chip->regmap,
+ PM8821_SSBI_ADDR_IRQ_ROOT(master, block), &bits);
+ if (ret) {
+ pr_err("Reading block %d failed ret=%d", block, ret);
+ return;
+ }
+
+ /* Convert block offset to global block number */
+ block += (master * PM8821_BLOCKS_PER_MASTER) - 1;
+
+ /* Check IRQ bits */
+ for (i = 0; i < 8; i++) {
+ if (bits & BIT(i)) {
+ pmirq = block * 8 + i;
+ irq = irq_find_mapping(chip->irqdomain, pmirq);
+ generic_handle_irq(irq);
+ }
+ }
+}
+
+static inline void pm8821_irq_master_handler(struct pm_irq_chip *chip,
+ int master, u8 master_val)
+{
+ int block;
+
+ for (block = 1; block < 8; block++)
+ if (master_val & BIT(block))
+ pm8821_irq_block_handler(chip, master, block);
+}
+
+static void pm8821_irq_handler(struct irq_desc *desc)
+{
+ struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
+ struct irq_chip *irq_chip = irq_desc_get_chip(desc);
+ unsigned int master;
+ int ret;
+
+ chained_irq_enter(irq_chip, desc);
+ ret = regmap_read(chip->regmap,
+ PM8821_SSBI_REG_ADDR_IRQ_MASTER0, &master);
+ if (ret) {
+ pr_err("Failed to read master 0 ret=%d\n", ret);
+ goto done;
+ }
+
+ /* bits 1 through 7 marks the first 7 blocks in master 0 */
+ if (master & GENMASK(7, 1))
+ pm8821_irq_master_handler(chip, 0, master);
+
+ /* bit 0 marks if master 1 contains any bits */
+ if (!(master & BIT(0)))
+ goto done;
+
+ ret = regmap_read(chip->regmap,
+ PM8821_SSBI_REG_ADDR_IRQ_MASTER1, &master);
+ if (ret) {
+ pr_err("Failed to read master 1 ret=%d\n", ret);
+ goto done;
+ }
+
+ pm8821_irq_master_handler(chip, 1, master);
+
+done:
+ chained_irq_exit(irq_chip, desc);
+}
+
static void pm8xxx_irq_mask_ack(struct irq_data *d)
{
struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
@@ -299,6 +392,104 @@ static const struct irq_domain_ops pm8xxx_irq_domain_ops = {
.map = pm8xxx_irq_domain_map,
};
+static void pm8821_irq_mask_ack(struct irq_data *d)
+{
+ struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+ unsigned int pmirq = irqd_to_hwirq(d);
+ u8 block, master;
+ int irq_bit, rc;
+
+ block = pmirq / 8;
+ master = block / PM8821_BLOCKS_PER_MASTER;
+ irq_bit = pmirq % 8;
+ block %= PM8821_BLOCKS_PER_MASTER;
+
+ rc = regmap_update_bits(chip->regmap,
+ PM8821_SSBI_ADDR_IRQ_MASK(master, block),
+ BIT(irq_bit), BIT(irq_bit));
+ if (rc) {
+ pr_err("Failed to mask IRQ:%d rc=%d\n", pmirq, rc);
+ return;
+ }
+
+ rc = regmap_update_bits(chip->regmap,
+ PM8821_SSBI_ADDR_IRQ_CLEAR(master, block),
+ BIT(irq_bit), BIT(irq_bit));
+ if (rc)
+ pr_err("Failed to CLEAR IRQ:%d rc=%d\n", pmirq, rc);
+}
+
+static void pm8821_irq_unmask(struct irq_data *d)
+{
+ struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+ unsigned int pmirq = irqd_to_hwirq(d);
+ int irq_bit, rc;
+ u8 block, master;
+
+ block = pmirq / 8;
+ master = block / PM8821_BLOCKS_PER_MASTER;
+ irq_bit = pmirq % 8;
+ block %= PM8821_BLOCKS_PER_MASTER;
+
+ rc = regmap_update_bits(chip->regmap,
+ PM8821_SSBI_ADDR_IRQ_MASK(master, block),
+ BIT(irq_bit), ~BIT(irq_bit));
+ if (rc)
+ pr_err("Failed to read/write unmask IRQ:%d rc=%d\n", pmirq, rc);
+
+}
+
+static int pm8821_irq_get_irqchip_state(struct irq_data *d,
+ enum irqchip_irq_state which,
+ bool *state)
+{
+ struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+ int rc, pmirq = irqd_to_hwirq(d);
+ u8 block, irq_bit, master;
+ unsigned int bits;
+
+ block = pmirq / 8;
+ master = block / PM8821_BLOCKS_PER_MASTER;
+ irq_bit = pmirq % 8;
+ block %= PM8821_BLOCKS_PER_MASTER;
+
+ rc = regmap_read(chip->regmap,
+ PM8821_SSBI_ADDR_IRQ_RT_STATUS(master, block), &bits);
+ if (rc) {
+ pr_err("Reading Status of IRQ %d failed rc=%d\n", pmirq, rc);
+ return rc;
+ }
+
+ *state = !!(bits & BIT(irq_bit));
+
+ return rc;
+}
+
+static struct irq_chip pm8821_irq_chip = {
+ .name = "pm8821",
+ .irq_mask_ack = pm8821_irq_mask_ack,
+ .irq_unmask = pm8821_irq_unmask,
+ .irq_get_irqchip_state = pm8821_irq_get_irqchip_state,
+ .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
+};
+
+static int pm8821_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ struct pm_irq_chip *chip = d->host_data;
+
+ irq_set_chip_and_handler(irq, &pm8821_irq_chip, handle_level_irq);
+ irq_set_chip_data(irq, chip);
+ irq_set_noprobe(irq);
+
+ return 0;
+}
+
+static const struct irq_domain_ops pm8821_irq_domain_ops = {
+ .xlate = irq_domain_xlate_twocell,
+ .map = pm8821_irq_domain_map,
+};
+
static const struct regmap_config ssbi_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
@@ -308,22 +499,41 @@ static const struct regmap_config ssbi_regmap_config = {
.reg_write = ssbi_reg_write
};
+static const struct pm_irq_data pm8xxx_data = {
+ .num_irqs = PM8XXX_NR_IRQS,
+ .irq_domain_ops = &pm8xxx_irq_domain_ops,
+ .irq_handler = pm8xxx_irq_handler,
+};
+
+static const struct pm_irq_data pm8821_data = {
+ .num_irqs = PM8821_NR_IRQS,
+ .irq_domain_ops = &pm8821_irq_domain_ops,
+ .irq_handler = pm8821_irq_handler,
+};
+
static const struct of_device_id pm8xxx_id_table[] = {
- { .compatible = "qcom,pm8018", },
- { .compatible = "qcom,pm8058", },
- { .compatible = "qcom,pm8921", },
+ { .compatible = "qcom,pm8018", .data = &pm8xxx_data},
+ { .compatible = "qcom,pm8058", .data = &pm8xxx_data},
+ { .compatible = "qcom,pm8821", .data = &pm8821_data},
+ { .compatible = "qcom,pm8921", .data = &pm8xxx_data},
{ }
};
MODULE_DEVICE_TABLE(of, pm8xxx_id_table);
static int pm8xxx_probe(struct platform_device *pdev)
{
+ const struct pm_irq_data *data;
struct regmap *regmap;
int irq, rc;
unsigned int val;
u32 rev;
struct pm_irq_chip *chip;
- unsigned int nirqs = PM8XXX_NR_IRQS;
+
+ data = of_device_get_match_data(&pdev->dev);
+ if (!data) {
+ dev_err(&pdev->dev, "No matching driver data found\n");
+ return -EINVAL;
+ }
irq = platform_get_irq(pdev, 0);
if (irq < 0)
@@ -354,25 +564,26 @@ static int pm8xxx_probe(struct platform_device *pdev)
rev |= val << BITS_PER_BYTE;
chip = devm_kzalloc(&pdev->dev, sizeof(*chip) +
- sizeof(chip->config[0]) * nirqs,
- GFP_KERNEL);
+ sizeof(chip->config[0]) * data->num_irqs,
+ GFP_KERNEL);
if (!chip)
return -ENOMEM;
platform_set_drvdata(pdev, chip);
chip->regmap = regmap;
- chip->num_irqs = nirqs;
+ chip->num_irqs = data->num_irqs;
chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
spin_lock_init(&chip->pm_irq_lock);
- chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node, nirqs,
- &pm8xxx_irq_domain_ops,
+ chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node,
+ data->num_irqs,
+ data->irq_domain_ops,
chip);
if (!chip->irqdomain)
return -ENODEV;
- irq_set_chained_handler_and_data(irq, pm8xxx_irq_handler, chip);
+ irq_set_chained_handler_and_data(irq, data->irq_handler, chip);
irq_set_irq_wake(irq, 1);
rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
--
2.10.1
^ permalink raw reply related
* [PATCH] iommu/dma: Stop getting dma_32bit_pfn wrong
From: Joerg Roedel @ 2016-11-15 11:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <f9c96106e6253f7033be8dd975392f0edb12e603.1478889045.git.robin.murphy@arm.com>
On Fri, Nov 11, 2016 at 06:30:45PM +0000, Robin Murphy wrote:
> iommu_dma_init_domain() was originally written under the misconception
> that dma_32bit_pfn represented some sort of size limit for IOVA domains.
> Since the truth is almost the exact opposite of that, rework the logic
> and comments to reflect its real purpose of optimising lookups when
> allocating from a subset of the available space.
>
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> ---
> drivers/iommu/dma-iommu.c | 23 ++++++++++++++++++-----
> 1 file changed, 18 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index c5ab8667e6f2..ae045a14b530 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -139,6 +139,7 @@ int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
> {
> struct iova_domain *iovad = cookie_iovad(domain);
> unsigned long order, base_pfn, end_pfn;
> + bool pci = dev && dev_is_pci(dev);
>
> if (!iovad)
> return -ENODEV;
> @@ -161,19 +162,31 @@ int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
> end_pfn = min_t(unsigned long, end_pfn,
> domain->geometry.aperture_end >> order);
> }
> + /*
> + * PCI devices may have larger DMA masks, but still prefer allocating
> + * within a 32-bit mask to avoid DAC addressing. Such limitations don't
> + * apply to the typical platform device, so for those we may as well
> + * leave the cache limit at the top of the range they're likely to use.
> + */
> + if (pci)
> + end_pfn = min_t(unsigned long, end_pfn,
> + DMA_BIT_MASK(32) >> order);
Question, does it actually hurt platform devices to follow the same
allocation strategy as pci devices? I mean, does it hurt enough to
special-case the code here?
Joerg
^ permalink raw reply
* LEDs that change brightness "itself" -- that's a trigger. Re: PM regression with LED changes in next-20161109
From: Pavel Machek @ 2016-11-15 11:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <128aae59-b790-42f1-7d66-81391c9330c3@redhat.com>
Hi!
> >>>The LED you are talking about _has_ a trigger, implemented in
> >>>hardware. That trigger can change LED brightness behind kernel's (and
> >>>userspace's) back. Don't pretend the trigger does not exist, it does.
> >>>
> >>>And when you do that, you'll have nice place to report changes to
> >>>userspace -- trigger can now export that information, and offer poll()
> >>>interface.
> >>
> >>Well, that sounds interesting. It is logically justifiable.
> >
> >Thanks.
> >
> >>I initially proposed exactly this solution, with recently
> >>added userspace LED being a trigger listener. It seems a bit
> >>awkward though. How would you listen to the trigger events?
> >
> >Trigger exposes a file in sysfs, with poll() working on that file
>
> Hmm, a new file would give the advantage of making it easy for
> userspace to see if the trigger is poll-able, this is likely
> better then my own proposal I just send.
Good.
> >(and
> >probably read exposing the current brightness).
>
> If we do this, can we please make it mirror brightness, iow
> also make it writable, that will make it easier for userspace
> to deal with it. We can simply re-use the existing show / store
> methods for brightness for this.
Actually, echo 0 > brightness disables the trigger, IIRC. I'd avoid
that here, you want to be able to turn off the backlight but still
keep the trigger (and be notified of future changes).
> I suggest we call it:
>
> trigger_brightness
>
> And only register it when a poll-able trigger is present.
I'd call it 'current_brightness', but that's no big deal. Yes, only
registering it for poll-able triggers makes sense.
> >Key difference is that only triggers where this makes sense (keyboard
> >backlight) expose it and carry the overhead. CPU trigger would
> >definitely not do this.
>
> Ack only having some triggers pollable is important.
Thanks,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161115/c4399499/attachment.sig>
^ permalink raw reply
* [PATCH] arm/arm64: KVM: clean up useless code in kvm_timer_enable
From: Christoffer Dall @ 2016-11-15 11:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478659814-364872-1-git-send-email-longpeng2@huawei.com>
On Wed, Nov 09, 2016 at 10:50:14AM +0800, Longpeng(Mike) wrote:
> 1) Since commit:41a54482 changed timer enabled variable to per-vcpu,
> the correlative comment in kvm_timer_enable is useless now.
>
> 2) After the kvm module init successfully, the timecounter is always
> non-null, so we can remove the checking of timercounter.
>
> Signed-off-by: Longpeng(Mike) <longpeng2@huawei.com>
Acked-by: Christoffer Dall <christoffer.dall@linaro.org>
> ---
> virt/kvm/arm/arch_timer.c | 12 +-----------
> 1 file changed, 1 insertion(+), 11 deletions(-)
>
> diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
> index 27a1f63..17b8fa5 100644
> --- a/virt/kvm/arm/arch_timer.c
> +++ b/virt/kvm/arm/arch_timer.c
> @@ -498,17 +498,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
> if (ret)
> return ret;
>
> -
> - /*
> - * There is a potential race here between VCPUs starting for the first
> - * time, which may be enabling the timer multiple times. That doesn't
> - * hurt though, because we're just setting a variable to the same
> - * variable that it already was. The important thing is that all
> - * VCPUs have the enabled variable set, before entering the guest, if
> - * the arch timers are enabled.
> - */
> - if (timecounter)
> - timer->enabled = 1;
> + timer->enabled = 1;
>
> return 0;
> }
> --
> 1.8.3.1
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" 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 v2 07/10] ARM: add low level debug uart for rk1108
From: Heiko Stuebner @ 2016-11-15 11:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479125555-24465-1-git-send-email-andy.yan@rock-chips.com>
Am Montag, 14. November 2016, 20:12:35 CET schrieb Andy Yan:
> RK1108 UARTs are Synopsis DesignWare 8250 compatible.
> Only with different register addresses.
>
> Signed-off-by: Andy Yan <andy.yan@rock-chips.com>
> Tested-by: Jacob Chen <jacob2.chen@rock-chips.com>
applied to my soc branch
Thanks
Heiko
^ permalink raw reply
* wdt, gpio: move arch_initcall into subsys_initcall ?
From: Vladimir Zapolskiy @ 2016-11-15 11:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <afbf394e-e411-5c43-e2b0-667b3fbc2edf@mentor.com>
On 11/15/2016 01:10 PM, Vladimir Zapolskiy wrote:
> Hello Heiko,
>
> On 11/15/2016 12:20 PM, Heiko Schocher wrote:
>> Hello,
>>
>> commit e188cbf7564f: "gpio: mxc: shift gpio_mxc_init() to subsys_initcall level"
>> moves the gpio initialization of the mxc gpio driver
>> from the arch_initcall level into subsys_initcall level.
>>
>> This leads now on mxc boards, which use a gpio wdt driver
>> and the CONFIG_GPIO_WATCHDOG_ARCH_INITCALL option enabled,
>> to unwanted driver probe deferrals during kernel boot.
>>
>> I see this currently on an imx6 based board (which has unfortunately
>> 3 WDT: imx6 internal (disabled), gpio wdt and da9063 WDT ...).
>>
>> Also a side effect from above commit is, that the da9063 WDT driver
>> is now probed before the gpio WDT driver ... so /dev/watchdog now
>> does not point to the gpio_wdt, instead it points to the da9063 WDT.
>>
>> So there are 2 solutions possible:
>>
>> - add a CONFIG_GPIO_MCX_ARCH_INITCALL option
>> in drivers/gpio/gpio-mxc.c like for the gpio_wdt.c driver?
>
> in my opinion this is overly heavy solution and it might be
> better to avoid it if possible.
>
> I would rather prefer to reconsider GPIO_WATCHDOG_ARCH_INITCALL
> usage in the watchdog driver.
>
> Moreover adding this proposed GPIO_MCX_ARCH_INITCALL to call
> the driver on arch level will result in deferring the GPIO driver.
>
>> But how can we guarantee, that first the gpio driver and then
>> the gpio_wdt driver gets probed?
>>
>> - move the arch_initcall in gpio_wdt.c into a subsys_initcall
>> (Tested this, and the probe dereferral messages are gone ...)
>>
>> But this may results in problems on boards, which needs an early
>> trigger on an gpio wdt ...
>
> The level of "earliness" can not be defined in absolute time value
> in any case, why decreasing the init level of the watchdog driver
> to subsys level can cause problems? For that there should exist
> some kind of a dependency on IC or PCB hardware level, can you
> name it please?
>
> Also please note that more than a half of all GPIO drivers settle
> on subsys or later initcall level, this means that there is
> an expected GPIO watchdog driver deferral for all of them.
Please find two more late notes though.
> I propose to send two patches for review:
>
> 1. remove GPIO_WATCHDOG_ARCH_INITCALL option completely and decouple
> module_platform_driver() into arch_initcall() and module_exit()
> unconditionally.
>
> 2. change arch_initcall() in the watchdog driver to subsys_initcall().
> This change removes probe deferrals on boot, when the driver is
> used with the most of the GPIO controllers.
Alternatively commit 5e53c8ed813d ("watchdog: gpio_wdt: Add option for
early registration") can be reverted and then module_platform_driver()
is decoupled into subsys_initcall() and module_exit() as its replacement.
And also please note that since quite many GPIO controller drivers
live on initcall levels after subsys_initcall(), the solution won't
let to avoid watchdog driver deferrals totally, this should be accepted.
--
With best wishes,
Vladimir
^ permalink raw reply
* [PATCH v2 1/5] iommu: Allow taking a reference on a group directly
From: Joerg Roedel @ 2016-11-15 11:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <37029eb869380edb0d5ce8cc6601ce7e69c80458.1478886974.git.robin.murphy@arm.com>
On Fri, Nov 11, 2016 at 05:59:21PM +0000, Robin Murphy wrote:
> iommu_group_get_for_dev() expects that the IOMMU driver's device_group
> callback return a group with a reference held for the given device.
> Whilst allocating a new group is fine, and pci_device_group() correctly
> handles reusing an existing group, there is no general means for IOMMU
> drivers doing their own group lookup to take additional references on an
> existing group pointer without having to also store device pointers or
> resort to elaborate trickery.
>
> Add an IOMMU-driver-specific function to fill the hole.
>
> Acked-by: Sricharan R <sricharan@codeaurora.org>
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> ---
>
> v2: Fix the function name; clarify what exactly its callers are fixing.
>
> drivers/iommu/iommu.c | 13 +++++++++++++
> include/linux/iommu.h | 1 +
> 2 files changed, 14 insertions(+)
Applied the series, thanks Robin.
^ permalink raw reply
* LEDs that change brightness "itself" -- that's a trigger. Re: PM regression with LED changes in next-20161109
From: Hans de Goede @ 2016-11-15 11:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161115111154.GA5482@amd>
Hi,
On 15-11-16 12:11, Pavel Machek wrote:
> On Tue 2016-11-15 11:58:06, Jacek Anaszewski wrote:
>> On 11/15/2016 11:31 AM, Pavel Machek wrote:
>>> Hi!
>>>
>>>>> Hmm, v4 still calls led_notify_brightness_change(led_cdev)
>>>> >from both __led_set_brightness() and __led_set_brightness_blocking().
>>>>
>>>> Ugh, I see I accidentally send a v4 twice, instead of
>>>> calling the version which dropped those called v5 as
>>>> I should have, sorry.
>>>>
>>>> The v4 which I would like to see merged, the one with
>>>> those calls dropped, is here:
>>>>
>>>> https://patchwork.kernel.org/patch/9423093/
>>>
>>> Please, lets fix this properly.
>>>
>>> The LED you are talking about _has_ a trigger, implemented in
>>> hardware. That trigger can change LED brightness behind kernel's (and
>>> userspace's) back. Don't pretend the trigger does not exist, it does.
>>>
>>> And when you do that, you'll have nice place to report changes to
>>> userspace -- trigger can now export that information, and offer poll()
>>> interface.
>>
>> Well, that sounds interesting. It is logically justifiable.
>
> Thanks.
>
>> I initially proposed exactly this solution, with recently
>> added userspace LED being a trigger listener. It seems a bit
>> awkward though. How would you listen to the trigger events?
>
> Trigger exposes a file in sysfs, with poll() working on that file
Hmm, a new file would give the advantage of making it easy for
userspace to see if the trigger is poll-able, this is likely
better then my own proposal I just send.
> (and
> probably read exposing the current brightness).
If we do this, can we please make it mirror brightness, iow
also make it writable, that will make it easier for userspace
to deal with it. We can simply re-use the existing show / store
methods for brightness for this.
I suggest we call it:
trigger_brightness
And only register it when a poll-able trigger is present.
> Key difference is that only triggers where this makes sense (keyboard
> backlight) expose it and carry the overhead. CPU trigger would
> definitely not do this.
Ack only having some triggers pollable is important.
Regards,
Hans
^ permalink raw reply
* [PATCH] ARM: dma-mapping: preallocate DMA-debug hash tables in pure_initcall
From: Arnd Bergmann @ 2016-11-15 11:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <9470b8cc-daaf-0edc-da33-0872d9919311@samsung.com>
On Tuesday, November 15, 2016 11:39:17 AM CET Marek Szyprowski wrote:
> On 2016-11-15 11:31, Arnd Bergmann wrote:
> > On Tuesday, November 15, 2016 11:04:55 AM CET Marek Szyprowski wrote:
> >> fs_initcall is definitely too late to initialize DMA-debug hash tables,
> >> because some drivers might get probed and use DMA mapping framework
> >> already in core_initcall. Late initialization of DMA-debug results in
> >> false warning about accessing memory, that was not allocated, like this
> >> one:
> > To ask the obvious question: what driver does DMA allocations in a
> > core_initcall, and have you tried to change that first?
>
> See the attached stack trace.
>
> Exynos IOMMU driver does that in its domain_alloc implementation (to
> allocate
> first level of PTE) and I see no easy way to avoid that, as iommu
> domains are
> allocated very early (as well as the whole IOMMU initialization and
> attaching
> to the devices). Exynos IOMMU driver has to use DMA-mapping API for PTE
> management, because the IOMMU controllers are not coherent with system
> CPU and
> there is no other way to ensure proper CPU cache management.
Could the allocation be deferred until the first user of the IOMMU
comes up?
Arnd
^ permalink raw reply
* LEDs that change brightness "itself" -- that's a trigger. Re: PM regression with LED changes in next-20161109
From: Hans de Goede @ 2016-11-15 11:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4e392d5d-eb10-f285-517e-976a55c3e318@samsung.com>
HI,
On 15-11-16 11:58, Jacek Anaszewski wrote:
> On 11/15/2016 11:31 AM, Pavel Machek wrote:
>> Hi!
>>
>>>> Hmm, v4 still calls led_notify_brightness_change(led_cdev)
>>> >from both __led_set_brightness() and __led_set_brightness_blocking().
>>>
>>> Ugh, I see I accidentally send a v4 twice, instead of
>>> calling the version which dropped those called v5 as
>>> I should have, sorry.
>>>
>>> The v4 which I would like to see merged, the one with
>>> those calls dropped, is here:
>>>
>>> https://patchwork.kernel.org/patch/9423093/
>>
>> Please, lets fix this properly.
>>
>> The LED you are talking about _has_ a trigger, implemented in
>> hardware. That trigger can change LED brightness behind kernel's (and
>> userspace's) back. Don't pretend the trigger does not exist, it does.
>>
>> And when you do that, you'll have nice place to report changes to
>> userspace -- trigger can now export that information, and offer poll()
>> interface.
>
> Well, that sounds interesting. It is logically justifiable.
> I initially proposed exactly this solution, with recently
> added userspace LED being a trigger listener. It seems a bit
> awkward though. How would you listen to the trigger events?
We could make the trigger sysfs attribute poll()-able, but only
for select triggers, e.g.:
Documentation/ABI/testing/sysfs-class-led
What: /sys/class/leds/<led>/trigger
Date: March 2006
KernelVersion: 2.6.17
Contact: Richard Purdie <rpurdie@rpsys.net>
Description:
Set the trigger for this LED. A trigger is a kernel based source
of led events.
You can change triggers in a similar manner to the way an IO
scheduler is chosen. Trigger specific parameters can appear in
/sys/class/leds/<led> once a given trigger is selected. For
their documentation see sysfs-class-led-trigger-*.
+
+ For some triggers userspace my poll() this file, watching for
+ POLL_PRI to detect when the trigger triggers. This is only
+ supported if this is explicitly mentioned as supported in
+ sysfs-class-led-trigger-* for the selected trigger.
The reason for making this only supported for select triggers is to
avoid getting the whole power-consumption issue from triggers which fire
frequently again.
And then we could add a new:
Documentation/ABI/testing/sysfs-class-led-trigger-kbd-backlight-change
File which documents that the new to be added kbd-backlight-change
trigger is poll-able.
We would also need:
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -47,6 +47,7 @@ struct led_classdev {
#define LED_DEV_CAP_FLASH (1 << 18)
#define LED_HW_PLUGGABLE (1 << 19)
#define LED_PANIC_INDICATOR (1 << 20)
+#define LED_TRIGGER_READ_ONLY (1 << 21)
/* set_brightness_work / blink_timer flags, atomic, private. */
unsigned long work_flags;
To allow led drivers to indicate that there trigger is hardwired.
Regards,
Hans
^ permalink raw reply
* LEDs that change brightness "itself" -- that's a trigger. Re: PM regression with LED changes in next-20161109
From: Pavel Machek @ 2016-11-15 11:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4e392d5d-eb10-f285-517e-976a55c3e318@samsung.com>
On Tue 2016-11-15 11:58:06, Jacek Anaszewski wrote:
> On 11/15/2016 11:31 AM, Pavel Machek wrote:
> >Hi!
> >
> >>>Hmm, v4 still calls led_notify_brightness_change(led_cdev)
> >>>from both __led_set_brightness() and __led_set_brightness_blocking().
> >>
> >>Ugh, I see I accidentally send a v4 twice, instead of
> >>calling the version which dropped those called v5 as
> >>I should have, sorry.
> >>
> >>The v4 which I would like to see merged, the one with
> >>those calls dropped, is here:
> >>
> >>https://patchwork.kernel.org/patch/9423093/
> >
> >Please, lets fix this properly.
> >
> >The LED you are talking about _has_ a trigger, implemented in
> >hardware. That trigger can change LED brightness behind kernel's (and
> >userspace's) back. Don't pretend the trigger does not exist, it does.
> >
> >And when you do that, you'll have nice place to report changes to
> >userspace -- trigger can now export that information, and offer poll()
> >interface.
>
> Well, that sounds interesting. It is logically justifiable.
Thanks.
> I initially proposed exactly this solution, with recently
> added userspace LED being a trigger listener. It seems a bit
> awkward though. How would you listen to the trigger events?
Trigger exposes a file in sysfs, with poll() working on that file (and
probably read exposing the current brightness).
Key difference is that only triggers where this makes sense (keyboard
backlight) expose it and carry the overhead. CPU trigger would
definitely not do this.
Best regards,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161115/51071177/attachment.sig>
^ permalink raw reply
* wdt, gpio: move arch_initcall into subsys_initcall ?
From: Vladimir Zapolskiy @ 2016-11-15 11:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <582AE18A.2060405@denx.de>
Hello Heiko,
On 11/15/2016 12:20 PM, Heiko Schocher wrote:
> Hello,
>
> commit e188cbf7564f: "gpio: mxc: shift gpio_mxc_init() to subsys_initcall level"
> moves the gpio initialization of the mxc gpio driver
> from the arch_initcall level into subsys_initcall level.
>
> This leads now on mxc boards, which use a gpio wdt driver
> and the CONFIG_GPIO_WATCHDOG_ARCH_INITCALL option enabled,
> to unwanted driver probe deferrals during kernel boot.
>
> I see this currently on an imx6 based board (which has unfortunately
> 3 WDT: imx6 internal (disabled), gpio wdt and da9063 WDT ...).
>
> Also a side effect from above commit is, that the da9063 WDT driver
> is now probed before the gpio WDT driver ... so /dev/watchdog now
> does not point to the gpio_wdt, instead it points to the da9063 WDT.
>
> So there are 2 solutions possible:
>
> - add a CONFIG_GPIO_MCX_ARCH_INITCALL option
> in drivers/gpio/gpio-mxc.c like for the gpio_wdt.c driver?
in my opinion this is overly heavy solution and it might be
better to avoid it if possible.
I would rather prefer to reconsider GPIO_WATCHDOG_ARCH_INITCALL
usage in the watchdog driver.
Moreover adding this proposed GPIO_MCX_ARCH_INITCALL to call
the driver on arch level will result in deferring the GPIO driver.
> But how can we guarantee, that first the gpio driver and then
> the gpio_wdt driver gets probed?
>
> - move the arch_initcall in gpio_wdt.c into a subsys_initcall
> (Tested this, and the probe dereferral messages are gone ...)
>
> But this may results in problems on boards, which needs an early
> trigger on an gpio wdt ...
The level of "earliness" can not be defined in absolute time value
in any case, why decreasing the init level of the watchdog driver
to subsys level can cause problems? For that there should exist
some kind of a dependency on IC or PCB hardware level, can you
name it please?
Also please note that more than a half of all GPIO drivers settle
on subsys or later initcall level, this means that there is
an expected GPIO watchdog driver deferral for all of them.
I propose to send two patches for review:
1. remove GPIO_WATCHDOG_ARCH_INITCALL option completely and decouple
module_platform_driver() into arch_initcall() and module_exit()
unconditionally.
2. change arch_initcall() in the watchdog driver to subsys_initcall().
This change removes probe deferrals on boot, when the driver is
used with the most of the GPIO controllers.
> Other ideas?
>
> Thanks for all suggestions!
>
--
With best wishes,
Vladimir
^ permalink raw reply
* [PATCH] mxs-auart: count FIFO overrun errors
From: Wolfgang Ocker @ 2016-11-15 11:05 UTC (permalink / raw)
To: linux-arm-kernel
The mxs-auart driver does not count FIFO overrun errors. These errors never
appear in /proc/tty/driver/ttyAPP. This is because the OERR status bit is
masked by read_status_mask in the rx interrupt function, but the
AUART_STAT_OERR bit is never set in read_status_mask. The patch enables the
counting of overrun errors.
Signed-off-by: Wolfgang Ocker <weo@reccoware.de>
---
?drivers/tty/serial/mxs-auart.c | 2 +-
?1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 770454e0dfa3..8c1c9112b3fd 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -1016,7 +1016,7 @@ static void mxs_auart_settermios(struct uart_port *u,
? ctrl |= AUART_LINECTRL_EPS;
? }
?
- u->read_status_mask = 0;
+ u->read_status_mask = AUART_STAT_OERR;
?
? if (termios->c_iflag & INPCK)
? u->read_status_mask |= AUART_STAT_PERR;
--?
2.10.0
^ permalink raw reply related
* [PATCH fpga 1/9] fpga zynq: Add missing \n to messages
From: Matthias Brugger @ 2016-11-15 11:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478732303-13718-2-git-send-email-jgunthorpe@obsidianresearch.com>
On 09/11/16 23:58, Jason Gunthorpe wrote:
> Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Please add a commit message, although it is cristal clear what this
patch does :)
Regards,
Matthias
> ---
> drivers/fpga/zynq-fpga.c | 22 +++++++++++-----------
> 1 file changed, 11 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
> index c2fb4120bd62..e72340ea7323 100644
> --- a/drivers/fpga/zynq-fpga.c
> +++ b/drivers/fpga/zynq-fpga.c
> @@ -217,7 +217,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
> INIT_POLL_DELAY,
> INIT_POLL_TIMEOUT);
> if (err) {
> - dev_err(priv->dev, "Timeout waiting for PCFG_INIT");
> + dev_err(priv->dev, "Timeout waiting for PCFG_INIT\n");
> goto out_err;
> }
>
> @@ -231,7 +231,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
> INIT_POLL_DELAY,
> INIT_POLL_TIMEOUT);
> if (err) {
> - dev_err(priv->dev, "Timeout waiting for !PCFG_INIT");
> + dev_err(priv->dev, "Timeout waiting for !PCFG_INIT\n");
> goto out_err;
> }
>
> @@ -245,7 +245,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
> INIT_POLL_DELAY,
> INIT_POLL_TIMEOUT);
> if (err) {
> - dev_err(priv->dev, "Timeout waiting for PCFG_INIT");
> + dev_err(priv->dev, "Timeout waiting for PCFG_INIT\n");
> goto out_err;
> }
> }
> @@ -262,7 +262,7 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
> /* check that we have room in the command queue */
> status = zynq_fpga_read(priv, STATUS_OFFSET);
> if (status & STATUS_DMA_Q_F) {
> - dev_err(priv->dev, "DMA command queue full");
> + dev_err(priv->dev, "DMA command queue full\n");
> err = -EBUSY;
> goto out_err;
> }
> @@ -331,7 +331,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
> zynq_fpga_write(priv, INT_STS_OFFSET, intr_status);
>
> if (!((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) {
> - dev_err(priv->dev, "Error configuring FPGA");
> + dev_err(priv->dev, "Error configuring FPGA\n");
> err = -EFAULT;
> }
>
> @@ -426,7 +426,7 @@ static int zynq_fpga_probe(struct platform_device *pdev)
> priv->slcr = syscon_regmap_lookup_by_phandle(dev->of_node,
> "syscon");
> if (IS_ERR(priv->slcr)) {
> - dev_err(dev, "unable to get zynq-slcr regmap");
> + dev_err(dev, "unable to get zynq-slcr regmap\n");
> return PTR_ERR(priv->slcr);
> }
>
> @@ -434,26 +434,26 @@ static int zynq_fpga_probe(struct platform_device *pdev)
>
> priv->irq = platform_get_irq(pdev, 0);
> if (priv->irq < 0) {
> - dev_err(dev, "No IRQ available");
> + dev_err(dev, "No IRQ available\n");
> return priv->irq;
> }
>
> err = devm_request_irq(dev, priv->irq, zynq_fpga_isr, 0,
> dev_name(dev), priv);
> if (err) {
> - dev_err(dev, "unable to request IRQ");
> + dev_err(dev, "unable to request IRQ\n");
> return err;
> }
>
> priv->clk = devm_clk_get(dev, "ref_clk");
> if (IS_ERR(priv->clk)) {
> - dev_err(dev, "input clock not found");
> + dev_err(dev, "input clock not found\n");
> return PTR_ERR(priv->clk);
> }
>
> err = clk_prepare_enable(priv->clk);
> if (err) {
> - dev_err(dev, "unable to enable clock");
> + dev_err(dev, "unable to enable clock\n");
> return err;
> }
>
> @@ -465,7 +465,7 @@ static int zynq_fpga_probe(struct platform_device *pdev)
> err = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager",
> &zynq_fpga_ops, priv);
> if (err) {
> - dev_err(dev, "unable to register FPGA manager");
> + dev_err(dev, "unable to register FPGA manager\n");
> clk_unprepare(priv->clk);
> return err;
> }
>
^ permalink raw reply
* [PATCH v2] ARM: dts: da850: add the mstpri and ddrctl nodes
From: Bartosz Golaszewski @ 2016-11-15 11:00 UTC (permalink / raw)
To: linux-arm-kernel
Add the nodes for the MSTPRI configuration and DDR2/mDDR memory
controller drivers to da850.dtsi.
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
v1 -> v2:
- moved the priority controller node above the cfgchip node
- renamed added nodes to better reflect their purpose
arch/arm/boot/dts/da850.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
index 1bb1f6d..412eec6 100644
--- a/arch/arm/boot/dts/da850.dtsi
+++ b/arch/arm/boot/dts/da850.dtsi
@@ -210,6 +210,10 @@
};
};
+ prictrl: priority-controller at 14110 {
+ compatible = "ti,da850-mstpri";
+ reg = <0x14110 0x0c>;
+ };
cfgchip: chip-controller at 1417c {
compatible = "ti,da830-cfgchip", "syscon", "simple-mfd";
reg = <0x1417c 0x14>;
@@ -451,4 +455,8 @@
1 0 0x68000000 0x00008000>;
status = "disabled";
};
+ memctrl: memory-controller at b0000000 {
+ compatible = "ti,da850-ddr-controller";
+ reg = <0xb0000000 0xe8>;
+ };
};
--
2.9.3
^ permalink raw reply related
* LEDs that change brightness "itself" -- that's a trigger. Re: PM regression with LED changes in next-20161109
From: Jacek Anaszewski @ 2016-11-15 10:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161115103133.GA22860@amd>
On 11/15/2016 11:31 AM, Pavel Machek wrote:
> Hi!
>
>>> Hmm, v4 still calls led_notify_brightness_change(led_cdev)
>> >from both __led_set_brightness() and __led_set_brightness_blocking().
>>
>> Ugh, I see I accidentally send a v4 twice, instead of
>> calling the version which dropped those called v5 as
>> I should have, sorry.
>>
>> The v4 which I would like to see merged, the one with
>> those calls dropped, is here:
>>
>> https://patchwork.kernel.org/patch/9423093/
>
> Please, lets fix this properly.
>
> The LED you are talking about _has_ a trigger, implemented in
> hardware. That trigger can change LED brightness behind kernel's (and
> userspace's) back. Don't pretend the trigger does not exist, it does.
>
> And when you do that, you'll have nice place to report changes to
> userspace -- trigger can now export that information, and offer poll()
> interface.
Well, that sounds interesting. It is logically justifiable.
I initially proposed exactly this solution, with recently
added userspace LED being a trigger listener. It seems a bit
awkward though. How would you listen to the trigger events?
--
Best regards,
Jacek Anaszewski
^ permalink raw reply
* [PATCH resend] input: touchscreen: silead: Add regulator support
From: Hans de Goede @ 2016-11-15 10:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161114185057.GA7694@dtor-ws>
Hi,
On 14-11-16 19:50, Dmitry Torokhov wrote:
> Hi Hans,
>
> On Mon, Nov 14, 2016 at 03:45:02PM +0100, Hans de Goede wrote:
>> On some tablets the touchscreen controller is powered by seperate
>> regulators, add support for this.
>>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> Acked-by: Rob Herring <robh@kernel.org>
>> ---
>> .../bindings/input/touchscreen/silead_gsl1680.txt | 2 +
>> drivers/input/touchscreen/silead.c | 51 ++++++++++++++++++++--
>> 2 files changed, 49 insertions(+), 4 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/input/touchscreen/silead_gsl1680.txt b/Documentation/devicetree/bindings/input/touchscreen/silead_gsl1680.txt
>> index e844c3f..b726823 100644
>> --- a/Documentation/devicetree/bindings/input/touchscreen/silead_gsl1680.txt
>> +++ b/Documentation/devicetree/bindings/input/touchscreen/silead_gsl1680.txt
>> @@ -22,6 +22,8 @@ Optional properties:
>> - touchscreen-inverted-y : See touchscreen.txt
>> - touchscreen-swapped-x-y : See touchscreen.txt
>> - silead,max-fingers : maximum number of fingers the touchscreen can detect
>> +- vddio-supply : regulator phandle for controller VDDIO
>> +- avdd-supply : regulator phandle for controller AVDD
>>
>> Example:
>>
>> diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c
>> index f502c84..c6a1ae9 100644
>> --- a/drivers/input/touchscreen/silead.c
>> +++ b/drivers/input/touchscreen/silead.c
>> @@ -29,6 +29,7 @@
>> #include <linux/input/touchscreen.h>
>> #include <linux/pm.h>
>> #include <linux/irq.h>
>> +#include <linux/regulator/consumer.h>
>>
>> #include <asm/unaligned.h>
>>
>> @@ -72,6 +73,8 @@ enum silead_ts_power {
>> struct silead_ts_data {
>> struct i2c_client *client;
>> struct gpio_desc *gpio_power;
>> + struct regulator *vddio;
>> + struct regulator *avdd;
>> struct input_dev *input;
>> char fw_name[64];
>> struct touchscreen_properties prop;
>> @@ -465,21 +468,52 @@ static int silead_ts_probe(struct i2c_client *client,
>> if (client->irq <= 0)
>> return -ENODEV;
>>
>> + data->vddio = devm_regulator_get_optional(dev, "vddio");
>> + if (IS_ERR(data->vddio)) {
>> + if (PTR_ERR(data->vddio) == -EPROBE_DEFER)
>> + return -EPROBE_DEFER;
>> + data->vddio = NULL;
>
> Why do we ignore other errors?
Other errors indicate that the regulator is not there
specifically I think regulator_get_optional will return -ENOENT
in that case.
> If there is an issue reported by
> regulator framework we should net be ignoring it.
>
> Unless regulator is truly optional (i.e. chip can work with some
> functionality powered off) and not simply hidden (firmware takes care of
> powering up system),
In most systems the vddio is simply hardwired to the always-on
vcc-3.3V
> we should not be using regulator_get_optional():
> if regulator is absent from ACPI/DT/etc, regulator framework will supply
> dummy regulator that you can enable/disable and not bothering checking
> whether it is NULL or not.
Right, the downside of that is that it prints a msg about this
in dmesg which typically will lead to user questions.
Anyways if you prefer the non _optional variant I can do a v3
with that ...
> Also, please consider using devm_regulator_bulk_get().
Hmm, so I would get:
In struct silead_ts_data:
struct regulator_bulk_data regulators[2];
And then in probe() do:
data->regulators[0].supply = "vddio";
data->regulators[1].supply = "avdd";
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->regulators),
data->regulators);
if (ret)
return ret;
And modify the enable / disable code to match.
Yes I can see how that is better / cleaner and it also
answers the question whether or not to use get_optional.
Ok, I'll do a v2 switching to regulator_bulk_get.
Regards,
Hans
>
>> + }
>> +
>> + data->avdd = devm_regulator_get_optional(dev, "avdd");
>> + if (IS_ERR(data->avdd)) {
>> + if (PTR_ERR(data->avdd) == -EPROBE_DEFER)
>> + return -EPROBE_DEFER;
>> + data->avdd = NULL;
>> + }
>> +
>> + /*
>> + * Enable regulators at probe and disable them at remove, we need
>> + * to keep the chip powered otherwise it forgets its firmware.
>> + */
>> + if (data->vddio) {
>> + error = regulator_enable(data->vddio);
>> + if (error)
>> + return error;
>> + }
>> +
>> + if (data->avdd) {
>> + error = regulator_enable(data->avdd);
>> + if (error)
>> + goto disable_vddio;
>> + }
>
> Use devm_add_action_or_reset() to work regulator_bulk_disable call into
> devm stream. As it is you are leaving regulators on on unbind/remove.
>
>> +
>> /* Power GPIO pin */
>> data->gpio_power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW);
>> if (IS_ERR(data->gpio_power)) {
>> if (PTR_ERR(data->gpio_power) != -EPROBE_DEFER)
>> dev_err(dev, "Shutdown GPIO request failed\n");
>> - return PTR_ERR(data->gpio_power);
>> + error = PTR_ERR(data->gpio_power);
>> + goto disable_avdd;
>> }
>>
>> error = silead_ts_setup(client);
>> if (error)
>> - return error;
>> + goto disable_avdd;
>>
>> error = silead_ts_request_input_dev(data);
>> if (error)
>> - return error;
>> + goto disable_avdd;
>>
>> error = devm_request_threaded_irq(dev, client->irq,
>> NULL, silead_ts_threaded_irq_handler,
>> @@ -487,10 +521,19 @@ static int silead_ts_probe(struct i2c_client *client,
>> if (error) {
>> if (error != -EPROBE_DEFER)
>> dev_err(dev, "IRQ request failed %d\n", error);
>> - return error;
>> + goto disable_avdd;
>> }
>>
>> return 0;
>> +
>> +disable_avdd:
>> + if (data->avdd)
>> + regulator_disable(data->avdd);
>> +disable_vddio:
>> + if (data->vddio)
>> + regulator_disable(data->vddio);
>> +
>> + return error;
>> }
>>
>> static int __maybe_unused silead_ts_suspend(struct device *dev)
>> --
>> 2.9.3
>>
>
> Thanks.
>
^ permalink raw reply
* [PATCH v2 2/6] mfd: stm32-adc: Add support for stm32 ADC
From: Fabrice Gasnier @ 2016-11-15 10:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161114164701.GA2668@dell>
On 11/14/2016 05:47 PM, Lee Jones wrote:
> On Sat, 12 Nov 2016, Jonathan Cameron wrote:
>
>> On 10/11/16 16:18, Fabrice Gasnier wrote:
>>> Add core driver for STMicroelectronics STM32 ADC (Analog to Digital
>>> Converter). STM32 ADC can be composed of up to 3 ADCs with shared
>>> resources like clock prescaler, common interrupt line and analog
>>> reference voltage.
>>> This core driver basically manages shared resources.
>>>
>>> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
>> Looks good to me (other than the build issue obviously ;)
Hi Jonathan,
Thanks for your review.
I'll fix build issue, sure ;-)
>>
>> The fun bit will be trying to keep the whole thing this clean as you
>> add the more 'interesting' functionality. *fingers crossed*
Yes... But in the end, splitting shared resources in core driver makes
it more simple.
Not sure there will be more complexity here.
>>
>> Acked-by: Jonathan Cameron <jic23@kernel.org>
> There isn't anything MFD about this driver.
>
> Please move it into IIO.
Hmm, there is no other sub sysbtem that may be used here, ADC driver
belongs to IIO.
Also, of_platform_populate() is being used here. This can perfectly be
called from within IIO.
Jonathan, can this "stm32-adc-core" driver be moved to, and live in
drivers/iio/adc ?
(e.g. in addition to stm32-adc iio driver)
Is it ok for you ?
Please advise,
Best Regards,
Fabrice
>
>>> ---
>>> drivers/mfd/Kconfig | 14 ++
>>> drivers/mfd/Makefile | 1 +
>>> drivers/mfd/stm32-adc-core.c | 301 +++++++++++++++++++++++++++++++++++++
>>> include/linux/mfd/stm32-adc-core.h | 52 +++++++
>>> 4 files changed, 368 insertions(+)
>>> create mode 100644 drivers/mfd/stm32-adc-core.c
>>> create mode 100644 include/linux/mfd/stm32-adc-core.h
>>>
>>> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
>>> index c6df644..2580cee 100644
>>> --- a/drivers/mfd/Kconfig
>>> +++ b/drivers/mfd/Kconfig
>>> @@ -1152,6 +1152,20 @@ config MFD_PALMAS
>>> If you say yes here you get support for the Palmas
>>> series of PMIC chips from Texas Instruments.
>>>
>>> +config MFD_STM32_ADC
>>> + tristate "STMicroelectronics STM32 adc"
>>> + depends on ARCH_STM32 || COMPILE_TEST
>>> + depends on OF
>>> + select MFD_CORE
>>> + select REGULATOR
>>> + select REGULATOR_FIXED_VOLTAGE
>>> + help
>>> + Select this option to enable the core driver for STMicroelectronics
>>> + STM32 analog-to-digital converter (ADC).
>>> +
>>> + This driver can also be built as a module. If so, the module
>>> + will be called stm32-adc-core.
>>> +
>>> config TPS6105X
>>> tristate "TI TPS61050/61052 Boost Converters"
>>> depends on I2C
>>> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
>>> index 9834e66..4571506 100644
>>> --- a/drivers/mfd/Makefile
>>> +++ b/drivers/mfd/Makefile
>>> @@ -185,6 +185,7 @@ obj-$(CONFIG_MFD_INTEL_LPSS_PCI) += intel-lpss-pci.o
>>> obj-$(CONFIG_MFD_INTEL_LPSS_ACPI) += intel-lpss-acpi.o
>>> obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
>>> obj-$(CONFIG_MFD_PALMAS) += palmas.o
>>> +obj-$(CONFIG_MFD_STM32_ADC) += stm32-adc-core.o
>>> obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o
>>> obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o
>>> obj-$(CONFIG_MFD_RK808) += rk808.o
>>> diff --git a/drivers/mfd/stm32-adc-core.c b/drivers/mfd/stm32-adc-core.c
>>> new file mode 100644
>>> index 0000000..bcf52fb
>>> --- /dev/null
>>> +++ b/drivers/mfd/stm32-adc-core.c
>>> @@ -0,0 +1,301 @@
>>> +/*
>>> + * This file is part of STM32 ADC driver
>>> + *
>>> + * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
>>> + * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
>>> + *
>>> + * Inspired from: fsl-imx25-tsadc
>>> + *
>>> + * License type: GPLv2
>>> + *
>>> + * 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.
>>> + *
>>> + * 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, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#include <linux/clk.h>
>>> +#include <linux/interrupt.h>
>>> +#include <linux/irqchip/chained_irq.h>
>>> +#include <linux/irqdesc.h>
>>> +#include <linux/irqdomain.h>
>>> +#include <linux/mfd/stm32-adc-core.h>
>>> +#include <linux/module.h>
>>> +#include <linux/of_device.h>
>>> +#include <linux/regulator/consumer.h>
>>> +#include <linux/slab.h>
>>> +
>>> +/* STM32F4 - common registers for all ADC instances: 1, 2 & 3 */
>>> +#define STM32F4_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00)
>>> +#define STM32F4_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x04)
>>> +
>>> +/* STM32F4_ADC_CSR - bit fields */
>>> +#define STM32F4_EOC3 BIT(17)
>>> +#define STM32F4_EOC2 BIT(9)
>>> +#define STM32F4_EOC1 BIT(1)
>>> +
>>> +/* STM32F4_ADC_CCR - bit fields */
>>> +#define STM32F4_ADC_ADCPRE_SHIFT 16
>>> +#define STM32F4_ADC_ADCPRE_MASK GENMASK(17, 16)
>>> +
>>> +/* STM32 F4 maximum analog clock rate (from datasheet) */
>>> +#define STM32F4_ADC_MAX_CLK_RATE 36000000
>>> +
>>> +/**
>>> + * struct stm32_adc_priv - stm32 ADC core private data
>>> + * @irq: irq for ADC block
>>> + * @domain: irq domain reference
>>> + * @aclk: clock reference for the analog circuitry
>>> + * @vref: regulator reference
>>> + * @common: common data for all ADC instances
>>> + */
>>> +struct stm32_adc_priv {
>>> + int irq;
>>> + struct irq_domain *domain;
>>> + struct clk *aclk;
>>> + struct regulator *vref;
>>> + struct stm32_adc_common common;
>>> +};
>>> +
>>> +static struct stm32_adc_priv *to_stm32_adc_priv(struct stm32_adc_common *com)
>>> +{
>>> + return container_of(com, struct stm32_adc_priv, common);
>>> +}
>>> +
>>> +/* STM32F4 ADC internal common clock prescaler division ratios */
>>> +static int stm32f4_pclk_div[] = {2, 4, 6, 8};
>>> +
>>> +/**
>>> + * stm32f4_adc_clk_sel() - Select stm32f4 ADC common clock prescaler
>>> + * @priv: stm32 ADC core private data
>>> + * Select clock prescaler used for analog conversions, before using ADC.
>>> + */
>>> +static int stm32f4_adc_clk_sel(struct platform_device *pdev,
>>> + struct stm32_adc_priv *priv)
>>> +{
>>> + unsigned long rate;
>>> + u32 val;
>>> + int i;
>>> +
>>> + rate = clk_get_rate(priv->aclk);
>>> + for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) {
>>> + if ((rate / stm32f4_pclk_div[i]) <= STM32F4_ADC_MAX_CLK_RATE)
>>> + break;
>>> + }
>>> + if (i >= ARRAY_SIZE(stm32f4_pclk_div))
>>> + return -EINVAL;
>>> +
>>> + val = readl_relaxed(priv->common.base + STM32F4_ADC_CCR);
>>> + val &= ~STM32F4_ADC_ADCPRE_MASK;
>>> + val |= i << STM32F4_ADC_ADCPRE_SHIFT;
>>> + writel_relaxed(val, priv->common.base + STM32F4_ADC_CCR);
>>> +
>>> + dev_dbg(&pdev->dev, "Using analog clock source at %ld kHz\n",
>>> + rate / (stm32f4_pclk_div[i] * 1000));
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +/* ADC common interrupt for all instances */
>>> +static void stm32_adc_irq_handler(struct irq_desc *desc)
>>> +{
>>> + struct stm32_adc_priv *priv = irq_desc_get_handler_data(desc);
>>> + struct irq_chip *chip = irq_desc_get_chip(desc);
>>> + u32 status;
>>> +
>>> + chained_irq_enter(chip, desc);
>>> + status = readl_relaxed(priv->common.base + STM32F4_ADC_CSR);
>>> +
>>> + if (status & STM32F4_EOC1)
>>> + generic_handle_irq(irq_find_mapping(priv->domain, 0));
>>> +
>>> + if (status & STM32F4_EOC2)
>>> + generic_handle_irq(irq_find_mapping(priv->domain, 1));
>>> +
>>> + if (status & STM32F4_EOC3)
>>> + generic_handle_irq(irq_find_mapping(priv->domain, 2));
>>> +
>>> + chained_irq_exit(chip, desc);
>>> +};
>>> +
>>> +static int stm32_adc_domain_map(struct irq_domain *d, unsigned int irq,
>>> + irq_hw_number_t hwirq)
>>> +{
>>> + irq_set_chip_data(irq, d->host_data);
>>> + irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_level_irq);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static void stm32_adc_domain_unmap(struct irq_domain *d, unsigned int irq)
>>> +{
>>> + irq_set_chip_and_handler(irq, NULL, NULL);
>>> + irq_set_chip_data(irq, NULL);
>>> +}
>>> +
>>> +static const struct irq_domain_ops stm32_adc_domain_ops = {
>>> + .map = stm32_adc_domain_map,
>>> + .unmap = stm32_adc_domain_unmap,
>>> + .xlate = irq_domain_xlate_onecell,
>>> +};
>>> +
>>> +static int stm32_adc_irq_probe(struct platform_device *pdev,
>>> + struct stm32_adc_priv *priv)
>>> +{
>>> + struct device_node *np = pdev->dev.of_node;
>>> +
>>> + priv->irq = platform_get_irq(pdev, 0);
>>> + if (priv->irq < 0) {
>>> + dev_err(&pdev->dev, "failed to get irq\n");
>>> + return priv->irq;
>>> + }
>>> +
>>> + priv->domain = irq_domain_add_simple(np, STM32_ADC_MAX_ADCS, 0,
>>> + &stm32_adc_domain_ops,
>>> + priv);
>>> + if (!priv->domain) {
>>> + dev_err(&pdev->dev, "Failed to add irq domain\n");
>>> + return -ENOMEM;
>>> + }
>>> +
>>> + irq_set_chained_handler(priv->irq, stm32_adc_irq_handler);
>>> + irq_set_handler_data(priv->irq, priv);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static void stm32_adc_irq_remove(struct platform_device *pdev,
>>> + struct stm32_adc_priv *priv)
>>> +{
>>> + int hwirq;
>>> +
>>> + for (hwirq = 0; hwirq < STM32_ADC_MAX_ADCS; hwirq++)
>>> + irq_dispose_mapping(irq_find_mapping(priv->domain, hwirq));
>>> + irq_domain_remove(priv->domain);
>>> + irq_set_chained_handler(priv->irq, NULL);
>>> +}
>>> +
>>> +static int stm32_adc_probe(struct platform_device *pdev)
>>> +{
>>> + struct stm32_adc_priv *priv;
>>> + struct device_node *np = pdev->dev.of_node;
>>> + struct resource *res;
>>> + int ret;
>>> +
>>> + if (!pdev->dev.of_node)
>>> + return -ENODEV;
>>> +
>>> + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
>>> + if (!priv)
>>> + return -ENOMEM;
>>> +
>>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> + priv->common.base = devm_ioremap_resource(&pdev->dev, res);
>>> + if (IS_ERR(priv->common.base))
>>> + return PTR_ERR(priv->common.base);
>>> +
>>> + priv->vref = devm_regulator_get(&pdev->dev, "vref");
>>> + if (IS_ERR(priv->vref)) {
>>> + ret = PTR_ERR(priv->vref);
>>> + dev_err(&pdev->dev, "vref get failed, %d\n", ret);
>>> + return ret;
>>> + }
>>> +
>>> + ret = regulator_enable(priv->vref);
>>> + if (ret < 0) {
>>> + dev_err(&pdev->dev, "vref enable failed\n");
>>> + return ret;
>>> + }
>>> +
>>> + ret = regulator_get_voltage(priv->vref);
>>> + if (ret < 0) {
>>> + dev_err(&pdev->dev, "vref get voltage failed, %d\n", ret);
>>> + goto err_regulator_disable;
>>> + }
>>> + priv->common.vref_mv = ret / 1000;
>>> + dev_dbg(&pdev->dev, "vref+=%dmV\n", priv->common.vref_mv);
>>> +
>>> + priv->aclk = devm_clk_get(&pdev->dev, "adc");
>>> + if (IS_ERR(priv->aclk)) {
>>> + ret = PTR_ERR(priv->aclk);
>>> + dev_err(&pdev->dev, "Can't get 'adc' clock\n");
>>> + goto err_regulator_disable;
>>> + }
>>> +
>>> + ret = clk_prepare_enable(priv->aclk);
>>> + if (ret < 0) {
>>> + dev_err(&pdev->dev, "adc clk enable failed\n");
>>> + goto err_regulator_disable;
>>> + }
>>> +
>>> + ret = stm32f4_adc_clk_sel(pdev, priv);
>>> + if (ret < 0) {
>>> + dev_err(&pdev->dev, "adc clk selection failed\n");
>>> + goto err_clk_disable;
>>> + }
>>> +
>>> + ret = stm32_adc_irq_probe(pdev, priv);
>>> + if (ret < 0)
>>> + goto err_clk_disable;
>>> +
>>> + platform_set_drvdata(pdev, &priv->common);
>>> +
>>> + ret = of_platform_populate(np, NULL, NULL, &pdev->dev);
>>> + if (ret < 0) {
>>> + dev_err(&pdev->dev, "failed to populate DT children\n");
>>> + goto err_irq_remove;
>>> + }
>>> +
>>> + return 0;
>>> +
>>> +err_irq_remove:
>>> + stm32_adc_irq_remove(pdev, priv);
>>> +
>>> +err_clk_disable:
>>> + clk_disable_unprepare(priv->aclk);
>>> +
>>> +err_regulator_disable:
>>> + regulator_disable(priv->vref);
>>> +
>>> + return ret;
>>> +}
>>> +
>>> +static int stm32_adc_remove(struct platform_device *pdev)
>>> +{
>>> + struct stm32_adc_common *common = platform_get_drvdata(pdev);
>>> + struct stm32_adc_priv *priv = to_stm32_adc_priv(common);
>>> +
>>> + of_platform_depopulate(&pdev->dev);
>>> + stm32_adc_irq_remove(pdev, priv);
>>> + clk_disable_unprepare(priv->aclk);
>>> + regulator_disable(priv->vref);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static const struct of_device_id stm32_adc_of_match[] = {
>>> + { .compatible = "st,stm32f4-adc-core" },
>>> +};
>>> +MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
>>> +
>>> +static struct platform_driver stm32_adc_driver = {
>>> + .probe = stm32_adc_probe,
>>> + .remove = stm32_adc_remove,
>>> + .driver = {
>>> + .name = "stm32-adc-core",
>>> + .of_match_table = stm32_adc_of_match,
>>> + },
>>> +};
>>> +module_platform_driver(stm32_adc_driver);
>>> +
>>> +MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
>>> +MODULE_DESCRIPTION("STMicroelectronics STM32 ADC MFD driver");
>>> +MODULE_LICENSE("GPL v2");
>>> +MODULE_ALIAS("platform:stm32-adc-core");
>>> diff --git a/include/linux/mfd/stm32-adc-core.h b/include/linux/mfd/stm32-adc-core.h
>>> new file mode 100644
>>> index 0000000..081fa5f
>>> --- /dev/null
>>> +++ b/include/linux/mfd/stm32-adc-core.h
>>> @@ -0,0 +1,52 @@
>>> +/*
>>> + * This file is part of STM32 ADC driver
>>> + *
>>> + * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
>>> + * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
>>> + *
>>> + * License type: GPLv2
>>> + *
>>> + * 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.
>>> + *
>>> + * 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, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#ifndef __STM32_ADC_H
>>> +#define __STM32_ADC_H
>>> +
>>> +/*
>>> + * STM32 - ADC global register map
>>> + * ________________________________________________________
>>> + * | Offset | Register |
>>> + * --------------------------------------------------------
>>> + * | 0x000 | Master ADC1 |
>>> + * --------------------------------------------------------
>>> + * | 0x100 | Slave ADC2 |
>>> + * --------------------------------------------------------
>>> + * | 0x200 | Slave ADC3 |
>>> + * --------------------------------------------------------
>>> + * | 0x300 | Master & Slave common regs |
>>> + * --------------------------------------------------------
>>> + */
>>> +#define STM32_ADC_MAX_ADCS 3
>>> +#define STM32_ADCX_COMN_OFFSET 0x300
>>> +
>>> +/**
>>> + * struct stm32_adc_common - stm32 ADC driver common data (for all instances)
>>> + * @base: control registers base cpu addr
>>> + * @vref_mv: vref voltage (mv)
>>> + */
>>> +struct stm32_adc_common {
>>> + void __iomem *base;
>>> + int vref_mv;
>>> +};
>>> +
>>> +#endif
>>>
^ permalink raw reply
* [PATCH] ARM64: dts: bcm2837-rpi-3-b: remove incorrect pwr LED
From: Gerd Hoffmann @ 2016-11-15 10:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <871sydfueq.fsf@eliezer.anholt.net>
On Mo, 2016-11-14 at 16:39 -0800, Eric Anholt wrote:
> Stefan Wahren <stefan.wahren@i2se.com> writes:
>
> > Hi Eric,
> >
> > [add Gerd to CC]
> >
> >> Eric Anholt <eric@anholt.net> hat am 11. November 2016 um 18:38 geschrieben:
> >>
> >>
> >> From: Andrea Merello <andrea.merello@gmail.com>
> >>
> >> We are incorrectly defining the pwr LED, attaching it to a gpio line
> >> that is wired to the Wi-Fi SDIO module (which fails due to this).
> >
> > i agree with the intention of this patch, but is the upstream kernel really
> > affected? I can't see any compatible for the Wifi interface.
>
> The wifi isn't in the DT yet because the driver isn't merged. Some
> progress was made on that a while ago, but people asked for more
> cleanups so it's still living out of tree.
some low-hanging fruits (codestyle mostly) are done, but more work is
needed (fix messy timeout handling, make dma work). Didn't happed yet
due to -ENOTIME. My current state is here:
https://www.kraxel.org/cgit/linux/log/?h=bcm2837-wifi
In case anyone wants pick it up feel free to do so (but please tell me
so we avoid duplicating work).
cheers,
Gerd
^ permalink raw reply
* [PATCH v4 4/4] ARM: dts: da850: Add the usb otg device node
From: Sekhar Nori @ 2016-11-15 10:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4fa9243a-47ec-80a7-bb79-fa65b4fc4d4a@lechnology.com>
On Friday 04 November 2016 09:10 AM, David Lechner wrote:
>
>> + usb0: usb at 200000 {
>> + compatible = "ti,da830-musb";
>> + reg = <0x200000 0x10000>;
>> + interrupts = <58>;
>> + interrupt-names = "mc";
>> + dr_mode = "otg";
>
> Isn't this the default value? Could we omit the dr_mode property here?
dr_mode is set to otg in quite a few dts files already. Even if its the
default, I think it makes it easy to recognize the mode immediately.
Thanks,
Sekhar
^ permalink raw reply
* [PATCH v4 4/4] ARM: dts: da850: Add the usb otg device node
From: Sekhar Nori @ 2016-11-15 10:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478188752-22447-5-git-send-email-abailon@baylibre.com>
On Thursday 03 November 2016 09:29 PM, Alexandre Bailon wrote:
> This adds the device tree node for the usb otg
> controller present in the da850 family of SoC's.
> This also enables the otg usb controller for the lcdk board.
>
> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> ---
> arch/arm/boot/dts/da850-lcdk.dts | 8 ++++++++
> arch/arm/boot/dts/da850.dtsi | 15 +++++++++++++++
> 2 files changed, 23 insertions(+)
>
> diff --git a/arch/arm/boot/dts/da850-lcdk.dts b/arch/arm/boot/dts/da850-lcdk.dts
> index 7b8ab21..9f5040c 100644
> --- a/arch/arm/boot/dts/da850-lcdk.dts
> +++ b/arch/arm/boot/dts/da850-lcdk.dts
> @@ -158,6 +158,14 @@
> rx-num-evt = <32>;
> };
>
> +&usb_phy {
> + status = "okay";
> + };
As mentioned by David already, this node needs to be removed. Please
rebase this on top of latest linux-davinci/master when ready for merging
(driver changes accepted).
> +
> +&usb0 {
> + status = "okay";
> +};
> +
> &aemif {
> pinctrl-names = "default";
> pinctrl-0 = <&nand_pins>;
> diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
> index f79e1b9..322a31a 100644
> --- a/arch/arm/boot/dts/da850.dtsi
> +++ b/arch/arm/boot/dts/da850.dtsi
> @@ -372,6 +372,21 @@
> >;
> status = "disabled";
> };
> + usb_phy: usb-phy {
> + compatible = "ti,da830-usb-phy";
> + #phy-cells = <1>;
> + status = "disabled";
> + };
> + usb0: usb at 200000 {
> + compatible = "ti,da830-musb";
> + reg = <0x200000 0x10000>;
> + interrupts = <58>;
> + interrupt-names = "mc";
> + dr_mode = "otg";
> + phys = <&usb_phy 0>;
> + phy-names = "usb-phy";
> + status = "disabled";
> + };
Can you separate out the soc specific changes from board changes? Please
place the usb0 node above the mdio node. I am trying to get to a rough
ordering based on reg property.
Thanks,
Sekhar
^ permalink raw reply
* [PATCH v9 2/4] soc: mediatek: Init MT8173 scpsys driver earlier
From: Honghui Zhang @ 2016-11-15 10:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477879702.6649.4.camel@mtksdaap41>
On Mon, 2016-10-31 at 10:08 +0800, James Liao wrote:
> On Mon, 2016-10-31 at 01:08 +0100, Matthias Brugger wrote:
> > Hi James,
> >
> > On 10/20/2016 10:56 AM, James Liao wrote:
> > > Some power domain comsumers may init before module_init.
> > > So the power domain provider (scpsys) need to be initialized
> > > earlier too.
> > >
> > > Take an example for our IOMMU (M4U) and SMI. SMI is a bridge
> > > between IOMMU and multimedia HW. SMI is responsible to
> > > enable/disable iommu and help transfer data for each multimedia
> > > HW. Both of them have to wait until the power and clocks are
> > > enabled.
> > >
> > > So scpsys driver should be initialized before SMI, and SMI should
> > > be initialized before IOMMU, and then init IOMMU consumers
> > > (display/vdec/venc/camera etc.).
> > >
> > > IOMMU is subsys_init by default. So we need to init scpsys driver
> > > before subsys_init.
> > >
> > > Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
> > > Reviewed-by: Kevin Hilman <khilman@baylibre.com>
> > > ---
> >
> > I didn't applied this patch for now.
> > I answered you in v7 of this series [1]. I would prefer to see if we can
> > fix that otherwise.
> >
> > Would be great if you or Yong could provide some feedback.
> >
Hi, Matthias,
Yong had verified your propose and it seems didn't work[1].
But I'm looking at the recently merged device link patches[2], it maybe
could help with the probe sequence issue.
If we set the iommu client as the smi larb's device consumer of
device_link with the DL_DEV_PROBING flags, it will be wait for smi
larb's probe done. But I'm not test that solution yet, need to do a bit
more test to verify this.
thanks.
[1]
https://lists.linuxfoundation.org/pipermail/iommu/2016-July/018034.html
[2]https://www.mail-archive.com/linux-kernel at vger.kernel.org/msg1261311.html
> > Thanks,
> > Matthias
> >
> > [1] https://patchwork.kernel.org/patch/9397405/
> >
> > > drivers/soc/mediatek/mtk-scpsys.c | 19 ++++++++++++++++++-
> > > 1 file changed, 18 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
> > > index fa9ee69..dd7a07d 100644
> > > --- a/drivers/soc/mediatek/mtk-scpsys.c
> > > +++ b/drivers/soc/mediatek/mtk-scpsys.c
> > > @@ -613,4 +613,21 @@ static int scpsys_probe(struct platform_device *pdev)
> > > .of_match_table = of_match_ptr(of_scpsys_match_tbl),
> > > },
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* [PATCH] reset: hisilicon: add a polarity cell for reset line specifier
From: Philipp Zabel @ 2016-11-15 10:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479193794-18350-1-git-send-email-xuejiancheng@hisilicon.com>
Hi Jiancheng,
Am Dienstag, den 15.11.2016, 15:09 +0800 schrieb Jiancheng Xue:
> Add a polarity cell for reset line specifier. If the reset line
> is asserted when the register bit is 1, the polarity is
> normal. Otherwise, it is inverted.
>
> Signed-off-by: Jiancheng Xue <xuejiancheng@hisilicon.com>
> ---
> .../devicetree/bindings/clock/hisi-crg.txt | 11 ++++---
> arch/arm/boot/dts/hi3519.dtsi | 2 +-
> drivers/clk/hisilicon/reset.c | 36 ++++++++++++++++------
> 3 files changed, 33 insertions(+), 16 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/clock/hisi-crg.txt b/Documentation/devicetree/bindings/clock/hisi-crg.txt
> index e3919b6..fcbb4f3 100644
> --- a/Documentation/devicetree/bindings/clock/hisi-crg.txt
> +++ b/Documentation/devicetree/bindings/clock/hisi-crg.txt
> @@ -25,19 +25,20 @@ to specify the clock which they consume.
>
> All these identifier could be found in <dt-bindings/clock/hi3519-clock.h>.
>
> -- #reset-cells: should be 2.
> +- #reset-cells: should be 3.
>
> A reset signal can be controlled by writing a bit register in the CRG module.
> -The reset specifier consists of two cells. The first cell represents the
> +The reset specifier consists of three cells. The first cell represents the
> register offset relative to the base address. The second cell represents the
> -bit index in the register.
> +bit index in the register. The third cell represents the polarity of the reset
> +line (0 for normal, 1 for inverted).
What is normal and what is inverted? Please specify which is active-high
and which is active-low.
>
> Example: CRG nodes
> CRG: clock-reset-controller at 12010000 {
> compatible = "hisilicon,hi3519-crg";
> reg = <0x12010000 0x10000>;
> #clock-cells = <1>;
> - #reset-cells = <2>;
> + #reset-cells = <3>;
> };
>
> Example: consumer nodes
> @@ -45,5 +46,5 @@ i2c0: i2c at 12110000 {
> compatible = "hisilicon,hi3519-i2c";
> reg = <0x12110000 0x1000>;
> clocks = <&CRG HI3519_I2C0_RST>;
> - resets = <&CRG 0xe4 0>;
> + resets = <&CRG 0xe4 0 0>;
> };
> diff --git a/arch/arm/boot/dts/hi3519.dtsi b/arch/arm/boot/dts/hi3519.dtsi
> index 5729ecf..b7cb182 100644
> --- a/arch/arm/boot/dts/hi3519.dtsi
> +++ b/arch/arm/boot/dts/hi3519.dtsi
> @@ -50,7 +50,7 @@
> crg: clock-reset-controller at 12010000 {
> compatible = "hisilicon,hi3519-crg";
> #clock-cells = <1>;
> - #reset-cells = <2>;
> + #reset-cells = <3>;
That is a backwards incompatible change. Which I think in this case
could be tolerated, because there are no users yet of the reset
controller. Or are there any hi3519 based device trees that use the
resets out in the wild? If there are, the driver must continue to
support old device trees with two reset-cells. Which would not be
trivial because currently the core checks in reset_control_get that
rcdev->of_n_reset_cells is equal to the #reset-cells value from DT.
One possibility to get around changing the binding would be to stuff the
polarity bit into low bits of the register address cell.
Either way, I'm not very happy with blowing up the complexity of the
reset phandles at the reset consumer side.
If you do change the binding, is there any way you could change from a
register address + bit offset binding to an index based binding with the
information about reset bit positions and polarities contained in the
driver, or in the crg node, similarly to the ti-syscon-reset bindings?
That would also improve consistency with clock bindings, which already
use a number as identifier.
[...]
> @@ -59,14 +65,19 @@ static int hisi_reset_assert(struct reset_controller_dev *rcdev,
> unsigned long flags;
> u32 offset, reg;
> u8 bit;
> + bool polarity;
>
> offset = (id & HISI_RESET_OFFSET_MASK) >> HISI_RESET_OFFSET_SHIFT;
> - bit = id & HISI_RESET_BIT_MASK;
> + bit = (id & HISI_RESET_BIT_MASK) >> HISI_RESET_BIT_SHIFT;
> + polarity = id & HISI_RESET_POLARITY_MASK;
>
> spin_lock_irqsave(&rstc->lock, flags);
>
> reg = readl(rstc->membase + offset);
> - writel(reg | BIT(bit), rstc->membase + offset);
> + if (polarity)
> + writel(reg & ~BIT(bit), rstc->membase + offset);
> + else
> + writel(reg | BIT(bit), rstc->membase + offset);
So there is no hardware polarity setting, which means the
ti-syscon-reset bindings could fit in this case.
regards
Philipp
^ permalink raw reply
* [PATCH v3 2/2] arm64: Support systems without FP/ASIMD
From: Suzuki K Poulose @ 2016-11-15 10:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161114114858.GB3096@e104818-lin.cambridge.arm.com>
On 14/11/16 11:48, Catalin Marinas wrote:
> Hi Suzuki,
>
>> +static inline bool system_supports_fpsimd(void)
>> +{
>> + return !cpus_have_const_cap(ARM64_HAS_NO_FPSIMD);
>> +}
>
> Any particular reason why using negation instead of a ARM64_HAS_FPSIMD?
> A potential problem would be the default cpus_have_const_cap()
> implementation and the default static key having a slight performance
> impact.
The negation was chosen to avoid hotpatching in the most common case.
But as you said, it has an impact on the other side. I think doing
a one time hotpatching at boot time is more optimal than penalising
a bunch of other users throughout the execution. I will take a look
at changing it back to a ARM64_HAS_FPSIMD.
>> },
>> + {
>> + /* FP/SIMD is not implemented */
>> + .capability = ARM64_HAS_NO_FPSIMD,
>> + .def_scope = SCOPE_SYSTEM,
>> + .min_field_value = 0,
>> + .matches = has_no_fpsimd,
>> + },
>
> If we go for negation, I don't think we need a min_field_value at all,
> the matching is done by the has_no_fpsimd() function.
You're right.
Suzuki
^ permalink raw reply
* [PATCH] ARM: dma-mapping: preallocate DMA-debug hash tables in pure_initcall
From: Marek Szyprowski @ 2016-11-15 10:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <3289056.5bg7xtivbS@wuerfel>
On 2016-11-15 11:31, Arnd Bergmann wrote:
> On Tuesday, November 15, 2016 11:04:55 AM CET Marek Szyprowski wrote:
>> fs_initcall is definitely too late to initialize DMA-debug hash tables,
>> because some drivers might get probed and use DMA mapping framework
>> already in core_initcall. Late initialization of DMA-debug results in
>> false warning about accessing memory, that was not allocated, like this
>> one:
> To ask the obvious question: what driver does DMA allocations in a
> core_initcall, and have you tried to change that first?
See the attached stack trace.
Exynos IOMMU driver does that in its domain_alloc implementation (to
allocate
first level of PTE) and I see no easy way to avoid that, as iommu
domains are
allocated very early (as well as the whole IOMMU initialization and
attaching
to the devices). Exynos IOMMU driver has to use DMA-mapping API for PTE
management, because the IOMMU controllers are not coherent with system
CPU and
there is no other way to ensure proper CPU cache management.
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ 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