Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [linux-sunxi] Re: [PATCH 1/3] mfd: axp20x: Add mfd driver for axp20x PMIC
From: Carlo Caione @ 2014-02-10 22:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140210211900.GC32042@lee--X1>

On Mon, Feb 10, 2014 at 10:19 PM, Lee Jones <lee.jones@linaro.org> wrote:
>> This patch introduces the preliminary support for PMICs X-Powers AXP202
>> and AXP209. The core contains support only for two sub-modules (PEK
>> and regulators) that will be added with two different patch-sets.
>>
>> Signed-off-by: Carlo Caione <carlo@caione.org>
>> ---
>>  drivers/mfd/Kconfig        |  12 +++
>>  drivers/mfd/Makefile       |   1 +
>>  drivers/mfd/axp20x.c       | 251 +++++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/mfd/axp20x.h | 178 ++++++++++++++++++++++++++++++++
>>  4 files changed, 442 insertions(+)
>>  create mode 100644 drivers/mfd/axp20x.c
>>  create mode 100644 include/linux/mfd/axp20x.h
>>
>> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
>> index dd67158..33d38c4 100644
>> --- a/drivers/mfd/Kconfig
>> +++ b/drivers/mfd/Kconfig
>> @@ -59,6 +59,18 @@ config MFD_AAT2870_CORE
>>         additional drivers must be enabled in order to use the
>>         functionality of the device.
>
> <snip>
>
>> diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
>> new file mode 100644
>> index 0000000..efd0cb3
>> --- /dev/null
>> +++ b/drivers/mfd/axp20x.c
>> @@ -0,0 +1,251 @@
>> +/*
>
> A nice descriptive title here would be good.

Agree.

>> + * Author: Carlo Caione <carlo@caione.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#include <linux/err.h>
>> +#include <linux/i2c.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/pm_runtime.h>
>> +#include <linux/regmap.h>
>> +#include <linux/slab.h>
>> +#include <linux/regulator/consumer.h>
>> +#include <linux/mfd/axp20x.h>
>> +#include <linux/mfd/core.h>
>> +#include <linux/of_device.h>
>> +#include <linux/of_irq.h>
>> +
>> +static const struct regmap_range axp20x_writeable_ranges[] = {
>> +     {
>> +             .range_min = AXP20X_DATA(0),
>> +             .range_max = AXP20X_IRQ5_STATE,
>> +     }, {
>> +             .range_min = AXP20X_DCDC_MODE,
>> +             .range_max = AXP20X_FG_RES,
>> +     },
>> +};
>> +
>> +static const struct regmap_range axp20x_volatile_ranges[] = {
>> +     {
>> +             .range_min = AXP20X_IRQ1_EN,
>> +             .range_max = AXP20X_IRQ5_STATE,
>> +     },
>> +};
>> +
>> +static const struct regmap_access_table axp20x_writeable_table = {
>> +     .yes_ranges     = axp20x_writeable_ranges,
>> +     .n_yes_ranges   = ARRAY_SIZE(axp20x_writeable_ranges),
>> +};
>> +
>> +static const struct regmap_access_table axp20x_volatile_table = {
>> +     .yes_ranges     = axp20x_volatile_ranges,
>> +     .n_yes_ranges   = ARRAY_SIZE(axp20x_volatile_ranges),
>> +};
>> +
>> +static struct resource axp20x_pek_resources[] = {
>> +     {
>> +             .name   = "PEK_DBR",
>> +             .start  = AXP20X_IRQ_PEK_RIS_EDGE,
>> +             .end    = AXP20X_IRQ_PEK_RIS_EDGE,
>> +             .flags  = IORESOURCE_IRQ,
>> +     },
>> +     {
>> +             .name   = "PEK_DBF",
>> +             .start  = AXP20X_IRQ_PEK_FAL_EDGE,
>> +             .end    = AXP20X_IRQ_PEK_FAL_EDGE,
>> +             .flags  = IORESOURCE_IRQ,
>> +     },
>> +
>
> Superfluous new line.
>
>> +};
>> +
>> +static const struct regmap_config axp20x_regmap_config = {
>> +     .reg_bits       = 8,
>> +     .val_bits       = 8,
>> +     .wr_table       = &axp20x_writeable_table,
>> +     .volatile_table = &axp20x_volatile_table,
>> +     .max_register   = AXP20X_FG_RES,
>> +     .cache_type     = REGCACHE_RBTREE,
>> +};
>> +
>> +#define AXP20X_IRQ(_irq, _off, _mask) \
>> +     [AXP20X_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
>> +
>> +static const struct regmap_irq axp20x_regmap_irqs[] = {
>> +     AXP20X_IRQ(ACIN_OVER_V,         0, 7),
>> +     AXP20X_IRQ(ACIN_PLUGIN,         0, 6),
>> +     AXP20X_IRQ(ACIN_REMOVAL,        0, 5),
>> +     AXP20X_IRQ(VBUS_OVER_V,         0, 4),
>> +     AXP20X_IRQ(VBUS_PLUGIN,         0, 3),
>> +     AXP20X_IRQ(VBUS_REMOVAL,        0, 2),
>> +     AXP20X_IRQ(VBUS_V_LOW,          0, 1),
>> +     AXP20X_IRQ(BATT_PLUGIN,         1, 7),
>> +     AXP20X_IRQ(BATT_REMOVAL,        1, 6),
>> +     AXP20X_IRQ(BATT_ENT_ACT_MODE,   1, 5),
>> +     AXP20X_IRQ(BATT_EXIT_ACT_MODE,  1, 4),
>> +     AXP20X_IRQ(CHARG,               1, 3),
>> +     AXP20X_IRQ(CHARG_DONE,          1, 2),
>> +     AXP20X_IRQ(BATT_TEMP_HIGH,      1, 1),
>> +     AXP20X_IRQ(BATT_TEMP_LOW,       1, 0),
>> +     AXP20X_IRQ(DIE_TEMP_HIGH,       2, 7),
>> +     AXP20X_IRQ(CHARG_I_LOW,         2, 6),
>> +     AXP20X_IRQ(DCDC1_V_LONG,        2, 5),
>> +     AXP20X_IRQ(DCDC2_V_LONG,        2, 4),
>> +     AXP20X_IRQ(DCDC3_V_LONG,        2, 3),
>> +     AXP20X_IRQ(PEK_SHORT,           2, 1),
>> +     AXP20X_IRQ(PEK_LONG,            2, 0),
>> +     AXP20X_IRQ(N_OE_PWR_ON,         3, 7),
>> +     AXP20X_IRQ(N_OE_PWR_OFF,        3, 6),
>> +     AXP20X_IRQ(VBUS_VALID,          3, 5),
>> +     AXP20X_IRQ(VBUS_NOT_VALID,      3, 4),
>> +     AXP20X_IRQ(VBUS_SESS_VALID,     3, 3),
>> +     AXP20X_IRQ(VBUS_SESS_END,       3, 2),
>> +     AXP20X_IRQ(LOW_PWR_LVL1,        3, 1),
>> +     AXP20X_IRQ(LOW_PWR_LVL2,        3, 0),
>> +     AXP20X_IRQ(TIMER,               4, 7),
>> +     AXP20X_IRQ(PEK_RIS_EDGE,        4, 6),
>> +     AXP20X_IRQ(PEK_FAL_EDGE,        4, 5),
>> +     AXP20X_IRQ(GPIO3_INPUT,         4, 3),
>> +     AXP20X_IRQ(GPIO2_INPUT,         4, 2),
>> +     AXP20X_IRQ(GPIO1_INPUT,         4, 1),
>> +     AXP20X_IRQ(GPIO0_INPUT,         4, 0),
>> +};
>
> Where are these handled i.e. where is the irq_handler located?

Each one is used by a different driver for each subsystem of the MFD,
so each driver will have a specific irq_handler. I need the full list
here to register with regmap_add_irq_chip() the generic
regmap_irq_thread.

>> +static const struct regmap_irq_chip axp20x_regmap_irq_chip = {
>> +     .name                   = "axp20x_irq_chip",
>> +     .status_base            = AXP20X_IRQ1_STATE,
>> +     .ack_base               = AXP20X_IRQ1_STATE,
>> +     .mask_base              = AXP20X_IRQ1_EN,
>> +     .num_regs               = 5,
>> +     .irqs                   = axp20x_regmap_irqs,
>> +     .num_irqs               = ARRAY_SIZE(axp20x_regmap_irqs),
>> +     .mask_invert            = 1,
>
> This is a bool; true or false please.
>
>> +     .init_ack_masked        = 1,
>
> Same here.

I'll fix both in v2.

>> +};
>> +
>> +static struct mfd_cell axp20x_cells[] = {
>> +     {
>> +             .name           = "axp20x-pek",
>> +             .of_compatible  = "x-powers,axp20x-pek",
>> +             .num_resources  = ARRAY_SIZE(axp20x_pek_resources),
>> +             .resources      = axp20x_pek_resources,
>
> I already saw the comments about these.
>
>> +     }, {
>> +             .name           = "axp20x-regulator",
>> +     },
>> +};
>> +
>> +const struct of_device_id axp20x_of_match[] = {
>> +     { .compatible = "x-powers,axp20x", .data = (void *)AXP20X },
>
> There's no need to add device IDs if you only support one device.

Ok. But what if in the future we want to add a new device?

>> +     { },
>> +};
>> +
>> +static struct axp20x_dev *axp20x_pm_power_off;
>
> This looks pretty unconventional. What's the point of it?

On a single board we can have multiple AXPs so I track which one is in
charge of powering off the board (and to get the correct device in the
axp20x_power_off())

>> +static void axp20x_power_off(void)
>> +{
>> +     regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL, 0x80);
>
> What does the 0x80 do exactly? Think about #defining.

It's only used here, but I'll #define it.

>> +}
>> +
>> +static int axp20x_i2c_probe(struct i2c_client *i2c,
>> +                      const struct i2c_device_id *id)
>> +{
>> +     struct axp20x_dev *axp20x;
>> +     const struct of_device_id *of_id;
>> +     int ret;
>> +
>> +     axp20x = devm_kzalloc(&i2c->dev, sizeof(*axp20x), GFP_KERNEL);
>> +     if (!axp20x)
>> +             return -ENOMEM;
>> +
>> +     of_id = of_match_device(axp20x_of_match, &i2c->dev);
>> +     if (!of_id) {
>> +             dev_err(&i2c->dev, "Unable to setup AXP20X data\n");
>> +             return -ENODEV;
>> +     }
>> +     axp20x->variant = (int) of_id->data;
>
> Lots of code here surrounding added device support, but only one
> device is supported. Why so?

Because at the moment I support only axp202 and axp209 but I wanted
something future-proof

>> +     axp20x->i2c_client = i2c;
>> +     i2c_set_clientdata(i2c, axp20x);
>> +
>> +     axp20x->dev = &i2c->dev;
>> +     dev_set_drvdata(axp20x->dev, axp20x);
>
> Do you make use of all this saving of the device container?
>
> If so, where?

In the drivers for subsystems (input, regulators, gpio, etc..)

> Also:
>   i2c_set_clientdata(i2c)
>
> and:
>   dev_set_drvdata(i2c->dev);
>
> ... do exactly the same thing i.e. set i2c->dev->p->device_data.

Right.

>> +     axp20x->regmap = devm_regmap_init_i2c(i2c, &axp20x_regmap_config);
>> +     if (IS_ERR(axp20x->regmap)) {
>> +             ret = PTR_ERR(axp20x->regmap);
>> +             dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
>> +             return ret;
>> +     }
>> +
>> +     axp20x->irq = i2c->irq;
>> +     ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq,
>> +                               IRQF_ONESHOT | IRQF_SHARED, -1,
>> +                               &axp20x_regmap_irq_chip,
>> +                               &axp20x->regmap_irqc);
>> +     if (ret != 0) {
>
> It's more succinct to say:
>   if (!ret)

Agree

>> +             dev_err(&i2c->dev, "failed to add irq chip: %d\n", ret);
>> +             return ret;
>> +     }
>> +
>> +     ret = mfd_add_devices(axp20x->dev, -1, axp20x_cells,
>> +                           ARRAY_SIZE(axp20x_cells), NULL, 0, NULL);
>> +     if (ret != 0) {
>> +             dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
>> +             goto mfd_err;
>> +     }
>> +
>> +     if (!pm_power_off) {
>> +             axp20x_pm_power_off = axp20x;
>> +             pm_power_off = axp20x_power_off;
>> +     }
>
> Can you describe to me what you're using the pm_power_off call-back
> for please?

It's meant to poweroff the board

>> +     dev_info(&i2c->dev, "AXP20X driver loaded\n");
>> +
>> +     return 0;
>> +
>> +mfd_err:
>> +     regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc);
>> +
>> +     return ret;
>> +}
>> +
>> +static int axp20x_i2c_remove(struct i2c_client *i2c)
>> +{
>> +     struct axp20x_dev *axp20x = i2c_get_clientdata(i2c);
>> +
>> +     if (axp20x == axp20x_pm_power_off) {
>> +             axp20x_pm_power_off = NULL;
>> +             pm_power_off = NULL;
>> +     }
>> +
>> +     mfd_remove_devices(axp20x->dev);
>> +     regmap_del_irq_chip(axp20x->i2c_client->irq, axp20x->regmap_irqc);
>> +
>> +     return 0;
>> +}
>> +
>> +static const struct i2c_device_id axp20x_i2c_id[] = {
>> +     { "axp20x", AXP20X },
>
> It doesn't look like you're using this ID either?

No, I am not. I'll fix it in v2.

>> +     { }
>> +};
>> +MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
>> +
>> +static struct i2c_driver axp20x_i2c_driver = {
>> +     .driver = {
>> +             .name   = "axp20x",
>> +             .owner  = THIS_MODULE,
>> +             .of_match_table = of_match_ptr(axp20x_of_match),
>> +     },
>> +     .probe          = axp20x_i2c_probe,
>> +     .remove         = axp20x_i2c_remove,
>> +     .id_table       = axp20x_i2c_id,
>> +};
>> +
>> +module_i2c_driver(axp20x_i2c_driver);
>> +
>> +MODULE_DESCRIPTION("PMIC MFD core driver for AXP20X");
>> +MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
>> +MODULE_LICENSE("GPL");
>> diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
>> new file mode 100644
>> index 0000000..94d99fd
>> --- /dev/null
>> +++ b/include/linux/mfd/axp20x.h
>> @@ -0,0 +1,178 @@
>> +/*
>> + * Functions to access AXP20X power management chip.
>> + *
>> + * Copyright (C) 2013, Carlo Caione <carlo@caione.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#ifndef __LINUX_MFD_AXP20X_H
>> +#define __LINUX_MFD_AXP20X_H
>> +
>> +#define AXP20X                               0
>> +
>> +#define AXP20X_DATA(m)                       (0x04 + (m))
>
> This is not a great name for a macro.  'data' and 'value' seldom make
> for good names for variables/macros.  Please replace it with something
> more descriptive.

Agree. I'll change it.

> In fact, on closer inspection it appears as though you only use this
> once while defining writable registers.  What happened to registers
> 0x00 to 0x03, and why have the top registers below been omitted from
> the range(s)?

All the registers defined here can be used by the drivers of the
different subsystems including this header file, thus all the
registers are reported here though they are not directly used by the
core driver.
About the range you are right, I'll fix it in v2. Thanks for noticing.

>> +
>> +/* Power supply */
>> +#define AXP20X_PWR_INPUT_STATUS              0x00
>> +#define AXP20X_PWR_OP_MODE           0x01
>> +#define AXP20X_USB_OTG_STATUS                0x02
>> +#define AXP20X_PWR_OUT_CTRL          0x12
>> +#define AXP20X_DCDC2_V_OUT           0x23
>> +#define AXP20X_DCDC2_LDO3_V_SCAL     0x25
>> +#define AXP20X_DCDC3_V_OUT           0x27
>> +#define AXP20X_LDO24_V_OUT           0x28
>> +#define AXP20X_LDO3_V_OUT            0x29
>> +#define AXP20X_VBUS_IPSOUT_MGMT              0x30
>> +#define AXP20X_V_OFF                 0x31
>> +#define AXP20X_OFF_CTRL                      0x32
>> +#define AXP20X_CHRG_CTRL1            0x33
>> +#define AXP20X_CHRG_CTRL2            0x34
>> +#define AXP20X_CHRG_BAK_CTRL         0x35
>> +#define AXP20X_PEK_KEY                       0x36
>> +#define AXP20X_DCDC_FREQ             0x37
>> +#define AXP20X_V_LTF_CHRG            0x38
>> +#define AXP20X_V_HTF_CHRG            0x39
>> +#define AXP20X_APS_WARN_L1           0x3a
>> +#define AXP20X_APS_WARN_L2           0x3b
>> +#define AXP20X_V_LTF_DISCHRG         0x3c
>> +#define AXP20X_V_HTF_DISCHRG         0x3d
>> +
>> +/* Interrupt */
>> +#define AXP20X_IRQ1_EN                       0x40
>> +#define AXP20X_IRQ2_EN                       0x41
>> +#define AXP20X_IRQ3_EN                       0x42
>> +#define AXP20X_IRQ4_EN                       0x43
>> +#define AXP20X_IRQ5_EN                       0x44
>> +#define AXP20X_IRQ1_STATE            0x48
>> +#define AXP20X_IRQ2_STATE            0x49
>> +#define AXP20X_IRQ3_STATE            0x4a
>> +#define AXP20X_IRQ4_STATE            0x4b
>> +#define AXP20X_IRQ5_STATE            0x4c
>> +
>> +/* ADC */
>> +#define AXP20X_ACIN_V_ADC_H          0x56
>> +#define AXP20X_ACIN_V_ADC_L          0x57
>> +#define AXP20X_ACIN_I_ADC_H          0x58
>> +#define AXP20X_ACIN_I_ADC_L          0x59
>> +#define AXP20X_VBUS_V_ADC_H          0x5a
>> +#define AXP20X_VBUS_V_ADC_L          0x5b
>> +#define AXP20X_VBUS_I_ADC_H          0x5c
>> +#define AXP20X_VBUS_I_ADC_L          0x5d
>> +#define AXP20X_TEMP_ADC_H            0x5e
>> +#define AXP20X_TEMP_ADC_L            0x5f
>> +#define AXP20X_TS_IN_H                       0x62
>> +#define AXP20X_TS_IN_L                       0x63
>> +#define AXP20X_GPIO0_V_ADC_H         0x64
>> +#define AXP20X_GPIO0_V_ADC_L         0x65
>> +#define AXP20X_GPIO1_V_ADC_H         0x66
>> +#define AXP20X_GPIO1_V_ADC_L         0x67
>> +#define AXP20X_PWR_BATT_H            0x70
>> +#define AXP20X_PWR_BATT_M            0x71
>> +#define AXP20X_PWR_BATT_L            0x72
>> +#define AXP20X_BATT_V_H                      0x78
>> +#define AXP20X_BATT_V_L                      0x79
>> +#define AXP20X_BATT_CHRG_I_H         0x7a
>> +#define AXP20X_BATT_CHRG_I_L         0x7b
>> +#define AXP20X_BATT_DISCHRG_I_H              0x7c
>> +#define AXP20X_BATT_DISCHRG_I_L              0x7d
>> +#define AXP20X_IPSOUT_V_HIGH_H               0x7e
>> +#define AXP20X_IPSOUT_V_HIGH_L               0x7f
>> +
>> +/* Power supply */
>> +#define AXP20X_DCDC_MODE             0x80
>> +#define AXP20X_ADC_EN1                       0x82
>> +#define AXP20X_ADC_EN2                       0x83
>> +#define AXP20X_ADC_RATE                      0x84
>> +#define AXP20X_GPIO10_IN_RANGE               0x85
>> +#define AXP20X_GPIO1_ADC_IRQ_RIS     0x86
>> +#define AXP20X_GPIO1_ADC_IRQ_FAL     0x87
>> +#define AXP20X_TIMER_CTRL            0x8a
>> +#define AXP20X_VBUS_MON                      0x8b
>> +#define AXP20X_OVER_TMP                      0x8f
>> +
>> +/* GPIO */
>> +#define AXP20X_GPIO0_CTRL            0x90
>> +#define AXP20X_LDO5_V_OUT            0x91
>> +#define AXP20X_GPIO1_CTRL            0x92
>> +#define AXP20X_GPIO2_CTRL            0x93
>> +#define AXP20X_GPIO20_SS             0x94
>> +#define AXP20X_GPIO3_CTRL            0x95
>> +
>> +/* Battery */
>> +#define AXP20X_CHRG_CC_31_24         0xb0
>> +#define AXP20X_CHRG_CC_23_16         0xb1
>> +#define AXP20X_CHRG_CC_15_8          0xb2
>> +#define AXP20X_CHRG_CC_7_0           0xb3
>> +#define AXP20X_DISCHRG_CC_31_24              0xb4
>> +#define AXP20X_DISCHRG_CC_23_16              0xb5
>> +#define AXP20X_DISCHRG_CC_15_8               0xb6
>> +#define AXP20X_DISCHRG_CC_7_0                0xb7
>> +#define AXP20X_CC_CTRL                       0xb8
>> +#define AXP20X_FG_RES                        0xb9
>> +
>> +/* Regulators IDs */
>> +enum {
>> +     AXP20X_LDO1 = 0,
>> +     AXP20X_LDO2,
>> +     AXP20X_LDO3,
>> +     AXP20X_LDO4,
>> +     AXP20X_LDO5,
>> +     AXP20X_DCDC2,
>> +     AXP20X_DCDC3,
>> +     AXP20X_REG_ID_MAX,
>> +};
>> +
>> +/* IRQs */
>> +enum {
>> +     AXP20X_IRQ_ACIN_OVER_V = 1,
>> +     AXP20X_IRQ_ACIN_PLUGIN,
>> +     AXP20X_IRQ_ACIN_REMOVAL,
>> +     AXP20X_IRQ_VBUS_OVER_V,
>> +     AXP20X_IRQ_VBUS_PLUGIN,
>> +     AXP20X_IRQ_VBUS_REMOVAL,
>> +     AXP20X_IRQ_VBUS_V_LOW,
>> +     AXP20X_IRQ_BATT_PLUGIN,
>> +     AXP20X_IRQ_BATT_REMOVAL,
>> +     AXP20X_IRQ_BATT_ENT_ACT_MODE,
>> +     AXP20X_IRQ_BATT_EXIT_ACT_MODE,
>> +     AXP20X_IRQ_CHARG,
>> +     AXP20X_IRQ_CHARG_DONE,
>> +     AXP20X_IRQ_BATT_TEMP_HIGH,
>> +     AXP20X_IRQ_BATT_TEMP_LOW,
>> +     AXP20X_IRQ_DIE_TEMP_HIGH,
>> +     AXP20X_IRQ_CHARG_I_LOW,
>> +     AXP20X_IRQ_DCDC1_V_LONG,
>> +     AXP20X_IRQ_DCDC2_V_LONG,
>> +     AXP20X_IRQ_DCDC3_V_LONG,
>> +     AXP20X_IRQ_PEK_SHORT = 22,
>> +     AXP20X_IRQ_PEK_LONG,
>> +     AXP20X_IRQ_N_OE_PWR_ON,
>> +     AXP20X_IRQ_N_OE_PWR_OFF,
>> +     AXP20X_IRQ_VBUS_VALID,
>> +     AXP20X_IRQ_VBUS_NOT_VALID,
>> +     AXP20X_IRQ_VBUS_SESS_VALID,
>> +     AXP20X_IRQ_VBUS_SESS_END,
>> +     AXP20X_IRQ_LOW_PWR_LVL1,
>> +     AXP20X_IRQ_LOW_PWR_LVL2,
>> +     AXP20X_IRQ_TIMER,
>> +     AXP20X_IRQ_PEK_RIS_EDGE,
>> +     AXP20X_IRQ_PEK_FAL_EDGE,
>> +     AXP20X_IRQ_GPIO3_INPUT,
>> +     AXP20X_IRQ_GPIO2_INPUT,
>> +     AXP20X_IRQ_GPIO1_INPUT,
>> +     AXP20X_IRQ_GPIO0_INPUT,
>> +};
>> +
>> +struct axp20x_dev {
>> +     struct device                   *dev;
>> +     struct i2c_client               *i2c_client;
>> +     struct regmap                   *regmap;
>> +     struct regmap_irq_chip_data     *regmap_irqc;
>> +     int                             variant;
>> +     int                             irq;
>> +};
>
> Is this used anywhere else except in the MFD driver?
>
> If not, consider moving it into the *.c file.

