On Thu, 17 Sep 2015, Barry Song wrote:

> From: Guo Zeng <guo.z...@csr.com>
> 
> CSR SiRFSoC Power Control Module includes power on or power
> off for sysctl power and gnss, it also includes onkey, RTC
> domain clock controllers and interrupt controller for power
> events.

There are lots of Three (and four) Letter Abbreviations (TLAs) here,
which mean nothing to the average reader.  Please break them out in
the commit log as I have done i.e. "Long Abbreviated Word (LAW)", so
us normies can see what they mean.

> Signed-off-by: Guo Zeng <guo.z...@csr.com>
> Signed-off-by: Barry Song <baohua.s...@csr.com>
> ---
>  .../devicetree/bindings/mfd/sirf-pwrc.txt          |  37 ++++

This should be in a separate patch.

>  drivers/mfd/Kconfig                                |  12 ++
>  drivers/mfd/Makefile                               |   2 +
>  drivers/mfd/sirfsoc_pwrc.c                         | 238 
> +++++++++++++++++++++
>  include/linux/mfd/sirfsoc_pwrc.h                   |  97 +++++++++
>  5 files changed, 386 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/sirf-pwrc.txt
>  create mode 100644 drivers/mfd/sirfsoc_pwrc.c
>  create mode 100644 include/linux/mfd/sirfsoc_pwrc.h
> 
> diff --git a/Documentation/devicetree/bindings/mfd/sirf-pwrc.txt 
> b/Documentation/devicetree/bindings/mfd/sirf-pwrc.txt
> new file mode 100644
> index 0000000..b919cdd
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/sirf-pwrc.txt
> @@ -0,0 +1,37 @@
> +SiRFSoC Power Controller (PWRC) module
> +
> +Power Controller is used to control the whole SoC power process.
> +The power controller controls the process of Power-On sequence,

s/power controller/Power Controller/

> +Power-Off sequence, different power modes switching and power
> +status configuration. the pwrc is access by io bridge, so the

s/the pwrc/The PWRC/

s/access/accessed/

s/io/IO/

> +node's parent should be io bridge.

s/io/IO/

Not quite sure what an IO bridge is though.

> +Required properties:
> +- compatible: "sirf,prima2-pwrc", or "sirf,atlas7-pwrc"
> +- reg: Address range of pwrc register set

Address start and size.

> +- sysctl:mfd cell device of pwrc
> +- rtcm-clk:mfd cell device of pwrc
> +- onkey:mfd cell device of pwrc

MFD is a Linuxisum.  Please find another way to document them.

I always find documentation easier to read then it's tabbed out
nicely.  Like:

Required properties:
- compatible    : "sirf,prima2-pwrc", or "sirf,atlas7-pwrc"
- reg           : Address range of pwrc register set
- sysctl        : mfd cell device of pwrc
- rtcm-clk      : mfd cell device of pwrc
- onkey         : mfd cell device of pwrc

> +Example:
> +
> +pwrc@3000 {
> +     compatible = "sirf,atlas7-pwrc";
> +     reg = <0x3000 0x100>;

This doesn't look like a real address.  It looks like an offset.
Please provide a full example, complete with the parent node (which I
assume has ranges set-up).

> +     sysctl {
> +             compatible = "sirf,sirf-sysctl";
> +     };
> +
> +     rtcm-clk {
> +             compatible = "sirf,atlas7-rtcmclk";
> +     };
> +
> +     onkey {
> +             compatible = "sirf,prima2-onkey";
> +     };

Why do these require their own cells?

Do they have their own properties?  If so, where are they documented?

> +};
> +
> +pwrc@3000 {
> +     compatible = "sirf,prima2-pwrc";
> +     reg = <0x3000 0x100>;
> +};
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 99d6367..5b67bee 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -1515,5 +1515,17 @@ config MFD_VEXPRESS_SYSREG
>         System Registers are the platform configuration block
>         on the ARM Ltd. Versatile Express board.
>  
> +config MFD_SIRFSOC_PWRC
> +        bool "CSR SiRFSoC on-chip Power Control Module"
> +     depends on ARCH_SIRF
> +     default y
> +        select MFD_CORE
> +        select REGMAP_IRQ
> +        help
> +         CSR SiRFSoC Power Control Module includes power on or power
> +      off for sysctl power and gnss, it also includes onkey, RTC
> +      domain clock controllers and interrupt controller for power
> +      events.

Break out the TLAs.

Your tabbing is all over the place here.  Please match existing
entries.

