RE: [PATCH v5 11/14] ARM: OMAP2+: gpmc: handle connected peripherals

2012-06-14 Thread Mohammed, Afzal
Hi Jon,

On Wed, Jun 13, 2012 at 21:01:08, Hunter, Jon wrote:
 On 06/11/2012 09:27 AM, Afzal Mohammed wrote:

  +static __devinit int gpmc_setup_cs(struct gpmc_peripheral *g_per,
  +   struct gpmc_cs_data *cs, struct resource *res) {
  +   int num, ret;
  +
  +   num = gpmc_setup_cs_mem(cs, res);
  +   if (IS_ERR_VALUE(num))
  +   return num;
  +
  +   ret = gpmc_setup_cs_config_timing(g_per, cs);
  +   if (IS_ERR_VALUE(ret))
  +   return ret;
  +
  +   num += gpmc_setup_cs_irq(cs, res + num);
 
 
 What happens if the above function returns an error?

That has been deliberately done as that implies user has not
specified irq flag  hence is not an error.

But it seems, I should print error information if user tries to use an
interrupt and if driver does not want/unable to use gpmc interrupt.

Regards
Afzal
--
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 11/14] ARM: OMAP2+: gpmc: handle connected peripherals

2012-06-13 Thread Jon Hunter
Hi Afzal,

On 06/11/2012 09:27 AM, Afzal Mohammed wrote:
 Platform will provide driver with configuration details for
 each CS like configuration, timing, interrupts. Setup GPMC
 based on it. Platform data also provides platform data 
 resources used for connected peripheral (eg. gpio irq).
 GPMC driver tunnels those information to respective driver.
 
 Signed-off-by: Afzal Mohammed af...@ti.com
 ---
  arch/arm/mach-omap2/gpmc.c |  146 
 
  1 file changed, 146 insertions(+)
 
 diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
 index 9073a8a..281bd23 100644
 --- a/arch/arm/mach-omap2/gpmc.c
 +++ b/arch/arm/mach-omap2/gpmc.c
 @@ -155,6 +155,8 @@ struct gpmc_peripheral {
   struct platform_device  *pdev;
  };
  
 +static struct gpmc_peripheral gpmc_peripheral[GPMC_CS_NUM];
 +static unsigned gpmc_num_peripheral;
  static unsigned gpmc_waitpin_map;
  
  static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ];
 @@ -1235,6 +1237,39 @@ static int gpmc_setup_cs_waitpin(struct 
 gpmc_peripheral *g_per, unsigned cs,
   return 0;
  }
  
 +static int gpmc_setup_cs_config_timing(struct gpmc_peripheral *g_per,
 + struct gpmc_cs_data *cs)
 +{
 + int ret;
 +
 + /* some boards rely on bootloader for configuration */
 + if (cs-have_config) {
 + gpmc_setup_cs_config(cs-cs, cs-config);
 + ret = gpmc_setup_cs_waitpin(g_per, cs-cs, cs-config);
 + if (IS_ERR_VALUE(ret)) {
 + dev_err(gpmc_dev, error: waitpin on CS %d\n, cs-cs);
 + return ret;
 + }
 + } else
 + gpmc_print_cs_config(cs-cs);
 +
 + /* some boards rely on bootloader for timing */
 + if (cs-time_ctrl.type == has_period) {
 + ret = gpmc_cs_set_timings(cs-cs, cs-time_ctrl.timings);
 + if (IS_ERR_VALUE(ret)) {
 + dev_err(gpmc_dev, error: timing on CS: %d\n, cs-cs);
 + return ret;
 + }
 + gpmc_cs_misc_timings(cs-cs, cs-time_ctrl.bool_timings);
 + } else if (cs-time_ctrl.type == has_clock) {
 + gpmc_cs_set_register_timings(cs-cs, cs-time_ctrl.timings);
 + gpmc_cs_misc_timings(cs-cs, cs-time_ctrl.bool_timings);
 + } else
 + gpmc_print_cs_timings(cs-cs);
 +
 + return 0;
 +}
 +
  static inline unsigned gpmc_bit_to_irq(unsigned bitmask)
  {
   return bitmask;
 @@ -1307,10 +1342,100 @@ static int gpmc_setup_waitpin(struct gpmc_peripheral 
 *g_per)
   return 0;
  }
  
 +static __devinit int gpmc_setup_cs(struct gpmc_peripheral *g_per,
 + struct gpmc_cs_data *cs, struct resource *res)
 +{
 + int num, ret;
 +
 + num = gpmc_setup_cs_mem(cs, res);
 + if (IS_ERR_VALUE(num))
 + return num;
 +
 + ret = gpmc_setup_cs_config_timing(g_per, cs);
 + if (IS_ERR_VALUE(ret))
 + return ret;
 +
 + num += gpmc_setup_cs_irq(cs, res + num);


What happens if the above function returns an error?

Jon
--
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


[PATCH v5 11/14] ARM: OMAP2+: gpmc: handle connected peripherals

2012-06-11 Thread Afzal Mohammed
Platform will provide driver with configuration details for
each CS like configuration, timing, interrupts. Setup GPMC
based on it. Platform data also provides platform data 
resources used for connected peripheral (eg. gpio irq).
GPMC driver tunnels those information to respective driver.

Signed-off-by: Afzal Mohammed af...@ti.com
---
 arch/arm/mach-omap2/gpmc.c |  146 
 1 file changed, 146 insertions(+)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 9073a8a..281bd23 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -155,6 +155,8 @@ struct gpmc_peripheral {
struct platform_device  *pdev;
 };
 
+static struct gpmc_peripheral gpmc_peripheral[GPMC_CS_NUM];
+static unsigned gpmc_num_peripheral;
 static unsigned gpmc_waitpin_map;
 
 static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ];