Yes, it is used by drivers of subsystems.

Thank you,

-- 
Carlo Caione

^ permalink raw reply

* [linux-sunxi] Re: [PATCH 3/3] mfd: axp20x: Add bindings documentation
From: Carlo Caione @ 2014-02-10 22:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140210220102.GG3192@lukather>

On Mon, Feb 10, 2014 at 11:01 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> On Mon, Feb 10, 2014 at 09:37:37PM +0100, Carlo Caione wrote:
>> >> +Sub-nodes
>> >> +* regulators : Contain the regulator nodes. The regulators are bound using
>> >> +            their name as listed here: dcdc2, dcdc3, ldo1, ldo2, ldo3,
>> >> +            ldo4, ldo5.
>> >> +            The bindings details of individual regulator device can be found in:
>> >> +            Documentation/devicetree/bindings/regulator/regulator.txt with the
>> >> +            exception of:
>> >
>> > I'm guessing this is where you differentiate between AXP202 and
>> > AXP209?
>>
>> Not really. AXP202 and AXP209 have the same regulators (with the same
>> constrains)
>
> Ok. What's the difference between the two then?

Honestly I have no idea. For what I have seen (core, PEK and
regulators) AXP202 and AXP209 are identical.

-- 
Carlo Caione

^ permalink raw reply

