[PATCH v5 9/12] OMAP: dmtimer: platform driver
From: Thara Gopinath th...@ti.com Add dmtimer platform driver functions which include: (1) platform driver initialization (2) driver probe function (3) driver remove function Signed-off-by: Tarun Kanti DebBarma tarun.ka...@ti.com Signed-off-by: Thara Gopinath th...@ti.com Reviewed-by: Cousson, Benoit b-cous...@ti.com Reviewed-by: Varadarajan, Charulatha ch...@ti.com --- arch/arm/plat-omap/dmtimer.c | 156 +- 1 files changed, 154 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 9bf6ac8..ddc875b 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -43,6 +43,8 @@ #include linux/delay.h #include linux/io.h #include linux/module.h +#include linux/slab.h +#include linux/err.h #include mach/hardware.h #include plat/dmtimer.h #include mach/irqs.h @@ -167,6 +169,7 @@ struct omap_dm_timer { unsigned enabled:1; unsigned posted:1; struct platform_device *pdev; + struct list_head node; }; static int dm_timer_count; @@ -270,7 +273,8 @@ static struct omap_dm_timer *dm_timers; static const char **dm_source_names; static struct clk **dm_source_clocks; -static spinlock_t dm_timer_lock; +static LIST_HEAD(omap_timer_list); +static DEFINE_SPINLOCK(dm_timer_lock); /* * Reads timer registers in posted and non-posted mode. The posted mode bit @@ -702,6 +706,155 @@ int omap_dm_timers_active(void) } EXPORT_SYMBOL_GPL(omap_dm_timers_active); +/** + * omap_dm_timer_probe - probe function called for every registered device + * @pdev: pointer to current timer platform device + * + * Called by driver framework at the end of device registration for all + * timer devices. + */ +static int __devinit omap_dm_timer_probe(struct platform_device *pdev) +{ + int ret; + unsigned long flags; + struct omap_dm_timer *timer; + struct resource *mem, *irq, *ioarea; + struct dmtimer_platform_data *pdata = pdev-dev.platform_data; + + dev_dbg(pdev-dev, %s: +\n, __func__); + + if (!pdata) { + dev_err(pdev-dev, %s: no platform data\n, __func__); + return -ENODEV; + } + + spin_lock_irqsave(dm_timer_lock, flags); + list_for_each_entry(timer, omap_timer_list, node) + if (timer-pdev-id == pdev-id) { + timer-pdev = pdev; + spin_unlock_irqrestore(dm_timer_lock, flags); + return 0; + } + spin_unlock_irqrestore(dm_timer_lock, flags); + + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (unlikely(!irq)) { + dev_err(pdev-dev, %s: no IRQ resource\n, __func__); + ret = -ENODEV; + goto err_free_pdev; + } + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (unlikely(!mem)) { + dev_err(pdev-dev, %s: no memory resource\n, __func__); + ret = -ENODEV; + goto err_free_pdev; + } + + ioarea = request_mem_region(mem-start, resource_size(mem), + pdev-name); + if (!ioarea) { + dev_err(pdev-dev, %s: region already claimed\n, __func__); + ret = -EBUSY; + goto err_free_pdev; + } + + timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL); + if (!timer) { + dev_err(pdev-dev, %s: no memory for omap_dm_timer\n, + __func__); + ret = -ENOMEM; + goto err_release_ioregion; + } + + timer-io_base = ioremap(mem-start, resource_size(mem)); + if (!timer-io_base) { + dev_err(pdev-dev, %s: ioremap failed\n, __func__); + ret = -ENOMEM; + goto err_free_mem; + } + + timer-irq = irq-start; + timer-pdev = pdev; + timer-reserved = 0; + + /* add the timer element to the list */ + spin_lock_irqsave(dm_timer_lock, flags); + list_add_tail(timer-node, omap_timer_list); + spin_unlock_irqrestore(dm_timer_lock, flags); + + dev_dbg(pdev-dev, bound to its driver\n); + + return 0; + +err_free_mem: + kfree(timer); + +err_release_ioregion: + release_mem_region(mem-start, resource_size(mem)); + +err_free_pdev: + platform_device_del(pdev); + + return ret; +} + +/** + * omap_dm_timer_remove - cleanup a registered timer device + * @pdev: pointer to current timer platform device + * + * Called by driver framework whenever a timer device is unregistered. + * In addition to freeing platform resources it also deletes the timer + * entry from the local list. + */ +static int __devexit omap_dm_timer_remove(struct platform_device *pdev) +{ + struct omap_dm_timer *timer, *tmp; + unsigned long flags; + int ret = -EINVAL; + + spin_lock_irqsave(dm_timer_lock, flags); +
Re: [PATCH v5 9/12] OMAP: dmtimer: platform driver
On Tue, Dec 07, 2010 at 05:14:16AM +0530, Tarun Kanti DebBarma wrote: From: Thara Gopinath th...@ti.com Add dmtimer platform driver functions which include: (1) platform driver initialization (2) driver probe function (3) driver remove function Signed-off-by: Tarun Kanti DebBarma tarun.ka...@ti.com Signed-off-by: Thara Gopinath th...@ti.com Reviewed-by: Cousson, Benoit b-cous...@ti.com Reviewed-by: Varadarajan, Charulatha ch...@ti.com --- arch/arm/plat-omap/dmtimer.c | 156 +- 1 files changed, 154 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 9bf6ac8..ddc875b 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -43,6 +43,8 @@ #include linux/delay.h #include linux/io.h #include linux/module.h +#include linux/slab.h +#include linux/err.h #include mach/hardware.h not required. You can cleanup #include plat/dmtimer.h #include mach/irqs.h not required. You can cleanup @@ -167,6 +169,7 @@ struct omap_dm_timer { unsigned enabled:1; unsigned posted:1; struct platform_device *pdev; + struct list_head node; }; static int dm_timer_count; @@ -270,7 +273,8 @@ static struct omap_dm_timer *dm_timers; static const char **dm_source_names; static struct clk **dm_source_clocks; -static spinlock_t dm_timer_lock; +static LIST_HEAD(omap_timer_list); +static DEFINE_SPINLOCK(dm_timer_lock); /* * Reads timer registers in posted and non-posted mode. The posted mode bit @@ -702,6 +706,155 @@ int omap_dm_timers_active(void) } EXPORT_SYMBOL_GPL(omap_dm_timers_active); +/** + * omap_dm_timer_probe - probe function called for every registered device + * @pdev:pointer to current timer platform device + * + * Called by driver framework at the end of device registration for all + * timer devices. + */ +static int __devinit omap_dm_timer_probe(struct platform_device *pdev) +{ + int ret; + unsigned long flags; + struct omap_dm_timer *timer; + struct resource *mem, *irq, *ioarea; + struct dmtimer_platform_data *pdata = pdev-dev.platform_data; + + dev_dbg(pdev-dev, %s: +\n, __func__); + + if (!pdata) { + dev_err(pdev-dev, %s: no platform data\n, __func__); + return -ENODEV; + } + + spin_lock_irqsave(dm_timer_lock, flags); + list_for_each_entry(timer, omap_timer_list, node) + if (timer-pdev-id == pdev-id) { + timer-pdev = pdev; + spin_unlock_irqrestore(dm_timer_lock, flags); + return 0; + } + spin_unlock_irqrestore(dm_timer_lock, flags); + + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (unlikely(!irq)) { + dev_err(pdev-dev, %s: no IRQ resource\n, __func__); + ret = -ENODEV; + goto err_free_pdev; + } + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (unlikely(!mem)) { + dev_err(pdev-dev, %s: no memory resource\n, __func__); + ret = -ENODEV; + goto err_free_pdev; + } + + ioarea = request_mem_region(mem-start, resource_size(mem), + pdev-name); + if (!ioarea) { + dev_err(pdev-dev, %s: region already claimed\n, __func__); + ret = -EBUSY; + goto err_free_pdev; + } + + timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL); + if (!timer) { + dev_err(pdev-dev, %s: no memory for omap_dm_timer\n, + __func__); + ret = -ENOMEM; + goto err_release_ioregion; + } + + timer-io_base = ioremap(mem-start, resource_size(mem)); + if (!timer-io_base) { + dev_err(pdev-dev, %s: ioremap failed\n, __func__); + ret = -ENOMEM; + goto err_free_mem; + } + + timer-irq = irq-start; + timer-pdev = pdev; + timer-reserved = 0; + + /* add the timer element to the list */ + spin_lock_irqsave(dm_timer_lock, flags); + list_add_tail(timer-node, omap_timer_list); + spin_unlock_irqrestore(dm_timer_lock, flags); + + dev_dbg(pdev-dev, bound to its driver\n); + + return 0; + +err_free_mem: + kfree(timer); + +err_release_ioregion: + release_mem_region(mem-start, resource_size(mem)); + +err_free_pdev: You can also free pdata? + platform_device_del(pdev); + + return ret; +} + +/** + * omap_dm_timer_remove - cleanup a registered timer device + * @pdev:pointer to current timer platform device + * + * Called by driver framework whenever a timer device is unregistered. + * In addition to freeing platform resources it also deletes the timer + * entry from the local list. + */ +static int __devexit omap_dm_timer_remove(struct platform_device *pdev) +{ +
RE: [PATCH v5 9/12] OMAP: dmtimer: platform driver
-Original Message- From: G, Manjunath Kondaiah Sent: Tuesday, December 07, 2010 12:40 AM To: DebBarma, Tarun Kanti Cc: linux-omap@vger.kernel.org; Gopinath, Thara Subject: Re: [PATCH v5 9/12] OMAP: dmtimer: platform driver On Tue, Dec 07, 2010 at 05:14:16AM +0530, Tarun Kanti DebBarma wrote: From: Thara Gopinath th...@ti.com Add dmtimer platform driver functions which include: (1) platform driver initialization (2) driver probe function (3) driver remove function Signed-off-by: Tarun Kanti DebBarma tarun.ka...@ti.com Signed-off-by: Thara Gopinath th...@ti.com Reviewed-by: Cousson, Benoit b-cous...@ti.com Reviewed-by: Varadarajan, Charulatha ch...@ti.com --- arch/arm/plat-omap/dmtimer.c | 156 +- 1 files changed, 154 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 9bf6ac8..ddc875b 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -43,6 +43,8 @@ #include linux/delay.h #include linux/io.h #include linux/module.h +#include linux/slab.h +#include linux/err.h #include mach/hardware.h not required. You can cleanup Ok. #include plat/dmtimer.h #include mach/irqs.h not required. You can cleanup Ok. @@ -167,6 +169,7 @@ struct omap_dm_timer { unsigned enabled:1; unsigned posted:1; struct platform_device *pdev; + struct list_head node; }; static int dm_timer_count; @@ -270,7 +273,8 @@ static struct omap_dm_timer *dm_timers; static const char **dm_source_names; static struct clk **dm_source_clocks; -static spinlock_t dm_timer_lock; +static LIST_HEAD(omap_timer_list); +static DEFINE_SPINLOCK(dm_timer_lock); /* * Reads timer registers in posted and non-posted mode. The posted mode bit @@ -702,6 +706,155 @@ int omap_dm_timers_active(void) } EXPORT_SYMBOL_GPL(omap_dm_timers_active); +/** + * omap_dm_timer_probe - probe function called for every registered device + * @pdev: pointer to current timer platform device + * + * Called by driver framework at the end of device registration for all + * timer devices. + */ +static int __devinit omap_dm_timer_probe(struct platform_device *pdev) +{ + int ret; + unsigned long flags; + struct omap_dm_timer *timer; + struct resource *mem, *irq, *ioarea; + struct dmtimer_platform_data *pdata = pdev-dev.platform_data; + + dev_dbg(pdev-dev, %s: +\n, __func__); + + if (!pdata) { + dev_err(pdev-dev, %s: no platform data\n, __func__); + return -ENODEV; + } + + spin_lock_irqsave(dm_timer_lock, flags); + list_for_each_entry(timer, omap_timer_list, node) + if (timer-pdev-id == pdev-id) { + timer-pdev = pdev; + spin_unlock_irqrestore(dm_timer_lock, flags); + return 0; + } + spin_unlock_irqrestore(dm_timer_lock, flags); + + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (unlikely(!irq)) { + dev_err(pdev-dev, %s: no IRQ resource\n, __func__); + ret = -ENODEV; + goto err_free_pdev; + } + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (unlikely(!mem)) { + dev_err(pdev-dev, %s: no memory resource\n, __func__); + ret = -ENODEV; + goto err_free_pdev; + } + + ioarea = request_mem_region(mem-start, resource_size(mem), + pdev-name); + if (!ioarea) { + dev_err(pdev-dev, %s: region already claimed\n, __func__); + ret = -EBUSY; + goto err_free_pdev; + } + + timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL); + if (!timer) { + dev_err(pdev-dev, %s: no memory for omap_dm_timer\n, + __func__); + ret = -ENOMEM; + goto err_release_ioregion; + } + + timer-io_base = ioremap(mem-start, resource_size(mem)); + if (!timer-io_base) { + dev_err(pdev-dev, %s: ioremap failed\n, __func__); + ret = -ENOMEM; + goto err_free_mem; + } + + timer-irq = irq-start; + timer-pdev = pdev; + timer-reserved = 0; + + /* add the timer element to the list */ + spin_lock_irqsave(dm_timer_lock, flags); + list_add_tail(timer-node, omap_timer_list); + spin_unlock_irqrestore(dm_timer_lock, flags); + + dev_dbg(pdev-dev, bound to its driver\n); + + return 0; + +err_free_mem: + kfree(timer); + +err_release_ioregion: + release_mem_region(mem-start, resource_size(mem)); + +err_free_pdev: You can also free pdata? This pdata points to data within pdev created by omap_device_build. But the pdata which was allocated locally is already freed After omap_device_build() in omap_timer_init() in mach-omap
Re: [PATCH v5 9/12] OMAP: dmtimer: platform driver
* DebBarma, Tarun Kanti tarun.ka...@ti.com [2010-12-07 11:02:26 +0530]: -Original Message- From: G, Manjunath Kondaiah Sent: Tuesday, December 07, 2010 12:40 AM To: DebBarma, Tarun Kanti Cc: linux-omap@vger.kernel.org; Gopinath, Thara Subject: Re: [PATCH v5 9/12] OMAP: dmtimer: platform driver On Tue, Dec 07, 2010 at 05:14:16AM +0530, Tarun Kanti DebBarma wrote: From: Thara Gopinath th...@ti.com Add dmtimer platform driver functions which include: (1) platform driver initialization (2) driver probe function (3) driver remove function Signed-off-by: Tarun Kanti DebBarma tarun.ka...@ti.com Signed-off-by: Thara Gopinath th...@ti.com Reviewed-by: Cousson, Benoit b-cous...@ti.com [...] + +err_free_mem: + kfree(timer); + +err_release_ioregion: + release_mem_region(mem-start, resource_size(mem)); + +err_free_pdev: You can also free pdata? This pdata points to data within pdev created by omap_device_build. But the pdata which was allocated locally is already freed After omap_device_build() in omap_timer_init() in mach-omap. You should also free memory allocated for pdata during omap_device_build since you no longer require pdata due to probe fail. + platform_device_del(pdev); + + return ret; +} + +/** + * omap_dm_timer_remove - cleanup a registered timer device + * @pdev:pointer to current timer platform device + * + * Called by driver framework whenever a timer device is unregistered. + * In addition to freeing platform resources it also deletes the timer + * entry from the local list. + */ +static int __devexit omap_dm_timer_remove(struct platform_device *pdev) +{ + struct omap_dm_timer *timer, *tmp; + unsigned long flags; + int ret = -EINVAL; + + spin_lock_irqsave(dm_timer_lock, flags); + list_for_each_entry_safe(timer, tmp, omap_timer_list, node) { + if (timer-pdev-id == pdev-id) { + platform_device_del(timer-pdev); + list_del(timer-node); + kfree(timer); kfree(pdev-dev.platform_data); Ok, this is supposed to be done as part of platform_device_del above. No. platform_device_del will not free platform_data. You have use kfree for freeing pdata or platform_data. -Manjunath -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v5 9/12] OMAP: dmtimer: platform driver
-Original Message- From: G, Manjunath Kondaiah Sent: Tuesday, December 07, 2010 11:18 AM To: DebBarma, Tarun Kanti Cc: linux-omap@vger.kernel.org; Gopinath, Thara Subject: Re: [PATCH v5 9/12] OMAP: dmtimer: platform driver * DebBarma, Tarun Kanti tarun.ka...@ti.com [2010-12-07 11:02:26 +0530]: -Original Message- From: G, Manjunath Kondaiah Sent: Tuesday, December 07, 2010 12:40 AM To: DebBarma, Tarun Kanti Cc: linux-omap@vger.kernel.org; Gopinath, Thara Subject: Re: [PATCH v5 9/12] OMAP: dmtimer: platform driver On Tue, Dec 07, 2010 at 05:14:16AM +0530, Tarun Kanti DebBarma wrote: From: Thara Gopinath th...@ti.com Add dmtimer platform driver functions which include: (1) platform driver initialization (2) driver probe function (3) driver remove function Signed-off-by: Tarun Kanti DebBarma tarun.ka...@ti.com Signed-off-by: Thara Gopinath th...@ti.com Reviewed-by: Cousson, Benoit b-cous...@ti.com [...] + +err_free_mem: + kfree(timer); + +err_release_ioregion: + release_mem_region(mem-start, resource_size(mem)); + +err_free_pdev: You can also free pdata? This pdata points to data within pdev created by omap_device_build. But the pdata which was allocated locally is already freed After omap_device_build() in omap_timer_init() in mach-omap. You should also free memory allocated for pdata during omap_device_build since you no longer require pdata due to probe fail. I am not denying this. So, your comment you have been more easily understood If you have mentioned that platform_device_del does not free pdata. Therefore, it must be explicitly freed. + platform_device_del(pdev); + + return ret; +} + +/** + * omap_dm_timer_remove - cleanup a registered timer device + * @pdev: pointer to current timer platform device + * + * Called by driver framework whenever a timer device is unregistered. + * In addition to freeing platform resources it also deletes the timer + * entry from the local list. + */ +static int __devexit omap_dm_timer_remove(struct platform_device *pdev) +{ + struct omap_dm_timer *timer, *tmp; + unsigned long flags; + int ret = -EINVAL; + + spin_lock_irqsave(dm_timer_lock, flags); + list_for_each_entry_safe(timer, tmp, omap_timer_list, node) { + if (timer-pdev-id == pdev-id) { + platform_device_del(timer-pdev); + list_del(timer-node); + kfree(timer); kfree(pdev-dev.platform_data); Ok, this is supposed to be done as part of platform_device_del above. No. platform_device_del will not free platform_data. You have use kfree for freeing pdata or platform_data. I will confirm and change accordingly. -- Tarun -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html