>  endmenu
>  endif
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index a59e3fc..255fb80 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -192,3 +192,5 @@ obj-$(CONFIG_MFD_SKY81452)        += sky81452.o
>  intel-soc-pmic-objs          := intel_soc_pmic_core.o intel_soc_pmic_crc.o
>  obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
>  obj-$(CONFIG_MFD_MT6397)     += mt6397-core.o
> +
> +obj-$(CONFIG_MFD_SIRFSOC_PWRC)       += sirfsoc_pwrc.o
> diff --git a/drivers/mfd/sirfsoc_pwrc.c b/drivers/mfd/sirfsoc_pwrc.c
> new file mode 100644
> index 0000000..b43f8b4
> --- /dev/null
> +++ b/drivers/mfd/sirfsoc_pwrc.c
> @@ -0,0 +1,238 @@
> +/*
> + * power management mfd for CSR SiRFSoC chips

"Power Management MFD for CSR SiRFSoC chips"

> + * Copyright (c) 2014 Cambridge Silicon Radio Limited, a CSR plc group 
> company.

This is out of date.

> + * Licensed under GPLv2 or later.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/of.h>
> +#include <linux/of_irq.h>
> +#include <linux/io.h>
> +#include <linux/regmap.h>
> +#include <linux/module.h>

This isn't a module.

> +#include <linux/rtc/sirfsoc_rtciobrg.h>

What's this for?

> +#include <linux/mfd/core.h>
> +#include <linux/mfd/sirfsoc_pwrc.h>

Header files should be in alphabetical order.

> +struct sirfsoc_pwrc_register sirfsoc_a7da_pwrc = {
> +     .pwrc_pdn_ctrl_set = 0x0,
> +     .pwrc_pdn_ctrl_clr = 0x4,
> +     .pwrc_pon_status = 0x8,
> +     .pwrc_trigger_en_set = 0xc,
> +     .pwrc_trigger_en_clr = 0x10,
> +     .pwrc_int_mask_set = 0x14,
> +     .pwrc_int_mask_clr = 0x18,
> +     .pwrc_int_status = 0x1c,
> +     .pwrc_pin_status = 0x20,
> +     .pwrc_rtc_pll_ctrl = 0x28,
> +     .pwrc_gpio3_debug = 0x34,
> +     .pwrc_rtc_noc_pwrctl_set = 0x38,
> +     .pwrc_rtc_noc_pwrctl_clr = 0x3c,
> +     .pwrc_rtc_can_ctrl = 0x48,
> +     .pwrc_rtc_can_status = 0x4c,
> +     .pwrc_fsm_m3_ctrl = 0x50,
> +     .pwrc_fsm_state = 0x54,
> +     .pwrc_rtcldo_reg = 0x58,
> +     .pwrc_gnss_ctrl = 0x5c,
> +     .pwrc_gnss_status = 0x60,
> +     .pwrc_xtal_reg = 0x64,
> +     .pwrc_xtal_ldo_mux_sel = 0x68,
> +     .pwrc_rtc_sw_rstc_set = 0x6c,
> +     .pwrc_rtc_sw_rstc_clr = 0x70,
> +     .pwrc_power_sw_ctrl_set = 0x74,
> +     .pwrc_power_sw_ctrl_clr = 0x78,
> +     .pwrc_rtc_dcog = 0x7c,
> +     .pwrc_m3_memories = 0x80,
> +     .pwrc_can0_memory = 0x84,
> +     .pwrc_rtc_gnss_memory = 0x88,
> +     .pwrc_m3_clk_en = 0x8c,
> +     .pwrc_can0_clk_en = 0x90,
> +     .pwrc_spi0_clk_en = 0x94,
> +     .pwrc_rtc_sec_clk_en = 0x98,
> +     .pwrc_rtc_noc_clk_en = 0x9c,
> +};
> +
> +struct sirfsoc_pwrc_register sirfsoc_prima2_pwrc = {
> +     .pwrc_pdn_ctrl_set = 0x0,
> +     .pwrc_pon_status = 0x4,
> +     .pwrc_trigger_en_set = 0x8,
> +     .pwrc_int_status = 0xc,
> +     .pwrc_int_mask_set = 0x10,
> +     .pwrc_pin_status = 0x14,
> +     .pwrc_scratch_pad1 = 0x18,
> +     .pwrc_scratch_pad2 = 0x1c,
> +     .pwrc_scratch_pad3 = 0x20,
> +     .pwrc_scratch_pad4 = 0x24,
> +     .pwrc_scratch_pad5 = 0x28,
> +     .pwrc_scratch_pad6 = 0x2c,
> +     .pwrc_scratch_pad7 = 0x30,
> +     .pwrc_scratch_pad8 = 0x34,
> +     .pwrc_scratch_pad9 = 0x38,
> +     .pwrc_scratch_pad10 = 0x3c,
> +     .pwrc_scratch_pad11 = 0x40,
> +     .pwrc_scratch_pad12 = 0x44,
> +     .pwrc_gpio3_clk = 0x54,
> +     .pwrc_gpio_ds = 0x78,
> +};

This is not the way we usually define register addresses.

Please #define them properly.

> +static const struct regmap_irq pwrc_irqs[] = {
> +     /* INT0 */
> +     [PWRC_IRQ_ONKEY] = {
> +             .mask = BIT(PWRC_IRQ_ONKEY),

Better to do the BIT() shifting in the header file.

> +     },
> +     [PWRC_IRQ_EXT_ONKEY] = {
> +             .mask = BIT(PWRC_IRQ_EXT_ONKEY),
> +     },
> +};
> +
> +static struct regmap_irq_chip pwrc_irq_chip = {
> +     .name = "pwrc_irq",
> +     .irqs = pwrc_irqs,
> +     .num_irqs = ARRAY_SIZE(pwrc_irqs),
> +     .num_regs = 1,
> +     .ack_invert = 1,
> +     .init_ack_masked = true,
> +};
> +
> +static const struct of_device_id pwrc_ids[] = {
> +     { .compatible = "sirf,prima2-pwrc", .data = &sirfsoc_prima2_pwrc},
> +     { .compatible = "sirf,atlas7-pwrc", .data = &sirfsoc_a7da_pwrc},
> +     {}
> +};