* [PATCH v2 1/3] net: stmmac:sti: Add STi SOC glue driver.
From: David Miller @ 2014-02-10 22:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391770525-24349-1-git-send-email-srinivas.kandagatla@st.com>

From: <srinivas.kandagatla@st.com>
Date: Fri, 7 Feb 2014 10:55:25 +0000

> +		if (dwmac->interface == PHY_INTERFACE_MODE_MII ||
> +			dwmac->interface == PHY_INTERFACE_MODE_GMII) {

This is not indented correctly, the first character on the second line should
line up exactly at the column after the openning parenthesis on the first
line.

The objective is not to indent using only TAB characters, which you
are doing here.

Rather, the objective is to use the appropriate number of TAB _and_
space characters necessary to reach the proper column.

> +		const char *rs;
> +		err = of_property_read_string(np, "st,tx-retime-src", &rs);

Please add an empty line after the local variable declaration.

> +		if (!strcasecmp(rs, "clk_125"))
> +			dwmac->is_tx_retime_src_clk_125 = true;
> +
> +	}

That empty line is superfluous, please delete it.

^ permalink raw reply

* [PATCH v7 00/18] Armada 370/XP watchdog
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel

Yet another round. This time, addressing Guenter's comment about the nowayout
parameter. So, to allow for proper nowayout behavior, we now restrict the
initial watchdog stop; which is only done if the watchdog is not properly
enabled.

I've dropped the clocksource patch which was previously part of the series.
The patch is independent and will be merged through the subsystem maintainer,
Daniel Lezcano.

Also, I've updated the multi_v7_defconfig, as per Jason Cooper request.

This series depends on Sebastian's irqchip fixes to clear the bridge irqs
cause, which Jason picked here:

  http://git.infradead.org/linux-mvebu.git mvebu-next/irqchip-fixes

Wim: Can we take all the watchdog changes through mvebu, with your Ack?
This way, we can sort out the irqchip dependency.

Ezequiel Garcia (18):
  watchdog: orion: Add clock error handling
  watchdog: orion: Use atomic access for shared registers
  watchdog: orion: Remove unused macros
  watchdog: orion: Make sure the watchdog is initially stopped
  watchdog: orion: Handle the interrupt so it's properly acked
  watchdog: orion: Make RSTOUT register a separate resource
  watchdog: orion: Remove unneeded BRIDGE_CAUSE clear
  watchdog: orion: Introduce an orion_watchdog device structure
  watchdog: orion: Introduce per-compatible of_device_id data
  watchdog: orion: Add per-compatible clock initialization
  watchdog: orion: Add per-compatible watchdog start implementation
  watchdog: orion: Add support for Armada 370 and Armada XP SoC
  ARM: mvebu: Enable Armada 370/XP watchdog in the devicetree
  ARM: kirkwood: Add RSTOUT 'reg' entry to devicetree
  ARM: dove: Enable Dove watchdog in the devicetree
  watchdog: orion: Enable the build on ARCH_MVEBU
  ARM: mvebu: Enable watchdog support in defconfig
  ARM: dove: Enable watchdog support in the defconfig

 .../devicetree/bindings/watchdog/marvel.txt        |  11 +-
 arch/arm/boot/dts/armada-370-xp.dtsi               |   4 +
 arch/arm/boot/dts/armada-370.dtsi                  |   5 +
 arch/arm/boot/dts/armada-xp.dtsi                   |   6 +
 arch/arm/boot/dts/dove.dtsi                        |   8 +
 arch/arm/boot/dts/kirkwood.dtsi                    |   2 +-
 arch/arm/configs/dove_defconfig                    |   2 +
 arch/arm/configs/multi_v7_defconfig                |   2 +
 arch/arm/configs/mvebu_defconfig                   |   2 +
 arch/arm/mach-dove/include/mach/bridge-regs.h      |   1 +
 arch/arm/mach-kirkwood/include/mach/bridge-regs.h  |   1 +
 arch/arm/mach-mv78xx0/include/mach/bridge-regs.h   |   1 +
 arch/arm/mach-orion5x/include/mach/bridge-regs.h   |   1 +
 arch/arm/plat-orion/common.c                       |  10 +-
 drivers/watchdog/Kconfig                           |   2 +-
 drivers/watchdog/orion_wdt.c                       | 381 ++++++++++++++++-----
 16 files changed, 352 insertions(+), 87 deletions(-)

-- 
1.8.1.5

^ permalink raw reply

* [PATCH v7 01/18] watchdog: orion: Add clock error handling
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392073237-2554-1-git-send-email-ezequiel.garcia@free-electrons.com>

This commit adds a check for clk_prepare_enable success and introduces
an error path to disable the clock properly.

Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 drivers/watchdog/orion_wdt.c | 29 +++++++++++++++++++----------
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index f7722a4..7f19fa3 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -151,17 +151,24 @@ static int orion_wdt_probe(struct platform_device *pdev)
 	clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "Orion Watchdog missing clock\n");
-		return -ENODEV;
+		return PTR_ERR(clk);
 	}
-	clk_prepare_enable(clk);
+	ret = clk_prepare_enable(clk);
+	if (ret)
+		return ret;
 	wdt_tclk = clk_get_rate(clk);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENODEV;
+	if (!res) {
+		ret = -ENODEV;
+		goto disable_clk;
+	}
+
 	wdt_reg = devm_ioremap(&pdev->dev, res->start, resource_size(res));
-	if (!wdt_reg)
-		return -ENOMEM;
+	if (!wdt_reg) {
+		ret = -ENOMEM;
+		goto disable_clk;
+	}
 
 	wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk;
 
@@ -171,14 +178,16 @@ static int orion_wdt_probe(struct platform_device *pdev)
 
 	watchdog_set_nowayout(&orion_wdt, nowayout);
 	ret = watchdog_register_device(&orion_wdt);
-	if (ret) {
-		clk_disable_unprepare(clk);
-		return ret;
-	}
+	if (ret)
+		goto disable_clk;
 
 	pr_info("Initial timeout %d sec%s\n",
 		orion_wdt.timeout, nowayout ? ", nowayout" : "");
 	return 0;
+
+disable_clk:
+	clk_disable_unprepare(clk);
+	return ret;
 }
 
 static int orion_wdt_remove(struct platform_device *pdev)
-- 
1.8.1.5

^ permalink raw reply related

* [PATCH v7 02/18] watchdog: orion: Use atomic access for shared registers
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392073237-2554-1-git-send-email-ezequiel.garcia@free-electrons.com>

Since the timer control register is shared with the clocksource driver,
use the recently introduced atomic_io_clear_set() to access such register.
Given the watchdog core already provides serialization for all the
watchdog ops, this commit allows to remove the spinlock entirely.

Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 drivers/watchdog/orion_wdt.c | 42 +++++-------------------------------------
 1 file changed, 5 insertions(+), 37 deletions(-)

diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index 7f19fa3..b92a991 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -20,7 +20,6 @@
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/spinlock.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/of.h>
@@ -46,25 +45,16 @@ static unsigned int wdt_max_duration;	/* (seconds) */
 static struct clk *clk;
 static unsigned int wdt_tclk;
 static void __iomem *wdt_reg;
-static DEFINE_SPINLOCK(wdt_lock);
 
 static int orion_wdt_ping(struct watchdog_device *wdt_dev)
 {
-	spin_lock(&wdt_lock);
-
 	/* Reload watchdog duration */
 	writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL);
-
-	spin_unlock(&wdt_lock);
 	return 0;
 }
 
 static int orion_wdt_start(struct watchdog_device *wdt_dev)
 {
-	u32 reg;
-
-	spin_lock(&wdt_lock);
-
 	/* Set watchdog duration */
 	writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL);
 
@@ -72,48 +62,26 @@ static int orion_wdt_start(struct watchdog_device *wdt_dev)
 	writel(~WDT_INT_REQ, BRIDGE_CAUSE);
 
 	/* Enable watchdog timer */
-	reg = readl(wdt_reg + TIMER_CTRL);
-	reg |= WDT_EN;
-	writel(reg, wdt_reg + TIMER_CTRL);
+	atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, WDT_EN);
 
 	/* Enable reset on watchdog */
-	reg = readl(RSTOUTn_MASK);
-	reg |= WDT_RESET_OUT_EN;
-	writel(reg, RSTOUTn_MASK);
-
-	spin_unlock(&wdt_lock);
+	atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN);
 	return 0;
 }
 
 static int orion_wdt_stop(struct watchdog_device *wdt_dev)
 {
-	u32 reg;
-
-	spin_lock(&wdt_lock);
-
 	/* Disable reset on watchdog */
-	reg = readl(RSTOUTn_MASK);
-	reg &= ~WDT_RESET_OUT_EN;
-	writel(reg, RSTOUTn_MASK);
+	atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, 0);
 
 	/* Disable watchdog timer */