@@ -1235,6 +1237,39 @@ static int gpmc_setup_cs_waitpin(struct gpmc_peripheral 
*g_per, unsigned cs,
return 0;
 }
 
+static int gpmc_setup_cs_config_timing(struct gpmc_peripheral *g_per,
+   struct gpmc_cs_data *cs)
+{
+   int ret;
+
+   /* some boards rely on bootloader for configuration */
+   if (cs-have_config) {
+   gpmc_setup_cs_config(cs-cs, cs-config);
+   ret = gpmc_setup_cs_waitpin(g_per, cs-cs, cs-config);
+   if (IS_ERR_VALUE(ret)) {
+   dev_err(gpmc_dev, error: waitpin on CS %d\n, cs-cs);
+   return ret;
+   }
+   } else
+   gpmc_print_cs_config(cs-cs);
+
+   /* some boards rely on bootloader for timing */
+   if (cs-time_ctrl.type == has_period) {
+   ret = gpmc_cs_set_timings(cs-cs, cs-time_ctrl.timings);
+   if (IS_ERR_VALUE(ret)) {
+   dev_err(gpmc_dev, error: timing on CS: %d\n, cs-cs);
+   return ret;
+   }
+   gpmc_cs_misc_timings(cs-cs, cs-time_ctrl.bool_timings);
+   } else if (cs-time_ctrl.type == has_clock) {
+   gpmc_cs_set_register_timings(cs-cs, cs-time_ctrl.timings);
+   gpmc_cs_misc_timings(cs-cs, cs-time_ctrl.bool_timings);
+   } else
+   gpmc_print_cs_timings(cs-cs);
+
+   return 0;
+}
+
 static inline unsigned gpmc_bit_to_irq(unsigned bitmask)
 {
return bitmask;
@@ -1307,10 +1342,100 @@ static int gpmc_setup_waitpin(struct gpmc_peripheral 
*g_per)
return 0;
 }
 
+static __devinit int gpmc_setup_cs(struct gpmc_peripheral *g_per,
+   struct gpmc_cs_data *cs, struct resource *res)
+{
+   int num, ret;
+
+   num = gpmc_setup_cs_mem(cs, res);
+   if (IS_ERR_VALUE(num))
+   return num;
+
+   ret = gpmc_setup_cs_config_timing(g_per, cs);
+   if (IS_ERR_VALUE(ret))
+   return ret;
+
+   num += gpmc_setup_cs_irq(cs, res + num);
+
+   return num;
+}
+
+static __devinit int gpmc_setup_device(struct gpmc_peripheral *g_per,
+   struct gpmc_device_pdata *gdp)
+{
+   int i, n, ret;
+   struct gpmc_cs_data *cs;
+
+   for (i = 0, n = gdp-num_cs, cs = gdp-cs_data;
+   i  gdp-num_cs; i++, cs++)
+   n += hweight32(cs-irq_config);
+
+   g_per-gpmc_res = devm_kzalloc(gpmc_dev, sizeof(*g_per-gpmc_res) * n,
+   GFP_KERNEL);
+   if (g_per-gpmc_res == NULL) {
+   dev_err(gpmc_dev, error: memory allocation\n);
+   return -ENOMEM;
+   }
+
+   for (i = 0, cs = gdp-cs_data, g_per-gpmc_res_cnt = 0;
+   i  gdp-num_cs; cs++, i++) {
+   ret = gpmc_setup_cs(g_per, cs,
+   g_per-gpmc_res + g_per-gpmc_res_cnt);
+   if (IS_ERR_VALUE(ret) ||
+   IS_ERR_VALUE(gpmc_setup_waitpin(g_per))) {
+   dev_err(gpmc_dev, error: setup for %s\n, gdp-name);
+   devm_kfree(gpmc_dev, g_per-gpmc_res);
+   g_per-gpmc_res = NULL;
+   g_per-gpmc_res_cnt = 0;
+   return -EINVAL;
+   } else
+   g_per-gpmc_res_cnt += ret;
+   }
+
+   g_per-name = gdp-name;
+   g_per-id = gdp-id;
+   g_per-pdata = gdp-pdata;
+   g_per-pdata_size = gdp-pdata_size;
+   g_per-per_res = gdp-per_res;
+   g_per-per_res_cnt = gdp-per_res_cnt;
+
+   return 0;
+}
+
+static __devinit
+struct platform_device *gpmc_create_device(struct gpmc_peripheral *p)
+{
+   int num = p-per_res_cnt + p-gpmc_res_cnt;
+   struct resource *res;
+   struct platform_device *pdev;
+
+   res = devm_kzalloc(gpmc_dev, sizeof(struct resource) * num,
+   GFP_KERNEL);
+