RE: [PATCH v5 11/14] ARM: OMAP2+: gpmc: handle connected peripherals
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
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
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); +