-	reg = readl(wdt_reg + TIMER_CTRL);
-	reg &= ~WDT_EN;
-	writel(reg, wdt_reg + TIMER_CTRL);
-
-	spin_unlock(&wdt_lock);
+	atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, 0);
 	return 0;
 }
 
 static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev)
 {
-	unsigned int time_left;
-
-	spin_lock(&wdt_lock);
-	time_left = readl(wdt_reg + WDT_VAL) / wdt_tclk;
-	spin_unlock(&wdt_lock);
-
-	return time_left;
+	return readl(wdt_reg + WDT_VAL) / wdt_tclk;
 }
 
 static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev,
-- 
1.8.1.5

^ permalink raw reply related

* [PATCH v7 03/18] watchdog: orion: Remove unused macros
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392073237-2554-1-git-send-email-ezequiel.garcia@free-electrons.com>

These are not used anywhere so it's safe to remove them.

Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 drivers/watchdog/orion_wdt.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index b92a991..6746033 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -33,8 +33,6 @@
 #define WDT_VAL			0x0024
 
 #define WDT_MAX_CYCLE_COUNT	0xffffffff
-#define WDT_IN_USE		0
-#define WDT_OK_TO_CLOSE		1
 
 #define WDT_RESET_OUT_EN	BIT(1)
 #define WDT_INT_REQ		BIT(3)
-- 
1.8.1.5

^ permalink raw reply related

* [PATCH v7 04/18] watchdog: orion: Make sure the watchdog is initially stopped
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392073237-2554-1-git-send-email-ezequiel.garcia@free-electrons.com>

Having the watchdog initially fully stopped is important to avoid
any spurious watchdog triggers, in case the registers are not in
its reset state.

If the watchdog rstout is enabled and the watchdog counter running,
this initial stop is not performed, to comply with the 'nowayout'
parameter.

Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 drivers/watchdog/orion_wdt.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index 6746033..e10b0b1 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -77,6 +77,16 @@ static int orion_wdt_stop(struct watchdog_device *wdt_dev)
 	return 0;
 }
 
+static int orion_wdt_enabled(void)
+{
+	bool enabled, running;
+
+	enabled = readl(RSTOUTn_MASK) & WDT_RESET_OUT_EN;
+	running = readl(wdt_reg + TIMER_CTRL) & WDT_EN;
+
+	return enabled && running;
+}
+
 static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev)
 {
 	return readl(wdt_reg + WDT_VAL) / wdt_tclk;
@@ -142,6 +152,15 @@ static int orion_wdt_probe(struct platform_device *pdev)
 	orion_wdt.max_timeout = wdt_max_duration;
 	watchdog_init_timeout(&orion_wdt, heartbeat, &pdev->dev);
 
+	/*
+	 * Let's make sure the watchdog is fully stopped, unless it's
+	 * explicitly enabled. This may be the case if the module was
+	 * removed and re-insterted, or if the bootloader explicitly
+	 * set a running watchdog before booting the kernel.
+	 */
+	if (!orion_wdt_enabled())
+		orion_wdt_stop(&orion_wdt);
+
 	watchdog_set_nowayout(&orion_wdt, nowayout);
 	ret = watchdog_register_device(&orion_wdt);
 	if (ret)
-- 
1.8.1.5

^ permalink raw reply related

* [PATCH v7 05/18] watchdog: orion: Handle the interrupt so it's properly acked
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392073237-2554-1-git-send-email-ezequiel.garcia@free-electrons.com>

DT-enabled plaforms, where the irqchip driver for the brigde interrupt
controller is available, can handle the watchdog IRQ properly. Therefore,
request the interrupt and add a dummy handler that merely calls panic().

This is done in order to have an initial 'ack' of the interruption,
which clears the watchdog state.

Furthermore, since some platforms don't have such IRQ, this commit
makes the interrupt specification optional.

Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 .../devicetree/bindings/watchdog/marvel.txt        |  2 ++
 drivers/watchdog/orion_wdt.c                       | 24 +++++++++++++++++++++-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/watchdog/marvel.txt b/Documentation/devicetree/bindings/watchdog/marvel.txt
index 5dc8d30..0731fbd 100644
--- a/Documentation/devicetree/bindings/watchdog/marvel.txt
+++ b/Documentation/devicetree/bindings/watchdog/marvel.txt
@@ -7,6 +7,7 @@ Required Properties:
 
 Optional properties:
 
+- interrupts	: Contains the IRQ for watchdog expiration
 - timeout-sec	: Contains the watchdog timeout in seconds
 
 Example:
@@ -14,6 +15,7 @@ Example:
 	wdt at 20300 {
 		compatible = "marvell,orion-wdt";
 		reg = <0x20300 0x28>;
+		interrupts = <3>;
 		timeout-sec = <10>;
 		status = "okay";
 	};
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index e10b0b1..b7067ac 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/err.h>
@@ -119,10 +120,16 @@ static struct watchdog_device orion_wdt = {
 	.min_timeout = 1,
 };
 
+static irqreturn_t orion_wdt_irq(int irq, void *devid)
+{
+	panic("Watchdog Timeout");
+	return IRQ_HANDLED;
+}
+
 static int orion_wdt_probe(struct platform_device *pdev)
 {
 	struct resource *res;
-	int ret;
+	int ret, irq;
 
 	clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(clk)) {
@@ -161,6 +168,21 @@ static int orion_wdt_probe(struct platform_device *pdev)
 	if (!orion_wdt_enabled())
 		orion_wdt_stop(&orion_wdt);
 
+	/* Request the IRQ only after the watchdog is disabled */
+	irq = platform_get_irq(pdev, 0);
+	if (irq > 0) {
+		/*
+		 * Not all supported platforms specify an interrupt for the
+		 * watchdog, so let's make it optional.
+		 */
+		ret = devm_request_irq(&pdev->dev, irq, orion_wdt_irq, 0,
+				       pdev->name, &orion_wdt);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "failed to request IRQ\n");
+			goto disable_clk;
+		}
+	}
+
 	watchdog_set_nowayout(&orion_wdt, nowayout);
 	ret = watchdog_register_device(&orion_wdt);
 	if (ret)
-- 
1.8.1.5

^ permalink raw reply related

* [PATCH v7 06/18] watchdog: orion: Make RSTOUT register a separate resource
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392073237-2554-1-git-send-email-ezequiel.garcia@free-electrons.com>

In order to support other SoC, it's required to distinguish
the 'control' timer register, from the 'rstout' register
that enables system reset on watchdog expiration.

To prevent a compatibility break, this commit adds a fallback
to a hardcoded RSTOUT address.

Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 .../devicetree/bindings/watchdog/marvel.txt        |  6 ++-
 arch/arm/mach-dove/include/mach/bridge-regs.h      |  1 +
 arch/arm/mach-kirkwood/include/mach/bridge-regs.h  |  1 +
 arch/arm/mach-mv78xx0/include/mach/bridge-regs.h   |  1 +
 arch/arm/mach-orion5x/include/mach/bridge-regs.h   |  1 +
 arch/arm/plat-orion/common.c                       | 10 +++--
 drivers/watchdog/orion_wdt.c                       | 47 ++++++++++++++++++++--
 7 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/Documentation/devicetree/bindings/watchdog/marvel.txt b/Documentation/devicetree/bindings/watchdog/marvel.txt
index 0731fbd..1544fe9 100644
--- a/Documentation/devicetree/bindings/watchdog/marvel.txt
+++ b/Documentation/devicetree/bindings/watchdog/marvel.txt
@@ -3,7 +3,9 @@
 Required Properties:
 
 - Compatibility : "marvell,orion-wdt"
-- reg		: Address of the timer registers
+- reg		: Should contain two entries: first one with the
+		  timer control address, second one with the
+		  rstout enable address.
 
 Optional properties:
 
@@ -14,7 +16,7 @@ Example:
 
 	wdt at 20300 {
 		compatible = "marvell,orion-wdt";
-		reg = <0x20300 0x28>;
+		reg = <0x20300 0x28>, <0x20108 0x4>;
 		interrupts = <3>;
 		timeout-sec = <10>;
 		status = "okay";
diff --git a/arch/arm/mach-dove/include/mach/bridge-regs.h b/arch/arm/mach-dove/include/mach/bridge-regs.h
index 5362df3..f4a5b34 100644
--- a/arch/arm/mach-dove/include/mach/bridge-regs.h
+++ b/arch/arm/mach-dove/include/mach/bridge-regs.h
@@ -21,6 +21,7 @@
 #define  CPU_CTRL_PCIE1_LINK	0x00000008
 
 #define RSTOUTn_MASK		(BRIDGE_VIRT_BASE + 0x0108)
+#define RSTOUTn_MASK_PHYS	(BRIDGE_PHYS_BASE + 0x0108)
 #define  SOFT_RESET_OUT_EN	0x00000004
 
 #define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE + 0x010c)
diff --git a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
index 8b9d1c9..60f6421 100644
--- a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
+++ b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
@@ -21,6 +21,7 @@
 #define CPU_RESET		0x00000002
 
 #define RSTOUTn_MASK		(BRIDGE_VIRT_BASE + 0x0108)
+#define RSTOUTn_MASK_PHYS	(BRIDGE_PHYS_BASE + 0x0108)
 #define SOFT_RESET_OUT_EN	0x00000004
 
 #define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE + 0x010c)
diff --git a/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h b/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
index 5f03484..e20d6da 100644
--- a/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
+++ b/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
@@ -15,6 +15,7 @@
 #define L2_WRITETHROUGH		0x00020000
 
 #define RSTOUTn_MASK		(BRIDGE_VIRT_BASE + 0x0108)
+#define RSTOUTn_MASK_PHYS	(BRIDGE_PHYS_BASE + 0x0108)
 #define SOFT_RESET_OUT_EN	0x00000004
 
 #define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE + 0x010c)
diff --git a/arch/arm/mach-orion5x/include/mach/bridge-regs.h b/arch/arm/mach-orion5x/include/mach/bridge-regs.h
index f727d03..5766e3f 100644
--- a/arch/arm/mach-orion5x/include/mach/bridge-regs.h
+++ b/arch/arm/mach-orion5x/include/mach/bridge-regs.h
@@ -18,6 +18,7 @@
 #define CPU_CTRL		(ORION5X_BRIDGE_VIRT_BASE + 0x104)
 
 #define RSTOUTn_MASK		(ORION5X_BRIDGE_VIRT_BASE + 0x108)
+#define RSTOUTn_MASK_PHYS	(ORION5X_BRIDGE_PHYS_BASE + 0x108)
 
 #define CPU_SOFT_RESET		(ORION5X_BRIDGE_VIRT_BASE + 0x10c)
 
diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
index 830ff07..3ec6e8e 100644
--- a/arch/arm/plat-orion/common.c
+++ b/arch/arm/plat-orion/common.c
@@ -595,14 +595,16 @@ void __init orion_spi_1_init(unsigned long mapbase)
 /*****************************************************************************
  * Watchdog
  ****************************************************************************/
-static struct resource orion_wdt_resource =
-		DEFINE_RES_MEM(TIMER_PHYS_BASE, 0x28);
+static struct resource orion_wdt_resource[] = {
+		DEFINE_RES_MEM(TIMER_PHYS_BASE, 0x04),
+		DEFINE_RES_MEM(RSTOUTn_MASK_PHYS, 0x04),
+};
 
 static struct platform_device orion_wdt_device = {
 	.name		= "orion_wdt",
 	.id		= -1,
-	.num_resources	= 1,
-	.resource	= &orion_wdt_resource,
+	.num_resources	= ARRAY_SIZE(orion_wdt_resource),
+	.resource	= orion_wdt_resource,
 };
 
 void __init orion_wdt_init(void)
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index b7067ac..6061b83 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -26,6 +26,12 @@
 #include <linux/of.h>
 #include <mach/bridge-regs.h>
 
+/* RSTOUT mask register physical address for Orion5x, Kirkwood and Dove */
+#define ORION_RSTOUT_MASK_OFFSET	0x20108
+
+/* Internal registers can be configured at any 1 MiB aligned address */
+#define INTERNAL_REGS_MASK		~(SZ_1M - 1)
+
 /*
  * Watchdog timer block registers.
  */
@@ -44,6 +50,7 @@ static unsigned int wdt_max_duration;	/* (seconds) */
 static struct clk *clk;
 static unsigned int wdt_tclk;
 static void __iomem *wdt_reg;
+static void __iomem *wdt_rstout;
 
 static int orion_wdt_ping(struct watchdog_device *wdt_dev)
 {
@@ -64,14 +71,14 @@ static int orion_wdt_start(struct watchdog_device *wdt_dev)
 	atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, WDT_EN);
 
 	/* Enable reset on watchdog */
-	atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN);
+	atomic_io_modify(wdt_rstout, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN);
 	return 0;
 }
 
 static int orion_wdt_stop(struct watchdog_device *wdt_dev)
 {
 	/* Disable reset on watchdog */
-	atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, 0);
+	atomic_io_modify(wdt_rstout, WDT_RESET_OUT_EN, 0);
 
 	/* Disable watchdog timer */
 	atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, 0);
