Hi Gael,

On Wed, 20 Aug 2014 00:07:51 +0200
Gaël PORTAY <gael.por...@gmail.com> wrote:

> Move resource retrieval from atmel_tc_alloc to tc_probe to avoid lately
> reporting resource related issues when a TC block user request a TC block.
> 
> Moreover, resources retrieval are usually done in the probe function,
> thus moving them add some consistency with other drivers.
> 
> Initialization is done once, ie not every time a tc block is requested.
> If it fails, the device is not appended to the list of tc blocks.
> 
> Furhermore, the device id is retrieved at probe as well, avoiding parsing
> DT every time the user requests of tc block.
> 
> Signed-off-by: Gaël PORTAY <gael.por...@gmail.com>

Acked-by: Boris Brezillon <boris.brezil...@free-electrons.com>

> ---
>  drivers/clocksource/tcb_clksrc.c |  2 +-
>  drivers/misc/atmel_tclib.c       | 71 
> +++++++++++++---------------------------
>  drivers/pwm/pwm-atmel-tcb.c      |  2 +-
>  include/linux/atmel_tc.h         |  8 +++--
>  4 files changed, 29 insertions(+), 54 deletions(-)
> 
> diff --git a/drivers/clocksource/tcb_clksrc.c 
> b/drivers/clocksource/tcb_clksrc.c
> index a8d7ea1..f922e81 100644
> --- a/drivers/clocksource/tcb_clksrc.c
> +++ b/drivers/clocksource/tcb_clksrc.c
> @@ -279,7 +279,7 @@ static int __init tcb_clksrc_init(void)
>       int i;
>       int ret;
>  
> -     tc = atmel_tc_alloc(CONFIG_ATMEL_TCB_CLKSRC_BLOCK, clksrc.name);
> +     tc = atmel_tc_alloc(CONFIG_ATMEL_TCB_CLKSRC_BLOCK);
>       if (!tc) {
>               pr_debug("can't alloc TC for clocksource\n");
>               return -ENODEV;
> diff --git a/drivers/misc/atmel_tclib.c b/drivers/misc/atmel_tclib.c
> index b514a2d..d505d1e 100644
> --- a/drivers/misc/atmel_tclib.c
> +++ b/drivers/misc/atmel_tclib.c
> @@ -35,60 +35,31 @@ static LIST_HEAD(tc_list);
>  /**
>   * atmel_tc_alloc - allocate a specified TC block
>   * @block: which block to allocate
> - * @name: name to be associated with the iomem resource
>   *
>   * Caller allocates a block.  If it is available, a pointer to a
>   * pre-initialized struct atmel_tc is returned. The caller can access
>   * the registers directly through the "regs" field.
>   */
> -struct atmel_tc *atmel_tc_alloc(unsigned block, const char *name)
> +struct atmel_tc *atmel_tc_alloc(unsigned block)
>  {
>       struct atmel_tc         *tc;
>       struct platform_device  *pdev = NULL;
> -     struct resource         *r;
> -     size_t                  size;
>  
>       spin_lock(&tc_list_lock);
>       list_for_each_entry(tc, &tc_list, node) {
> -             if (tc->pdev->dev.of_node) {
> -                     if (of_alias_get_id(tc->pdev->dev.of_node, "tcb")
> -                                     == block) {
> -                             pdev = tc->pdev;
> -                             break;
> -                     }
> -             } else if (tc->pdev->id == block) {
> +             if (tc->allocated)
> +                     continue;
> +
> +             if ((tc->pdev->dev.of_node && tc->id == block) ||
> +                 (tc->pdev->id == block)) {
>                       pdev = tc->pdev;
> +                     tc->allocated = true;
>                       break;
>               }
>       }
> -
> -     if (!pdev || tc->iomem)
> -             goto fail;
> -
> -     r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -     if (!r)
> -             goto fail;
> -
> -     size = resource_size(r);
> -     r = request_mem_region(r->start, size, name);
> -     if (!r)
> -             goto fail;
> -
> -     tc->regs = ioremap(r->start, size);
> -     if (!tc->regs)
> -             goto fail_ioremap;
> -
> -     tc->iomem = r;
> -
> -out:
>       spin_unlock(&tc_list_lock);
> -     return tc;
>  
> -fail_ioremap:
> -     release_mem_region(r->start, size);
> -fail:
> -     tc = NULL;
> -     goto out;
> +     return pdev ? tc : NULL;
>  }
>  EXPORT_SYMBOL_GPL(atmel_tc_alloc);
>  
> @@ -96,19 +67,14 @@ EXPORT_SYMBOL_GPL(atmel_tc_alloc);
>   * atmel_tc_free - release a specified TC block
>   * @tc: Timer/counter block that was returned by atmel_tc_alloc()
>   *
> - * This reverses the effect of atmel_tc_alloc(), unmapping the I/O
> - * registers, invalidating the resource returned by that routine and
> - * making the TC available to other drivers.
> + * This reverses the effect of atmel_tc_alloc(), invalidating the resource
> + * returned by that routine and making the TC available to other drivers.
>   */
>  void atmel_tc_free(struct atmel_tc *tc)
>  {
>       spin_lock(&tc_list_lock);
> -     if (tc->regs) {
> -             iounmap(tc->regs);
> -             release_mem_region(tc->iomem->start, resource_size(tc->iomem));
> -             tc->regs = NULL;
> -             tc->iomem = NULL;
> -     }
> +     if (tc->allocated)
> +             tc->allocated = false;
>       spin_unlock(&tc_list_lock);
>  }
>  EXPORT_SYMBOL_GPL(atmel_tc_free);
> @@ -142,9 +108,7 @@ static int __init tc_probe(struct platform_device *pdev)
>       struct atmel_tc *tc;
>       struct clk      *clk;
>       int             irq;
> -
> -     if (!platform_get_resource(pdev, IORESOURCE_MEM, 0))
> -             return -EINVAL;
> +     struct resource *r;
>  
>       irq = platform_get_irq(pdev, 0);
>       if (irq < 0)
> @@ -160,12 +124,21 @@ static int __init tc_probe(struct platform_device *pdev)
>       if (IS_ERR(clk))
>               return PTR_ERR(clk);
>  
> +     r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +     tc->regs = devm_ioremap_resource(&pdev->dev, r);
> +     if (IS_ERR(tc->regs))
> +             return PTR_ERR(tc->regs);
> +
>       /* Now take SoC information if available */
>       if (pdev->dev.of_node) {
>               const struct of_device_id *match;
>               match = of_match_node(atmel_tcb_dt_ids, pdev->dev.of_node);
>               if (match)
>                       tc->tcb_config = match->data;
> +
> +             tc->id = of_alias_get_id(tc->pdev->dev.of_node, "tcb");
> +     } else {
> +             tc->id = pdev->id;
>       }
>  
>       tc->clk[0] = clk;
> diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c
> index f3dcd02..d56e5b7 100644
> --- a/drivers/pwm/pwm-atmel-tcb.c
> +++ b/drivers/pwm/pwm-atmel-tcb.c
> @@ -379,7 +379,7 @@ static int atmel_tcb_pwm_probe(struct platform_device 
> *pdev)
>               return err;
>       }
>  
> -     tc = atmel_tc_alloc(tcblock, "tcb-pwm");
> +     tc = atmel_tc_alloc(tcblock);
>       if (tc == NULL) {
>               dev_err(&pdev->dev, "failed to allocate Timer Counter Block\n");
>               return -ENOMEM;
> diff --git a/include/linux/atmel_tc.h b/include/linux/atmel_tc.h
> index 89a931b..d8aa884 100644
> --- a/include/linux/atmel_tc.h
> +++ b/include/linux/atmel_tc.h
> @@ -44,12 +44,13 @@ struct atmel_tcb_config {
>  /**
>   * struct atmel_tc - information about a Timer/Counter Block
>   * @pdev: physical device
> - * @iomem: resource associated with the I/O register
>   * @regs: mapping through which the I/O registers can be accessed
> + * @id: block id
>   * @tcb_config: configuration data from SoC
>   * @irq: irq for each of the three channels
>   * @clk: internal clock source for each of the three channels
>   * @node: list node, for tclib internal use
> + * @allocated: if already used, for tclib internal use
>   *
>   * On some platforms, each TC channel has its own clocks and IRQs,
>   * while on others, all TC channels share the same clock and IRQ.
> @@ -61,15 +62,16 @@ struct atmel_tcb_config {
>   */
>  struct atmel_tc {
>       struct platform_device  *pdev;
> -     struct resource         *iomem;
>       void __iomem            *regs;
> +     int                     id;
>       const struct atmel_tcb_config *tcb_config;
>       int                     irq[3];
>       struct clk              *clk[3];
>       struct list_head        node;
> +     bool                    allocated;
>  };
>  
> -extern struct atmel_tc *atmel_tc_alloc(unsigned block, const char *name);
> +extern struct atmel_tc *atmel_tc_alloc(unsigned block);
>  extern void atmel_tc_free(struct atmel_tc *tc);
>  
>  /* platform-specific ATMEL_TC_TIMER_CLOCKx divisors (0 means 32KiHz) */



-- 
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
--
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