Please put these _just_ before you use them, so just above .probe() in
this case.

> +static const struct mfd_cell pwrc_devs[] = {
> +     {
> +             .name = "rtcmclk",
> +             .of_compatible = "sirf,atlas7-rtcmclk",
> +     }, {
> +             .name = "sirf-sysctl",
> +             .of_compatible = "sirf,sirf-sysctl",
> +     }, {
> +             .name = "gps-power",
> +             .of_compatible = "sirf,gps-power",
> +     }, {
> +             .name = "onkey",
> +             .of_compatible = "sirf,prima2-onkey",
> +     },
> +};
> +
> +static const struct regmap_config pwrc_regmap_config = {
> +     .fast_io = true,
> +     .reg_bits = 32,
> +     .val_bits = 32,
> +     .reg_stride = 4,
> +};
> +
> +static int sirfsoc_pwrc_probe(struct platform_device *pdev)
> +{
> +     struct device_node *np = pdev->dev.of_node;
> +     const struct of_device_id *match;
> +     struct sirfsoc_pwrc_info *pwrcinfo;
> +     struct regmap_irq_chip *regmap_irq_chip;
> +     struct sirfsoc_pwrc_register *pwrc_reg;
> +     struct regmap *map;
> +     int ret;
> +     u32 base;
> +
> +     if (of_property_read_u32(np, "reg", &base))
> +             panic("unable to find base address of pwrc node in dtb\n");

It looks like this driver should depend on OF.

Why are you obtaining the base address manually? Use:

  res = platform_get_resource();
  devm_ioremap_resource(res);

... instead.

> +     pwrcinfo = devm_kzalloc(&pdev->dev,
> +                     sizeof(struct sirfsoc_pwrc_info), GFP_KERNEL);

sizeof(pwrcinfo)

> +     if (!pwrcinfo)
> +             return -ENOMEM;
> +     pwrcinfo->base = base;
> +
> +     /*
> +      * pwrc behind rtciobrg offset is diff between prima2 and atlas7
> +      * here match to each ids data for it.
> +      */

Use uppercase characters for abbreviations.

Besides, I have no idea what you're trying to say.

> +     match = of_match_node(pwrc_ids, np);
> +     pwrcinfo->pwrc_reg = (struct sirfsoc_pwrc_register *)match->data;

It looks like you're trying to use the same variables two different
device's register sets.  That's asking for trouble, please don't do
that.

> +     if (of_device_is_compatible(np, "sirf,atlas7-pwrc"))
> +             pwrcinfo->ver = PWRC_ATLAS7_VER;
> +     else if (of_device_is_compatible(np, "sirf,prima2-pwrc"))
> +             pwrcinfo->ver = PWRC_PRIMA2_VER;
> +     else
> +             return -EINVAL;

These aren't versions, are they?  It's different hardware.

Can't you probe for this at runtime?

> +     of_node_put(np);

What are you putting here?

> +     map = (struct regmap *)devm_regmap_init_iobg(&pdev->dev,
> +                     &pwrc_regmap_config);

Why are you casting?

> +     if (IS_ERR(map)) {
> +             ret = PTR_ERR(map);
> +             dev_err(&pdev->dev, "Failed to allocate register map: %d\n",
> +                     ret);
> +             goto err;

Please remove the 'err' label and just return from here.

> +     }
> +
> +     pwrcinfo->regmap = map;
> +     pwrcinfo->dev = &pdev->dev;
> +     platform_set_drvdata(pdev, pwrcinfo);
> +
> +     ret = mfd_add_devices(pwrcinfo->dev, 0, pwrc_devs,
> +             ARRAY_SIZE(pwrc_devs), NULL, 0, NULL);
> +     if (ret) {
> +             dev_err(&pdev->dev, "Failed to add all pwrc subdev\n");

Capitalise all abbreviations.

Don't abbreviate things like "sub devices".

> +             goto err;

Just return.

> +     }
> +
> +     ret = of_irq_get(pdev->dev.of_node, 0);

You already put this in to a succinct variable 'np'.  Please use it.

> +     if (ret <= 0) {
> +             dev_info(&pdev->dev,
> +                     "Unable to find IRQ for pwrc. ret=%d\n", ret);

Just print ret.  No need for the ugly "ret=".

> +             goto err_irq;
> +     }
> +
> +     pwrcinfo->irq = ret;

Better change this to 'irq' instead of using 'ret'.

> +     regmap_irq_chip = &pwrc_irq_chip;
> +     pwrcinfo->regmap_irq_chip = regmap_irq_chip;
> +
> +     pwrc_reg = pwrcinfo->pwrc_reg;
> +     regmap_irq_chip->mask_base = pwrcinfo->base +
> +                                             pwrc_reg->pwrc_int_mask_set;
> +     regmap_irq_chip->unmask_base = pwrcinfo->base +
> +                             pwrc_reg->pwrc_int_mask_clr;
> +     regmap_irq_chip->status_base = pwrcinfo->base +
> +                                             pwrc_reg->pwrc_int_status;
> +     regmap_irq_chip->ack_base = pwrcinfo->base +
> +                                             pwrc_reg->pwrc_int_status;

This is ugly.

Better to create 2 regmap_irq_chip structures, one for each device.

> +     /* enable onkey trigger interrupt controller */

Capital letters to start a sentence. 

> +     ret = regmap_update_bits(map,
> +                     pwrcinfo->base +
> +                     pwrc_reg->pwrc_trigger_en_set,
> +                     BIT(PWRC_IRQ_ONKEY) | BIT(PWRC_IRQ_EXT_ONKEY),
> +                     BIT(PWRC_IRQ_ONKEY) | BIT(PWRC_IRQ_EXT_ONKEY));
> +     if (ret < 0)
> +             goto err_irq;
> +
> +     /* add irq controller for pwrc */

Capital letters to start a sentence and for abbreviations.

> +     ret = regmap_add_irq_chip(map, pwrcinfo->irq, IRQF_ONESHOT,
> +                             -1, pwrcinfo->regmap_irq_chip,
> +                             &pwrcinfo->irq_data);
> +
> +     if (ret) {
> +             dev_err(&pdev->dev, "Failed to add regmap irq controller for 
> pwrc\n");
> +             goto err;
> +     }
> +
> +     return 0;
> +err_irq:
> +     mfd_remove_devices(pwrcinfo->dev);
> +err:

Remove this label, it's not helpful.

> +     return ret;
> +}
> +
> +static struct platform_driver sirfsoc_pwrc_driver = {
> +     .probe  = sirfsoc_pwrc_probe,

.remove?

> +     .driver = {
> +             .name = "sirfsoc_pwrc",
> +             .of_match_table = pwrc_ids,

of_match_ptr()

> +     },
> +};
> +module_platform_driver(sirfsoc_pwrc_driver);

This isn't a module.

> diff --git a/include/linux/mfd/sirfsoc_pwrc.h 
> b/include/linux/mfd/sirfsoc_pwrc.h
> new file mode 100644
> index 0000000..ee2b3d5
> --- /dev/null
> +++ b/include/linux/mfd/sirfsoc_pwrc.h
> @@ -0,0 +1,97 @@
> +/*
> + * CSR SiRFSoC power control module MFD interface
> + *
> + * Copyright (c) 2014 Cambridge Silicon Radio Limited, a CSR plc group 
> company.

Out of date.

> + * Licensed under GPLv2 or later.
> + */

'\n' here.

> +#ifndef _SIRFSOC_PWRC_H_
> +#define _SIRFSOC_PWRC_H_

'\n' here.

> +#include <linux/interrupt.h>

What's this for?

> +#include <linux/regmap.h>
> +
> +#define PWRC_PDN_CTRL_OFFSET 0
> +#define AUDIO_POWER_EN_BIT   14
> +
> +struct sirfsoc_pwrc_register {
> +     /* hardware pwrc specific */
> +     u32 pwrc_pdn_ctrl_set;
> +     u32 pwrc_pdn_ctrl_clr;
> +     u32 pwrc_pon_status;
> +     u32 pwrc_trigger_en_set;
> +     u32 pwrc_trigger_en_clr;
> +     u32 pwrc_int_mask_set;
> +     u32 pwrc_int_mask_clr;
> +     u32 pwrc_int_status;
> +     u32 pwrc_pin_status;
> +     u32 pwrc_rtc_pll_ctrl;
> +     u32 pwrc_gpio3_debug;
> +     u32 pwrc_rtc_noc_pwrctl_set;
> +     u32 pwrc_rtc_noc_pwrctl_clr;
> +     u32 pwrc_rtc_can_ctrl;
> +     u32 pwrc_rtc_can_status;
> +     u32 pwrc_fsm_m3_ctrl;
> +     u32 pwrc_fsm_state;
> +     u32 pwrc_rtcldo_reg;
> +     u32 pwrc_gnss_ctrl;
> +     u32 pwrc_gnss_status;
> +     u32 pwrc_xtal_reg;
> +     u32 pwrc_xtal_ldo_mux_sel;
> +     u32 pwrc_rtc_sw_rstc_set;
> +     u32 pwrc_rtc_sw_rstc_clr;
> +     u32 pwrc_power_sw_ctrl_set;
> +     u32 pwrc_power_sw_ctrl_clr;
> +     u32 pwrc_rtc_dcog;
> +     u32 pwrc_m3_memories;
> +     u32 pwrc_can0_memory;
> +     u32 pwrc_rtc_gnss_memory;
> +     u32 pwrc_m3_clk_en;
> +     u32 pwrc_can0_clk_en;
> +     u32 pwrc_spi0_clk_en;
> +     u32 pwrc_rtc_sec_clk_en;
> +     u32 pwrc_rtc_noc_clk_en;
> +
> +     /*only for prima2*/
> +     u32 pwrc_scratch_pad1;
> +     u32 pwrc_scratch_pad2;
> +     u32 pwrc_scratch_pad3;
> +     u32 pwrc_scratch_pad4;
> +     u32 pwrc_scratch_pad5;
> +     u32 pwrc_scratch_pad6;
> +     u32 pwrc_scratch_pad7;
> +     u32 pwrc_scratch_pad8;
> +     u32 pwrc_scratch_pad9;
> +     u32 pwrc_scratch_pad10;
> +     u32 pwrc_scratch_pad11;
> +     u32 pwrc_scratch_pad12;
> +     u32 pwrc_gpio3_clk;
> +     u32 pwrc_gpio_ds;
> +
> +};

Please #define these instead.

> +enum pwrc_version {
> +     PWRC_MARCO_VER,
> +     PWRC_PRIMA2_VER,
> +     PWRC_ATLAS7_VER,
> +};

Kerneldoc header?

> +struct sirfsoc_pwrc_info {
> +     struct device *dev;
> +     struct regmap *regmap;
> +     struct sirfsoc_pwrc_register *pwrc_reg;
> +     struct regmap_irq_chip *regmap_irq_chip;
> +     struct regmap_irq_chip_data *irq_data;

Where are these reused?

> +     u32 ver;

What is this used for?

> +     u32 base;

Is this a u32 or a memory address?

> +     int irq;
> +};
> +
> +enum {
> +     PWRC_IRQ_ONKEY = 0,
> +     PWRC_IRQ_EXT_ONKEY,
> +     PWRC_MAX_IRQ,
> +};
> +
> +extern struct sirfsoc_pwrc_register sirfsoc_a7da_pwrc;
> +extern struct sirfsoc_pwrc_register sirfsoc_prima2_pwrc;
> +#endif

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to