@@ -82,7 +89,7 @@ static int orion_wdt_enabled(void)
 {
 	bool enabled, running;
 
-	enabled = readl(RSTOUTn_MASK) & WDT_RESET_OUT_EN;
+	enabled = readl(wdt_rstout) & WDT_RESET_OUT_EN;
 	running = readl(wdt_reg + TIMER_CTRL) & WDT_EN;
 
 	return enabled && running;
@@ -126,6 +133,33 @@ static irqreturn_t orion_wdt_irq(int irq, void *devid)
 	return IRQ_HANDLED;
 }
 
+/*
+ * The original devicetree binding for this driver specified only
+ * one memory resource, so in order to keep DT backwards compatibility
+ * we try to fallback to a hardcoded register address, if the resource
+ * is missing from the devicetree.
+ */
+static void __iomem *orion_wdt_ioremap_rstout(struct platform_device *pdev,
+					      phys_addr_t internal_regs)
+{
+	struct resource *res;
+	phys_addr_t rstout;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (res)
+		return devm_ioremap(&pdev->dev, res->start,
+				    resource_size(res));
+
+	/* This workaround works only for "orion-wdt", DT-enabled */
+	if (!of_device_is_compatible(pdev->dev.of_node, "marvell,orion-wdt"))
+		return NULL;
+
+	rstout = internal_regs + ORION_RSTOUT_MASK_OFFSET;
+
+	WARN(1, FW_BUG "falling back to harcoded RSTOUT reg 0x%x\n", rstout);
+	return devm_ioremap(&pdev->dev, rstout, 0x4);
+}
+
 static int orion_wdt_probe(struct platform_device *pdev)
 {
 	struct resource *res;
@@ -153,6 +187,13 @@ static int orion_wdt_probe(struct platform_device *pdev)
 		goto disable_clk;
 	}
 
+	wdt_rstout = orion_wdt_ioremap_rstout(pdev, res->start &
+						    INTERNAL_REGS_MASK);
+	if (!wdt_rstout) {
+		ret = -ENODEV;
+		goto disable_clk;
+	}
+
 	wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk;
 
 	orion_wdt.timeout = wdt_max_duration;
-- 
1.8.1.5

^ permalink raw reply related

* [PATCH v7 07/18] watchdog: orion: Remove unneeded BRIDGE_CAUSE clear
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392073237-2554-1-git-send-email-ezequiel.garcia@free-electrons.com>

After adding the IRQ request, the BRIDGE_CAUSE bit should be cleared by the
bridge interrupt controller. There's no longer a need to do it in the watchdog
driver, so we can simply remove it.

Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 drivers/watchdog/orion_wdt.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index 6061b83..65aa655 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -24,7 +24,6 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/of.h>
-#include <mach/bridge-regs.h>
 
 /* RSTOUT mask register physical address for Orion5x, Kirkwood and Dove */
 #define ORION_RSTOUT_MASK_OFFSET	0x20108
@@ -42,7 +41,6 @@
 #define WDT_MAX_CYCLE_COUNT	0xffffffff
 
 #define WDT_RESET_OUT_EN	BIT(1)
-#define WDT_INT_REQ		BIT(3)
 
 static bool nowayout = WATCHDOG_NOWAYOUT;
 static int heartbeat = -1;		/* module parameter (seconds) */
@@ -64,9 +62,6 @@ static int orion_wdt_start(struct watchdog_device *wdt_dev)
 	/* Set watchdog duration */
 	writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL);
 
-	/* Clear watchdog timer interrupt */
-	writel(~WDT_INT_REQ, BRIDGE_CAUSE);
-
 	/* Enable watchdog timer */
 	atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, WDT_EN);
 
-- 
1.8.1.5

^ permalink raw reply related

* [PATCH v7 08/18] watchdog: orion: Introduce an orion_watchdog device structure
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392073237-2554-1-git-send-email-ezequiel.garcia@free-electrons.com>

In order to prepare to support multiple compatible-strings, this
commit adds a device structure to hold the driver's state.

Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 drivers/watchdog/orion_wdt.c | 114 ++++++++++++++++++++++++++-----------------
 1 file changed, 69 insertions(+), 45 deletions(-)

diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index 65aa655..9d3a5b9 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -44,55 +44,66 @@
 
 static bool nowayout = WATCHDOG_NOWAYOUT;
 static int heartbeat = -1;		/* module parameter (seconds) */
-static unsigned int wdt_max_duration;	/* (seconds) */
-static struct clk *clk;
-static unsigned int wdt_tclk;
-static void __iomem *wdt_reg;
-static void __iomem *wdt_rstout;
+
+struct orion_watchdog {
+	struct watchdog_device wdt;
+	void __iomem *reg;
+	void __iomem *rstout;
+	unsigned long clk_rate;
+	struct clk *clk;
+};
 
 static int orion_wdt_ping(struct watchdog_device *wdt_dev)
 {
+	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
 	/* Reload watchdog duration */
-	writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL);
+	writel(dev->clk_rate * wdt_dev->timeout, dev->reg + WDT_VAL);
 	return 0;
 }
 
 static int orion_wdt_start(struct watchdog_device *wdt_dev)
 {
+	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
+
 	/* Set watchdog duration */
-	writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL);
+	writel(dev->clk_rate * wdt_dev->timeout, dev->reg + WDT_VAL);
 
 	/* Enable watchdog timer */
-	atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, WDT_EN);
+	atomic_io_modify(dev->reg + TIMER_CTRL, WDT_EN, WDT_EN);
 
 	/* Enable reset on watchdog */
-	atomic_io_modify(wdt_rstout, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN);
+	atomic_io_modify(dev->rstout, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN);
+
 	return 0;
 }
 
 static int orion_wdt_stop(struct watchdog_device *wdt_dev)
 {
+	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
+
 	/* Disable reset on watchdog */
-	atomic_io_modify(wdt_rstout, WDT_RESET_OUT_EN, 0);
+	atomic_io_modify(dev->rstout, WDT_RESET_OUT_EN, 0);
 
 	/* Disable watchdog timer */
-	atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, 0);
+	atomic_io_modify(dev->reg + TIMER_CTRL, WDT_EN, 0);
+
 	return 0;
 }
 
-static int orion_wdt_enabled(void)
+static int orion_wdt_enabled(struct orion_watchdog *dev)
 {
 	bool enabled, running;
 
-	enabled = readl(wdt_rstout) & WDT_RESET_OUT_EN;
-	running = readl(wdt_reg + TIMER_CTRL) & WDT_EN;
+	enabled = readl(dev->rstout) & WDT_RESET_OUT_EN;
+	running = readl(dev->reg + TIMER_CTRL) & WDT_EN;
 
 	return enabled && running;
 }
 
 static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev)
 {
-	return readl(wdt_reg + WDT_VAL) / wdt_tclk;
+	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
+	return readl(dev->reg + WDT_VAL) / dev->clk_rate;
 }
 
 static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev,
@@ -116,12 +127,6 @@ static const struct watchdog_ops orion_wdt_ops = {
 	.get_timeleft = orion_wdt_get_timeleft,
 };
 
-static struct watchdog_device orion_wdt = {
-	.info = &orion_wdt_info,
-	.ops = &orion_wdt_ops,
-	.min_timeout = 1,
-};
-
 static irqreturn_t orion_wdt_irq(int irq, void *devid)
 {
 	panic("Watchdog Timeout");
@@ -157,18 +162,29 @@ static void __iomem *orion_wdt_ioremap_rstout(struct platform_device *pdev,
 
 static int orion_wdt_probe(struct platform_device *pdev)
 {
+	struct orion_watchdog *dev;
+	unsigned int wdt_max_duration;	/* (seconds) */
 	struct resource *res;
 	int ret, irq;
 
-	clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(clk)) {
+	dev = devm_kzalloc(&pdev->dev, sizeof(struct orion_watchdog),
+			   GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	dev->wdt.info = &orion_wdt_info;
+	dev->wdt.ops = &orion_wdt_ops;
+	dev->wdt.min_timeout = 1;
+
+	dev->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dev->clk)) {
 		dev_err(&pdev->dev, "Orion Watchdog missing clock\n");
-		return PTR_ERR(clk);
+		return PTR_ERR(dev->clk);
 	}
-	ret = clk_prepare_enable(clk);
+	ret = clk_prepare_enable(dev->clk);
 	if (ret)
 		return ret;
-	wdt_tclk = clk_get_rate(clk);
+	dev->clk_rate = clk_get_rate(dev->clk);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
@@ -176,24 +192,28 @@ static int orion_wdt_probe(struct platform_device *pdev)
 		goto disable_clk;
 	}
 
-	wdt_reg = devm_ioremap(&pdev->dev, res->start, resource_size(res));
-	if (!wdt_reg) {
+	dev->reg = devm_ioremap(&pdev->dev, res->start,
+			       resource_size(res));
+	if (!dev->reg) {
 		ret = -ENOMEM;
 		goto disable_clk;
 	}
 
-	wdt_rstout = orion_wdt_ioremap_rstout(pdev, res->start &
-						    INTERNAL_REGS_MASK);
-	if (!wdt_rstout) {
+	dev->rstout = orion_wdt_ioremap_rstout(pdev, res->start &
+						     INTERNAL_REGS_MASK);
+	if (!dev->rstout) {
 		ret = -ENODEV;
 		goto disable_clk;
 	}
 
-	wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk;
+	wdt_max_duration = WDT_MAX_CYCLE_COUNT / dev->clk_rate;
+
+	dev->wdt.timeout = wdt_max_duration;
+	dev->wdt.max_timeout = wdt_max_duration;
+	watchdog_init_timeout(&dev->wdt, heartbeat, &pdev->dev);
 
-	orion_wdt.timeout = wdt_max_duration;
-	orion_wdt.max_timeout = wdt_max_duration;
-	watchdog_init_timeout(&orion_wdt, heartbeat, &pdev->dev);
+	platform_set_drvdata(pdev, &dev->wdt);
+	watchdog_set_drvdata(&dev->wdt, dev);
 
 	/*
 	 * Let's make sure the watchdog is fully stopped, unless it's
@@ -201,8 +221,8 @@ static int orion_wdt_probe(struct platform_device *pdev)
 	 * removed and re-insterted, or if the bootloader explicitly
 	 * set a running watchdog before booting the kernel.
 	 */
-	if (!orion_wdt_enabled())
-		orion_wdt_stop(&orion_wdt);
+	if (!orion_wdt_enabled(dev))
+		orion_wdt_stop(&dev->wdt);
 
 	/* Request the IRQ only after the watchdog is disabled */
 	irq = platform_get_irq(pdev, 0);
@@ -212,37 +232,41 @@ static int orion_wdt_probe(struct platform_device *pdev)
 		 * watchdog, so let's make it optional.
 		 */
 		ret = devm_request_irq(&pdev->dev, irq, orion_wdt_irq, 0,
-				       pdev->name, &orion_wdt);
+				       pdev->name, dev);
 		if (ret < 0) {
 			dev_err(&pdev->dev, "failed to request IRQ\n");
 			goto disable_clk;
 		}
 	}
 
-	watchdog_set_nowayout(&orion_wdt, nowayout);
-	ret = watchdog_register_device(&orion_wdt);
+	watchdog_set_nowayout(&dev->wdt, nowayout);
+	ret = watchdog_register_device(&dev->wdt);
 	if (ret)
 		goto disable_clk;
 
 	pr_info("Initial timeout %d sec%s\n",
-		orion_wdt.timeout, nowayout ? ", nowayout" : "");
+		dev->wdt.timeout, nowayout ? ", nowayout" : "");
 	return 0;
 
 disable_clk:
-	clk_disable_unprepare(clk);
+	clk_disable_unprepare(dev->clk);
 	return ret;
 }
 
 static int orion_wdt_remove(struct platform_device *pdev)
 {
-	watchdog_unregister_device(&orion_wdt);
-	clk_disable_unprepare(clk);
+	struct watchdog_device *wdt_dev = platform_get_drvdata(pdev);
+	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
+
+	watchdog_unregister_device(wdt_dev);
+	clk_disable_unprepare(dev->clk);
 	return 0;
 }
 
 static void orion_wdt_shutdown(struct platform_device *pdev)
 {
-	orion_wdt_stop(&orion_wdt);
+	struct watchdog_device *wdt_dev = platform_get_drvdata(pdev);
+	orion_wdt_stop(wdt_dev);
 }
 
 static const struct of_device_id orion_wdt_of_match_table[] = {
-- 
1.8.1.5

^ permalink raw reply related

* [PATCH v7 09/18] watchdog: orion: Introduce per-compatible of_device_id data
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392073237-2554-1-git-send-email-ezequiel.garcia@free-electrons.com>

This commit adds an orion_watchdog_data structure to hold compatible-data
information. This allows to remove the driver-wide definition and to
be able to add support for multiple compatible-strings in the future.

Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 drivers/watchdog/orion_wdt.c | 62 ++++++++++++++++++++++++++++++--------------
 1 file changed, 43 insertions(+), 19 deletions(-)

diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index 9d3a5b9..b220e34 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -24,6 +24,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 
 /* RSTOUT mask register physical address for Orion5x, Kirkwood and Dove */
 #define ORION_RSTOUT_MASK_OFFSET	0x20108
@@ -35,29 +36,33 @@
  * Watchdog timer block registers.
  */
 #define TIMER_CTRL		0x0000
-#define WDT_EN			0x0010
-#define WDT_VAL			0x0024
 
 #define WDT_MAX_CYCLE_COUNT	0xffffffff
 
-#define WDT_RESET_OUT_EN	BIT(1)
-
 static bool nowayout = WATCHDOG_NOWAYOUT;
 static int heartbeat = -1;		/* module parameter (seconds) */
 
+struct orion_watchdog_data {
+	int wdt_counter_offset;
+	int wdt_enable_bit;
+	int rstout_enable_bit;
+};
+
 struct orion_watchdog {
 	struct watchdog_device wdt;
 	void __iomem *reg;
 	void __iomem *rstout;
 	unsigned long clk_rate;
 	struct clk *clk;
+	const struct orion_watchdog_data *data;
 };
 
 static int orion_wdt_ping(struct watchdog_device *wdt_dev)
 {
 	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
 	/* Reload watchdog duration */
-	writel(dev->clk_rate * wdt_dev->timeout, dev->reg + WDT_VAL);
+	writel(dev->clk_rate * wdt_dev->timeout,
+	       dev->reg + dev->data->wdt_counter_offset);
 	return 0;
 }
 
@@ -66,13 +71,16 @@ static int orion_wdt_start(struct watchdog_device *wdt_dev)
 	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
 
 	/* Set watchdog duration */
-	writel(dev->clk_rate * wdt_dev->timeout, dev->reg + WDT_VAL);
+	writel(dev->clk_rate * wdt_dev->timeout,
+	       dev->reg + dev->data->wdt_counter_offset);
 
 	/* Enable watchdog timer */
-	atomic_io_modify(dev->reg + TIMER_CTRL, WDT_EN, WDT_EN);
+	atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit,
+						dev->data->wdt_enable_bit);
 
 	/* Enable reset on watchdog */
-	atomic_io_modify(dev->rstout, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN);
+	atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit,
+				      dev->data->rstout_enable_bit);
 
 	return 0;
 }
@@ -82,10 +90,10 @@ static int orion_wdt_stop(struct watchdog_device *wdt_dev)
 	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
 
 	/* Disable reset on watchdog */
-	atomic_io_modify(dev->rstout, WDT_RESET_OUT_EN, 0);
+	atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit, 0);
 
 	/* Disable watchdog timer */
-	atomic_io_modify(dev->reg + TIMER_CTRL, WDT_EN, 0);
+	atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit, 0);
 
 	return 0;
 }
@@ -94,8 +102,8 @@ static int orion_wdt_enabled(struct orion_watchdog *dev)
 {
 	bool enabled, running;
 
-	enabled = readl(dev->rstout) & WDT_RESET_OUT_EN;
-	running = readl(dev->reg + TIMER_CTRL) & WDT_EN;
+	enabled = readl(dev->rstout) & dev->data->rstout_enable_bit;
+	running = readl(dev->reg + TIMER_CTRL) & dev->data->wdt_enable_bit;
 
 	return enabled && running;
 }
@@ -103,7 +111,7 @@ static int orion_wdt_enabled(struct orion_watchdog *dev)
 static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev)
 {
 	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
-	return readl(dev->reg + WDT_VAL) / dev->clk_rate;
+	return readl(dev->reg + dev->data->wdt_counter_offset) / dev->clk_rate;
 }
 
 static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev,
@@ -160,9 +168,25 @@ static void __iomem *orion_wdt_ioremap_rstout(struct platform_device *pdev,
 	return devm_ioremap(&pdev->dev, rstout, 0x4);
 }
 
+static const struct orion_watchdog_data orion_data = {
+	.rstout_enable_bit = BIT(1),
+	.wdt_enable_bit = BIT(4),
+	.wdt_counter_offset = 0x24,
+};
+
+static const struct of_device_id orion_wdt_of_match_table[] = {
+	{
+		.compatible = "marvell,orion-wdt",
+		.data = &orion_data,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table);
+
 static int orion_wdt_probe(struct platform_device *pdev)
 {
 	struct orion_watchdog *dev;
+	const struct of_device_id *match;
 	unsigned int wdt_max_duration;	/* (seconds) */
 	struct resource *res;
 	int ret, irq;
@@ -172,9 +196,15 @@ static int orion_wdt_probe(struct platform_device *pdev)
 	if (!dev)
 		return -ENOMEM;
 
+	match = of_match_device(orion_wdt_of_match_table, &pdev->dev);
+	if (!match)
+		/* Default legacy match */
+		match = &orion_wdt_of_match_table[0];
+
 	dev->wdt.info = &orion_wdt_info;
 	dev->wdt.ops = &orion_wdt_ops;
 	dev->wdt.min_timeout = 1;
+	dev->data = match->data;
 
 	dev->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(dev->clk)) {
@@ -269,12 +299,6 @@ static void orion_wdt_shutdown(struct platform_device *pdev)
 	orion_wdt_stop(wdt_dev);
 }
 
-static const struct of_device_id orion_wdt_of_match_table[] = {
-	{ .compatible = "marvell,orion-wdt", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table);
-
 static struct platform_driver orion_wdt_driver = {
 	.probe		= orion_wdt_probe,
 	.remove		= orion_wdt_remove,
-- 
1.8.1.5

^ permalink raw reply related

* [PATCH v7 10/18] watchdog: orion: Add per-compatible clock initialization
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392073237-2554-1-git-send-email-ezequiel.garcia@free-electrons.com>

Following the introduction of the compatible-data field,
it's now possible to further abstract the clock initialization.
This will allow to support SoC with a different clock setup.

Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 drivers/watchdog/orion_wdt.c | 53 ++++++++++++++++++++++++++------------------
 1 file changed, 32 insertions(+), 21 deletions(-)

diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index b220e34..b48fd08 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -42,10 +42,14 @@
 static bool nowayout = WATCHDOG_NOWAYOUT;
 static int heartbeat = -1;		/* module parameter (seconds) */
 
+struct orion_watchdog;
+
 struct orion_watchdog_data {
 	int wdt_counter_offset;
 	int wdt_enable_bit;
 	int rstout_enable_bit;
+	int (*clock_init)(struct platform_device *,
+			  struct orion_watchdog *);
 };
 
 struct orion_watchdog {
@@ -57,6 +61,22 @@ struct orion_watchdog {
 	const struct orion_watchdog_data *data;
 };
 
+static int orion_wdt_clock_init(struct platform_device *pdev,
+				struct orion_watchdog *dev)
+{
+	int ret;
+
+	dev->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dev->clk))
+		return PTR_ERR(dev->clk);
+	ret = clk_prepare_enable(dev->clk);
+	if (ret)
+		return ret;
+
+	dev->clk_rate = clk_get_rate(dev->clk);
+	return 0;
+}
+
 static int orion_wdt_ping(struct watchdog_device *wdt_dev)
 {
 	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
@@ -172,6 +192,7 @@ static const struct orion_watchdog_data orion_data = {
 	.rstout_enable_bit = BIT(1),
 	.wdt_enable_bit = BIT(4),
 	.wdt_counter_offset = 0x24,
+	.clock_init = orion_wdt_clock_init,
 };
 
 static const struct of_device_id orion_wdt_of_match_table[] = {
@@ -206,34 +227,24 @@ static int orion_wdt_probe(struct platform_device *pdev)
 	dev->wdt.min_timeout = 1;
 	dev->data = match->data;
 
-	dev->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(dev->clk)) {
-		dev_err(&pdev->dev, "Orion Watchdog missing clock\n");
-		return PTR_ERR(dev->clk);
-	}
-	ret = clk_prepare_enable(dev->clk);
-	if (ret)
-		return ret;
-	dev->clk_rate = clk_get_rate(dev->clk);
-
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		ret = -ENODEV;
-		goto disable_clk;
-	}
+	if (!res)
+		return -ENODEV;
 
 	dev->reg = devm_ioremap(&pdev->dev, res->start,
 			       resource_size(res));
-	if (!dev->reg) {
-		ret = -ENOMEM;
-		goto disable_clk;
-	}
+	if (!dev->reg)
+		return -ENOMEM;
 
 	dev->rstout = orion_wdt_ioremap_rstout(pdev, res->start &
 						     INTERNAL_REGS_MASK);
-	if (!dev->rstout) {
-		ret = -ENODEV;
-		goto disable_clk;
+	if (!dev->rstout)
+		return -ENODEV;
+
+	ret = dev->data->clock_init(pdev, dev);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot initialize clock\n");
+		return ret;
 	}
 
 	wdt_max_duration = WDT_MAX_CYCLE_COUNT / dev->clk_rate;
-- 
1.8.1.5

^ permalink raw reply related

* [PATCH v7 11/18] watchdog: orion: Add per-compatible watchdog start implementation
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392073237-2554-1-git-send-email-ezequiel.garcia@free-electrons.com>

To handle differences between SoCs this commit adds per-compatible
string start() function for the watchdog kick-off. This is preparation
work and makes no functionality changes to the current driver.

Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 drivers/watchdog/orion_wdt.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index b48fd08..3925297 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -50,6 +50,7 @@ struct orion_watchdog_data {
 	int rstout_enable_bit;
 	int (*clock_init)(struct platform_device *,
 			  struct orion_watchdog *);
+	int (*start)(struct watchdog_device *);
 };
 
 struct orion_watchdog {
@@ -86,7 +87,7 @@ static int orion_wdt_ping(struct watchdog_device *wdt_dev)
 	return 0;
 }
 
-static int orion_wdt_start(struct watchdog_device *wdt_dev)
+static int orion_start(struct watchdog_device *wdt_dev)
 {
 	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
 
@@ -105,6 +106,14 @@ static int orion_wdt_start(struct watchdog_device *wdt_dev)
 	return 0;
 }
 
+static int orion_wdt_start(struct watchdog_device *wdt_dev)
+{
+	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
+
+	/* There are some per-SoC quirks to handle */
+	return dev->data->start(wdt_dev);
+}
+
 static int orion_wdt_stop(struct watchdog_device *wdt_dev)
 {
 	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
@@ -193,6 +202,7 @@ static const struct orion_watchdog_data orion_data = {
 	.wdt_enable_bit = BIT(4),
 	.wdt_counter_offset = 0x24,
 	.clock_init = orion_wdt_clock_init,
+	.start = orion_start,
 };
 
 static const struct of_device_id orion_wdt_of_match_table[] = {
-- 
1.8.1.5

^ permalink raw reply related

* [PATCH v7 12/18] watchdog: orion: Add support for Armada 370 and Armada XP SoC
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392073237-2554-1-git-send-email-ezequiel.garcia@free-electrons.com>

Using the added infrastructure for handling SoC differences,
this commit adds support for the watchdog controller available
in Armada 370 and Armada XP SoCs.

Also, and because the AXP clock initialization uses of_clk_get_by_name,
this commit changes the orion clock initialization to use clk_get() and
adds a proper clk_put() on the common exit/error paths.

Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 .../devicetree/bindings/watchdog/marvel.txt        |   3 +
 drivers/watchdog/orion_wdt.c                       | 106 ++++++++++++++++++++-
 2 files changed, 107 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/watchdog/marvel.txt b/Documentation/devicetree/bindings/watchdog/marvel.txt
index 1544fe9..de11eb4 100644
--- a/Documentation/devicetree/bindings/watchdog/marvel.txt
+++ b/Documentation/devicetree/bindings/watchdog/marvel.txt
@@ -3,6 +3,9 @@
 Required Properties:
 
 - Compatibility : "marvell,orion-wdt"
+		  "marvell,armada-370-wdt"
+		  "marvell,armada-xp-wdt"
+
 - reg		: Should contain two entries: first one with the
 		  timer control address, second one with the
 		  rstout enable address.
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index 3925297..15321aa 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -36,9 +36,17 @@
  * Watchdog timer block registers.
  */
 #define TIMER_CTRL		0x0000
+#define TIMER_A370_STATUS	0x04
 
 #define WDT_MAX_CYCLE_COUNT	0xffffffff
 
+#define WDT_A370_RATIO_MASK(v)	((v) << 16)
+#define WDT_A370_RATIO_SHIFT	5
+#define WDT_A370_RATIO		(1 << WDT_A370_RATIO_SHIFT)
+
+#define WDT_AXP_FIXED_ENABLE_BIT BIT(10)
+#define WDT_A370_EXPIRED	BIT(31)
+
 static bool nowayout = WATCHDOG_NOWAYOUT;
 static int heartbeat = -1;		/* module parameter (seconds) */
 
@@ -67,12 +75,60 @@ static int orion_wdt_clock_init(struct platform_device *pdev,
 {
 	int ret;
 
-	dev->clk = devm_clk_get(&pdev->dev, NULL);
+	dev->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(dev->clk))
 		return PTR_ERR(dev->clk);
 	ret = clk_prepare_enable(dev->clk);
-	if (ret)
+	if (ret) {
+		clk_put(dev->clk);
 		return ret;
+	}
+
+	dev->clk_rate = clk_get_rate(dev->clk);
+	return 0;
+}
+
+static int armada370_wdt_clock_init(struct platform_device *pdev,
+				    struct orion_watchdog *dev)
+{
+	int ret;
+
+	dev->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dev->clk))
+		return PTR_ERR(dev->clk);
+	ret = clk_prepare_enable(dev->clk);
+	if (ret) {
+		clk_put(dev->clk);
+		return ret;
+	}
+
+	/* Setup watchdog input clock */
+	atomic_io_modify(dev->reg + TIMER_CTRL,
+			WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT),
+			WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT));
+
+	dev->clk_rate = clk_get_rate(dev->clk) / WDT_A370_RATIO;
+	return 0;
+}
+
+static int armadaxp_wdt_clock_init(struct platform_device *pdev,
+				   struct orion_watchdog *dev)
+{
+	int ret;
+
+	dev->clk = of_clk_get_by_name(pdev->dev.of_node, "fixed");
+	if (IS_ERR(dev->clk))
+		return PTR_ERR(dev->clk);
+	ret = clk_prepare_enable(dev->clk);
+	if (ret) {
+		clk_put(dev->clk);
+		return ret;
+	}
+
+	/* Enable the fixed watchdog clock input */
+	atomic_io_modify(dev->reg + TIMER_CTRL,
+			 WDT_AXP_FIXED_ENABLE_BIT,
+			 WDT_AXP_FIXED_ENABLE_BIT);
 
 	dev->clk_rate = clk_get_rate(dev->clk);
 	return 0;
@@ -87,6 +143,26 @@ static int orion_wdt_ping(struct watchdog_device *wdt_dev)
 	return 0;
 }
 
+static int armada370_start(struct watchdog_device *wdt_dev)
+{
+	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
+
+	/* Set watchdog duration */
+	writel(dev->clk_rate * wdt_dev->timeout,
+	       dev->reg + dev->data->wdt_counter_offset);
+
+	/* Clear the watchdog expiration bit */
+	atomic_io_modify(dev->reg + TIMER_A370_STATUS, WDT_A370_EXPIRED, 0);
+
+	/* Enable watchdog timer */
+	atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit,
+						dev->data->wdt_enable_bit);
+
+	atomic_io_modify(dev->rstout, dev->data->rstout_enable_bit,
+				      dev->data->rstout_enable_bit);
+	return 0;
+}
+
 static int orion_start(struct watchdog_device *wdt_dev)
 {
 	struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
@@ -205,11 +281,35 @@ static const struct orion_watchdog_data orion_data = {
 	.start = orion_start,
 };
 
+static const struct orion_watchdog_data armada370_data = {
+	.rstout_enable_bit = BIT(8),
+	.wdt_enable_bit = BIT(8),
+	.wdt_counter_offset = 0x34,
+	.clock_init = armada370_wdt_clock_init,
+	.start = armada370_start,
+};
+
+static const struct orion_watchdog_data armadaxp_data = {
+	.rstout_enable_bit = BIT(8),
+	.wdt_enable_bit = BIT(8),
+	.wdt_counter_offset = 0x34,
+	.clock_init = armadaxp_wdt_clock_init,
+	.start = armada370_start,
+};
+
 static const struct of_device_id orion_wdt_of_match_table[] = {
 	{
 		.compatible = "marvell,orion-wdt",
 		.data = &orion_data,
 	},
+	{
+		.compatible = "marvell,armada-370-wdt",
+		.data = &armada370_data,
+	},
+	{
+		.compatible = "marvell,armada-xp-wdt",
+		.data = &armadaxp_data,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table);
@@ -301,6 +401,7 @@ static int orion_wdt_probe(struct platform_device *pdev)
 
 disable_clk:
 	clk_disable_unprepare(dev->clk);
+	clk_put(dev->clk);
 	return ret;
 }
 
@@ -311,6 +412,7 @@ static int orion_wdt_remove(struct platform_device *pdev)
 
 	watchdog_unregister_device(wdt_dev);
 	clk_disable_unprepare(dev->clk);
+	clk_put(dev->clk);
 	return 0;
 }
 
-- 
1.8.1.5

^ permalink raw reply related

* [PATCH v7 13/18] ARM: mvebu: Enable Armada 370/XP watchdog in the devicetree
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392073237-2554-1-git-send-email-ezequiel.garcia@free-electrons.com>

Add the DT nodes to enable watchdog support available in Armada 370
and Armada XP SoCs.

Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 arch/arm/boot/dts/armada-370-xp.dtsi | 4 ++++
 arch/arm/boot/dts/armada-370.dtsi    | 5 +++++
 arch/arm/boot/dts/armada-xp.dtsi     | 6 ++++++
 3 files changed, 15 insertions(+)

diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
index 74b5964..7bbc4ac 100644
--- a/arch/arm/boot/dts/armada-370-xp.dtsi
+++ b/arch/arm/boot/dts/armada-370-xp.dtsi
@@ -199,6 +199,10 @@
 				interrupts = <37>, <38>, <39>, <40>, <5>, <6>;
 			};
 
+			watchdog at 20300 {
+				reg = <0x20300 0x34>, <0x20704 0x4>;
+			};
+
 			usb at 50000 {
 				compatible = "marvell,orion-ehci";
 				reg = <0x50000 0x500>;
diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi
index 0d8530c..b7759b2 100644
--- a/arch/arm/boot/dts/armada-370.dtsi
+++ b/arch/arm/boot/dts/armada-370.dtsi
@@ -196,6 +196,11 @@
 				clocks = <&coreclk 2>;
 			};
 
+			watchdog at 20300 {
+				compatible = "marvell,armada-370-wdt";
+				clocks = <&coreclk 2>;
+			};
+
 			usb at 50000 {
 				clocks = <&coreclk 0>;
 			};
diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi
index b8b84a2..abb9f9d 100644
--- a/arch/arm/boot/dts/armada-xp.dtsi
+++ b/arch/arm/boot/dts/armada-xp.dtsi
@@ -111,6 +111,12 @@
 				clock-names = "nbclk", "fixed";
 			};
 
+			watchdog at 20300 {
+				compatible = "marvell,armada-xp-wdt";
+				clocks = <&coreclk 2>, <&refclk>;
+				clock-names = "nbclk", "fixed";
+			};
+
 			armada-370-xp-pmsu at 22000 {
 				compatible = "marvell,armada-370-xp-pmsu";
 				reg = <0x22100 0x400>, <0x20800 0x20>;
-- 
1.8.1.5

^ permalink raw reply related

* [PATCH v7 14/18] ARM: kirkwood: Add RSTOUT 'reg' entry to devicetree
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392073237-2554-1-git-send-email-ezequiel.garcia@free-electrons.com>

In order to support multiplatform builds the watchdog devicetree binding
was modified and now the 'reg' property is specified to need two
entries. This commit adds the second entry as-per the new specification.

Tested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 arch/arm/boot/dts/kirkwood.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi
index 6abf44d..85542c2 100644
--- a/arch/arm/boot/dts/kirkwood.dtsi
+++ b/arch/arm/boot/dts/kirkwood.dtsi
@@ -178,7 +178,7 @@
 
 		wdt: watchdog-timer at 20300 {
 			compatible = "marvell,orion-wdt";
-			reg = <0x20300 0x28>;
+			reg = <0x20300 0x28>, <0x20108 0x4>;
 			interrupt-parent = <&bridge_intc>;
 			interrupts = <3>;
 			clocks = <&gate_clk 7>;
-- 
1.8.1.5

^ permalink raw reply related

* [PATCH v7 15/18] ARM: dove: Enable Dove watchdog in the devicetree
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392073237-2554-1-git-send-email-ezequiel.garcia@free-electrons.com>

Add the devicetree node to enable watchdog support available in Dove SoCs.

Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 arch/arm/boot/dts/dove.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi
index 2b76524..a88ed73 100644
--- a/arch/arm/boot/dts/dove.dtsi
+++ b/arch/arm/boot/dts/dove.dtsi
@@ -210,6 +210,14 @@
 				clocks = <&core_clk 0>;
 			};
 
+			watchdog at 20300 {
+				compatible = "marvell,orion-wdt";
+				reg = <0x20300 0x28>, <0x20108 0x4>;
+				interrupt-parent = <&bridge_intc>;
+				interrupts = <3>;
+				clocks = <&core_clk 0>;
+			};
+
 			crypto: crypto-engine at 30000 {
 				compatible = "marvell,orion-crypto";
 				reg = <0x30000 0x10000>,
-- 
1.8.1.5

^ permalink raw reply related

* [PATCH v7 16/18] watchdog: orion: Enable the build on ARCH_MVEBU
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392073237-2554-1-git-send-email-ezequiel.garcia@free-electrons.com>

After adding support for Armada 370/XP SoC let's enable the build on
these platforms.

Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 drivers/watchdog/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 4c4c566..2dda6c0 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -291,7 +291,7 @@ config DAVINCI_WATCHDOG
 
 config ORION_WATCHDOG
 	tristate "Orion watchdog"
-	depends on ARCH_ORION5X || ARCH_KIRKWOOD || ARCH_DOVE
+	depends on ARCH_ORION5X || ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU
 	select WATCHDOG_CORE
 	help
 	  Say Y here if to include support for the watchdog timer
-- 
1.8.1.5

^ permalink raw reply related

* [PATCH v7 17/18] ARM: mvebu: Enable watchdog support in defconfig
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392073237-2554-1-git-send-email-ezequiel.garcia@free-electrons.com>

Now that we have proper support for Armada 370/XP watchdog
let's enable it in mvebu_defconfig and multi_v7_defconfig.

Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 arch/arm/configs/multi_v7_defconfig | 2 ++
 arch/arm/configs/mvebu_defconfig    | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 845bc74..51cee83 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -187,6 +187,8 @@ CONFIG_POWER_RESET_GPIO=y
 CONFIG_SENSORS_LM90=y
 CONFIG_THERMAL=y
 CONFIG_ARMADA_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_ORION_WATCHDOG=y
 CONFIG_MFD_AS3722=y
 CONFIG_MFD_CROS_EC=y
 CONFIG_MFD_CROS_EC_SPI=y
diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig
index 0f4511d..31bdc6f 100644
--- a/arch/arm/configs/mvebu_defconfig
+++ b/arch/arm/configs/mvebu_defconfig
@@ -62,6 +62,8 @@ CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_THERMAL=y
 CONFIG_ARMADA_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_ORION_WATCHDOG=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
-- 
1.8.1.5

^ permalink raw reply related

* [PATCH v7 18/18] ARM: dove: Enable watchdog support in the defconfig
From: Ezequiel Garcia @ 2014-02-10 23:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392073237-2554-1-git-send-email-ezequiel.garcia@free-electrons.com>

Now that we have watchdog support, let's add it to the defconfig.

Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 arch/arm/configs/dove_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/configs/dove_defconfig b/arch/arm/configs/dove_defconfig
index 1101054..a330690 100644
--- a/arch/arm/configs/dove_defconfig
+++ b/arch/arm/configs/dove_defconfig
@@ -80,6 +80,8 @@ CONFIG_SPI_ORION=y
 # CONFIG_HWMON is not set
 CONFIG_THERMAL=y
 CONFIG_DOVE_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_ORION_WATCHDOG=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
-- 
1.8.1.5

^ permalink raw reply related

* [GIT PULL] qcom cleanups for v3.15
From: Kumar Gala @ 2014-02-10 23:23 UTC (permalink / raw)
  To: linux-arm-kernel

The following changes since commit 38dbfb59d1175ef458d006556061adeaa8751b72:

   Linus 3.14-rc1 (2014-02-02 16:42:13 -0800)

are available in the git repository at:

   git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git tags/qcom-cleanup-for-3.15

for you to fetch changes up to cf1e8f0cd665e2a9966d2bee4e11ecc0938ff166:

   ARM: qcom: Rename various msm prefixed functions to qcom (2014-02-06 16:20:41 -0600)

----------------------------------------------------------------
General cleanups for MSM/QCOM for 3.15

Split of the multiplatform support for the Qualcomm SoCs into a mach-qcom
while we leave mach-msm as legacy support.  Also, some smp and device tree
related cleanups.

----------------------------------------------------------------
Kumar Gala (6):
       ARM: dts: msm: split out msm8660 and msm8960 soc into dts include
       ARM: msm: kill off hotplug.c
       clocksource: qcom: Move clocksource code out of mach-msm
       ARM: qcom: Split Qualcomm support into legacy and multiplatform
       clocksource: qcom: split building of legacy vs multiplatform support
       ARM: qcom: Rename various msm prefixed functions to qcom

Rohit Vaswani (1):
       ARM: msm: Remove pen_release usage

  MAINTAINERS                                        |  8 +++
  arch/arm/Kconfig                                   |  7 +-
  arch/arm/Kconfig.debug                             |  2 +-
  arch/arm/Makefile                                  |  1 +
  arch/arm/boot/dts/Makefile                         |  6 +-
  arch/arm/boot/dts/qcom-msm8660-surf.dts            | 59 +----------------
  arch/arm/boot/dts/qcom-msm8660.dtsi                | 63 ++++++++++++++++++
  arch/arm/boot/dts/qcom-msm8960-cdp.dts             | 66 +------------------
  arch/arm/boot/dts/qcom-msm8960.dtsi                | 70 ++++++++++++++++++++
  arch/arm/mach-msm/Kconfig                          | 54 ++--------------
  arch/arm/mach-msm/Makefile                         |  8 ---
  arch/arm/mach-msm/common.h                         |  1 -
  arch/arm/mach-msm/headsmp.S                        | 39 ------------
  arch/arm/mach-msm/hotplug.c                        | 74 ----------------------
  arch/arm/mach-qcom/Kconfig                         | 33 ++++++++++
  arch/arm/mach-qcom/Makefile                        |  5 ++
  .../arm/{mach-msm/board-dt.c => mach-qcom/board.c} | 15 ++---
  arch/arm/{mach-msm => mach-qcom}/platsmp.c         | 66 ++++++-------------
  arch/arm/{mach-msm => mach-qcom}/scm-boot.c        |  0
  arch/arm/{mach-msm => mach-qcom}/scm-boot.h        |  0
  arch/arm/{mach-msm => mach-qcom}/scm.c             |  0
  arch/arm/{mach-msm => mach-qcom}/scm.h             |  0
  drivers/clocksource/Kconfig                        |  3 +
  drivers/clocksource/Makefile                       |  1 +
  .../timer.c => drivers/clocksource/qcom-timer.c    | 29 ++++-----
  25 files changed, 240 insertions(+), 370 deletions(-)
  create mode 100644 arch/arm/boot/dts/qcom-msm8660.dtsi
  create mode 100644 arch/arm/boot/dts/qcom-msm8960.dtsi
  delete mode 100644 arch/arm/mach-msm/headsmp.S
  delete mode 100644 arch/arm/mach-msm/hotplug.c
  create mode 100644 arch/arm/mach-qcom/Kconfig
  create mode 100644 arch/arm/mach-qcom/Makefile
  rename arch/arm/{mach-msm/board-dt.c => mach-qcom/board.c} (68%)
  rename arch/arm/{mach-msm => mach-qcom}/platsmp.c (65%)
  rename arch/arm/{mach-msm => mach-qcom}/scm-boot.c (100%)
  rename arch/arm/{mach-msm => mach-qcom}/scm-boot.h (100%)
  rename arch/arm/{mach-msm => mach-qcom}/scm.c (100%)
  rename arch/arm/{mach-msm => mach-qcom}/scm.h (100%)
  rename arch/arm/mach-msm/timer.c => drivers/clocksource/qcom-timer.c (98%)

--
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply

* [RFC/PATCH v2] ARM: vDSO gettimeofday using generic timer architecture
From: Nathan Lynch @ 2014-02-10 23:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140209102023.GL26684@n2100.arm.linux.org.uk>

On 02/09/2014 04:20 AM, Russell King - ARM Linux wrote:
> On Fri, Feb 07, 2014 at 05:05:49PM -0600, Nathan Lynch wrote:
>> +	/* Grab the vDSO code pages. */
>> +	for (i = 0; i < vdso_pages; i++) {
>> +		pg = virt_to_page(&vdso_start + i*PAGE_SIZE);
>> +		ClearPageReserved(pg);
>> +		get_page(pg);
>> +		vdso_pagelist[i] = pg;
>> +	}
> 
> Why do we want to clear the reserved status?  This looks over complicated
> to me.
> 
>> +
>> +	/* Sanity check the shared object header. */
>> +	vbase = vmap(vdso_pagelist, 1, 0, PAGE_KERNEL);
>> +	if (vbase == NULL) {
>> +		pr_err("Failed to map vDSO pagelist!\n");
>> +		return -ENOMEM;
>> +	} else if (memcmp(vbase, "\177ELF", 4)) {
>> +		pr_err("vDSO is not a valid ELF object!\n");
>> +		ret = -EINVAL;
>> +		goto unmap;
>> +	}
> 
> Why do we need to vmap() pages which are already accessible - vdso_start
> must be part of the kernel image, and therefore will be accessible via
> standard mappings.

Right, this stuff doesn't appear to be necessary.  Removed the vmap,
get_page, and ClearPageReserved calls for v3.


>> +static long clock_gettime_fallback(clockid_t _clkid, struct timespec *_ts)
>> +{
>> +	register struct timespec *ts asm("r1") = _ts;
>> +	register clockid_t clkid asm("r0") = _clkid;
>> +	register long ret asm ("r0");
>> +	register long nr asm("r7") = __NR_clock_gettime;
>> +
>> +	asm("swi #0" : "=r" (ret) : "r" (clkid), "r" (ts), "r" (nr) : "memory");
> 
> This isn't compatible with OABI, so either this must not be enabled when
> AEABI is disabled, or this needs to be fixed.

Okay.  I'll plan on making the vdso code depend on CONFIG_AEABI, likely
indirectly via a CONFIG_VDSO Kconfig option.  Since you'll need an
updated C library to actually benefit from the vdso, I doubt any OABI
support in this code would get any use.

Thanks for reviewing.

^ permalink raw reply

* [PATCH v6 01/19] clocksource: orion: Use atomic access for shared registers
From: Daniel Lezcano @ 2014-02-11  0:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391707226-18258-2-git-send-email-ezequiel.garcia@free-electrons.com>

On 02/06/2014 06:20 PM, Ezequiel Garcia wrote:
> Replace the driver-specific thread-safe shared register API
> by the recently introduced atomic_io_clear_set().
>
> Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
> Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> Tested-by: Willy Tarreau <w@1wt.eu>
> Acked-by: Jason Cooper <jason@lakedaemon.net>
> Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>

The patch looks good for me.

Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>



-- 
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox