[PATCH v2 06/10] mtd: nand: omap2: obtain memory from resource
gpmc initialization done by platform code now updates struct resource with the address space alloted for nand. Use this interface to obtain memory rather than relying on platform data field - phys_base. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/plat-omap/include/plat/nand.h |1 - drivers/mtd/nand/omap2.c | 19 +++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h index 86e4d9c..290cef5 100644 --- a/arch/arm/plat-omap/include/plat/nand.h +++ b/arch/arm/plat-omap/include/plat/nand.h @@ -26,7 +26,6 @@ struct omap_nand_platform_data { booldev_ready; int gpmc_irq; enum nand_ioxfer_type; - unsigned long phys_base; int devsize; enum omap_ecc ecc_opt; struct gpmc_nand_regs reg; diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 1d138fe..318ed8a 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -132,6 +132,7 @@ struct omap_nand_info { int gpmc_cs; unsigned long phys_base; + unsigned long mem_size; struct completion comp; int dma_ch; int gpmc_irq; @@ -1279,6 +1280,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) struct omap_nand_platform_data *pdata; int err; int i, offset; + struct resource *res; pdata = pdev-dev.platform_data; if (pdata == NULL) { @@ -1298,7 +1300,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info-pdev = pdev; info-gpmc_cs = pdata-cs; - info-phys_base = pdata-phys_base; info-reg = pdata-reg; info-mtd.priv = info-nand; @@ -1311,13 +1312,23 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) /* NAND write protect off */ gpmc_cs_configure(info-gpmc_cs, GPMC_CONFIG_WP, 0); - if (!request_mem_region(info-phys_base, NAND_IO_SIZE, + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + err = -EINVAL; + dev_err(pdev-dev, error getting memory resource\n); + goto out_free_info; + } + + info-phys_base = res-start; + info-mem_size = resource_size(res); + + if (!request_mem_region(info-phys_base, info-mem_size, pdev-dev.driver-name)) { err = -EBUSY; goto out_free_info; } - info-nand.IO_ADDR_R = ioremap(info-phys_base, NAND_IO_SIZE); + info-nand.IO_ADDR_R = ioremap(info-phys_base, info-mem_size); if (!info-nand.IO_ADDR_R) { err = -ENOMEM; goto out_release_mem_region; @@ -1474,7 +1485,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) return 0; out_release_mem_region: - release_mem_region(info-phys_base, NAND_IO_SIZE); + release_mem_region(info-phys_base, info-mem_size); out_free_info: kfree(info); -- 1.7.10.2 -- 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 v2 07/10] mtd: onenand: omap2: obtain memory from resource
gpmc initialization for onenand done by platform code now provides onenand address space as memory resource. Hence remove usage of gpmc_cs_request in onenand driver and obtain memory details from resource structure. Signed-off-by: Afzal Mohammed af...@ti.com --- drivers/mtd/onenand/omap2.c | 29 - 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index 398a827..3ff893d 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -48,13 +48,13 @@ #define DRIVER_NAME omap2-onenand -#define ONENAND_IO_SIZESZ_128K #define ONENAND_BUFRAM_SIZE(1024 * 5) struct omap2_onenand { struct platform_device *pdev; int gpmc_cs; unsigned long phys_base; + unsigned int mem_size; int gpio_irq; struct mtd_info mtd; struct onenand_chip onenand; @@ -626,6 +626,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) struct omap2_onenand *c; struct onenand_chip *this; int r; + struct resource *res; pdata = pdev-dev.platform_data; if (pdata == NULL) { @@ -647,20 +648,24 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) c-gpio_irq = 0; } - r = gpmc_cs_request(c-gpmc_cs, ONENAND_IO_SIZE, c-phys_base); - if (r 0) { - dev_err(pdev-dev, Cannot request GPMC CS\n); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + r = -EINVAL; + dev_err(pdev-dev, error getting memory resource\n); goto err_kfree; } - if (request_mem_region(c-phys_base, ONENAND_IO_SIZE, + c-phys_base = res-start; + c-mem_size = resource_size(res); + + if (request_mem_region(c-phys_base, c-mem_size, pdev-dev.driver-name) == NULL) { - dev_err(pdev-dev, Cannot reserve memory region at 0x%08lx, - size: 0x%x\n, c-phys_base, ONENAND_IO_SIZE); + dev_err(pdev-dev, Cannot reserve memory region at 0x%08lx, size: 0x%x\n, + c-phys_base, c-mem_size); r = -EBUSY; - goto err_free_cs; + goto err_kfree; } - c-onenand.base = ioremap(c-phys_base, ONENAND_IO_SIZE); + c-onenand.base = ioremap(c-phys_base, c-mem_size); if (c-onenand.base == NULL) { r = -ENOMEM; goto err_release_mem_region; @@ -776,9 +781,7 @@ err_release_gpio: err_iounmap: iounmap(c-onenand.base); err_release_mem_region: - release_mem_region(c-phys_base, ONENAND_IO_SIZE); -err_free_cs: - gpmc_cs_free(c-gpmc_cs); + release_mem_region(c-phys_base, c-mem_size); err_kfree: kfree(c); @@ -800,7 +803,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev) gpio_free(c-gpio_irq); } iounmap(c-onenand.base); - release_mem_region(c-phys_base, ONENAND_IO_SIZE); + release_mem_region(c-phys_base, c-mem_size); gpmc_cs_free(c-gpmc_cs); kfree(c); -- 1.7.10.2 -- 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 v2 08/10] ARM: OMAP2+: gpmc: Modify interrupt handling
Modify interrupt handling such that interrupts can be handled by GPMC client drivers using standard interrupt APIs rather than requiring the drivers to have knowledge about GPMC interrupt handling. Currently only NAND related interrupts has been considered (which is the case even without this change) as the only user of GPMC interrupt is NAND. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 136 arch/arm/plat-omap/include/plat/gpmc.h |1 + 2 files changed, 120 insertions(+), 17 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index a2c0588..578fd4c 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -78,6 +78,15 @@ #define ENABLE_PREFETCH(0x1 7) #define DMA_MPU_MODE 2 +/* XXX: Only NAND irq has been considered,currently these are the only ones used + */ +#defineGPMC_NR_IRQ 2 + +struct gpmc_client_irq { + unsignedirq; + u32 bitmask; +}; + /* Structure to save gpmc cs context */ struct gpmc_cs_config { u32 config1; @@ -105,6 +114,10 @@ struct omap3_gpmc_regs { struct gpmc_cs_config cs_context[GPMC_CS_NUM]; }; +static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ]; +static struct irq_chip gpmc_irq_chip; +static unsigned gpmc_irq_start; + static struct resource gpmc_mem_root; static struct resource gpmc_cs_mem[GPMC_CS_NUM]; static DEFINE_SPINLOCK(gpmc_mem_lock); @@ -702,6 +715,97 @@ void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs) reg-gpmc_bch_result0 = gpmc_base + GPMC_ECC_BCH_RESULT_0; } +int gpmc_get_client_irq(unsigned irq_config) +{ + int i; + + if (hweight32(irq_config) 1) + return 0; + + for (i = 0; i GPMC_NR_IRQ; i++) + if (gpmc_client_irq[i].bitmask irq_config) + return gpmc_client_irq[i].irq; + + return 0; +} + +static int gpmc_irq_endis(unsigned irq, bool endis) +{ + int i; + u32 regval; + + for (i = 0; i GPMC_NR_IRQ; i++) + if (irq == gpmc_client_irq[i].irq) { + regval = gpmc_read_reg(GPMC_IRQENABLE); + if (endis) + regval |= gpmc_client_irq[i].bitmask; + else + regval = ~gpmc_client_irq[i].bitmask; + gpmc_write_reg(GPMC_IRQENABLE, regval); + break; + } + + return 0; +} + +static void gpmc_irq_disable(struct irq_data *p) +{ + gpmc_irq_endis(p-irq, false); +} + +static void gpmc_irq_enable(struct irq_data *p) +{ + gpmc_irq_endis(p-irq, true); +} + +static void gpmc_irq_noop(struct irq_data *data) { } + +static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; } + +static int gpmc_setup_irq(int gpmc_irq) +{ + int i; + u32 regval; + + if (!gpmc_irq) + return -EINVAL; + + gpmc_irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0); + if (IS_ERR_VALUE(gpmc_irq_start)) { + pr_err(irq_alloc_descs failed\n); + return gpmc_irq_start; + } + + gpmc_irq_chip.name = gpmc; + gpmc_irq_chip.irq_startup = gpmc_irq_noop_ret; + gpmc_irq_chip.irq_enable = gpmc_irq_enable; + gpmc_irq_chip.irq_disable = gpmc_irq_disable; + gpmc_irq_chip.irq_shutdown = gpmc_irq_noop; + gpmc_irq_chip.irq_ack = gpmc_irq_noop; + gpmc_irq_chip.irq_mask = gpmc_irq_noop; + gpmc_irq_chip.irq_unmask = gpmc_irq_noop; + + gpmc_client_irq[0].bitmask = GPMC_IRQ_FIFOEVENTENABLE; + gpmc_client_irq[1].bitmask = GPMC_IRQ_COUNT_EVENT; + + for (i = 0; i GPMC_NR_IRQ; i++) { + gpmc_client_irq[i].irq = gpmc_irq_start + i; + irq_set_chip_and_handler(gpmc_client_irq[i].irq, + gpmc_irq_chip, handle_simple_irq); + set_irq_flags(gpmc_client_irq[i].irq, + IRQF_VALID | IRQF_NOAUTOEN); + } + + /* Disable interrupts */ + gpmc_write_reg(GPMC_IRQENABLE, 0); + + /* clear interrupts */ + regval = gpmc_read_reg(GPMC_IRQSTATUS); + gpmc_write_reg(GPMC_IRQSTATUS, regval); + + return request_irq(gpmc_irq, gpmc_handle_irq, 0, gpmc, NULL); +} + static void __init gpmc_mem_init(void) { int cs; @@ -731,8 +835,8 @@ static void __init gpmc_mem_init(void) static int __init gpmc_init(void) { - u32 l, irq; - int cs, ret = -EINVAL; + u32 l; + int ret = -EINVAL; int gpmc_irq; char *ck = NULL; @@ -780,16 +884,7 @@ static int __init gpmc_init(void) gpmc_write_reg(GPMC_SYSCONFIG, l); gpmc_mem_init(); - /* initalize the irq_chained */ - irq = OMAP_GPMC_IRQ_BASE; - for (cs = 0; cs GPMC_CS_NUM; cs
[PATCH v2 09/10] ARM: OMAP2+: gpmc-nand: Modify Interrupt handling
Now GPMC provides its client with interrupts that can be handled using the standard interrupt API. Modify GPMC NAND setup to work with it. Also disable write protect in GPMC code, so that NAND driver can be ignorant of GPMC configuration. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc-nand.c | 26 -- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index c0320d2..045596a 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -21,15 +21,23 @@ #include plat/board.h #include plat/gpmc.h -static struct resource gpmc_nand_resource = { - .flags = IORESOURCE_MEM, +static struct resource gpmc_nand_resource[] = { + { + .flags = IORESOURCE_MEM, + }, + { + .flags = IORESOURCE_IRQ, + }, + { + .flags = IORESOURCE_IRQ, + }, }; static struct platform_device gpmc_nand_device = { .name = omap2-nand, .id = 0, - .num_resources = 1, - .resource = gpmc_nand_resource, + .num_resources = ARRAY_SIZE(gpmc_nand_resource), + .resource = gpmc_nand_resource, }; static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data) @@ -75,6 +83,7 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_DEV_SIZE, 0); gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND); + gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_WP, 0); err = gpmc_cs_set_timings(gpmc_nand_data-cs, t); if (err) return err; @@ -90,14 +99,19 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) gpmc_nand_device.dev.platform_data = gpmc_nand_data; err = gpmc_cs_request(gpmc_nand_data-cs, NAND_IO_SIZE, - (unsigned long *)gpmc_nand_resource.start); + (unsigned long *)gpmc_nand_resource[0].start); if (err 0) { dev_err(dev, Cannot request GPMC CS\n); return err; } - gpmc_nand_resource.end = gpmc_nand_resource.start + NAND_IO_SIZE - 1; + gpmc_nand_resource[0].end = gpmc_nand_resource[0].start + + NAND_IO_SIZE - 1; + gpmc_nand_resource[1].start = + gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE); + gpmc_nand_resource[2].start = + gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT); /* Set timings in GPMC */ err = omap2_nand_gpmc_retime(gpmc_nand_data); if (err 0) { -- 1.7.10.2 -- 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 v2 10/10] mtd: nand: omap2: use gpmc provided irqs
GPMC platform initialization provides it's clients with interrupts that can be used through struct resource. Make use of it for irq mode functionality. Also now write protect disable is done by GPMC, hence remove it. Signed-off-by: Afzal Mohammed af...@ti.com --- drivers/mtd/nand/omap2.c | 70 +++--- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 318ed8a..5193ebb 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -135,7 +135,8 @@ struct omap_nand_info { unsigned long mem_size; struct completion comp; int dma_ch; - int gpmc_irq; + int gpmc_irq_fifo; + int gpmc_irq_count; enum { OMAP_NAND_IO_READ = 0, /* read */ OMAP_NAND_IO_WRITE, /* write */ @@ -564,14 +565,12 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev) { struct omap_nand_info *info = (struct omap_nand_info *) dev; u32 bytes; - u32 irq_stat; - irq_stat = gpmc_read_status(GPMC_GET_IRQ_STATUS); bytes = readl(info-reg.gpmc_prefetch_status); bytes = GPMC_PREFETCH_STATUS_FIFO_CNT(bytes); bytes = bytes 0xFFFC; /* io in multiple of 4 bytes */ if (info-iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */ - if (irq_stat 0x2) + if (this_irq == info-gpmc_irq_count) goto done; if (info-buf_len (info-buf_len bytes)) @@ -588,20 +587,17 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev) (u32 *)info-buf, bytes 2); info-buf = info-buf + bytes; - if (irq_stat 0x2) + if (this_irq == info-gpmc_irq_count) goto done; } - gpmc_cs_configure(info-gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat); return IRQ_HANDLED; done: complete(info-comp); - /* disable irq */ - gpmc_cs_configure(info-gpmc_cs, GPMC_ENABLE_IRQ, 0); - /* clear status */ - gpmc_cs_configure(info-gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat); + disable_irq_nosync(info-gpmc_irq_fifo); + disable_irq_nosync(info-gpmc_irq_count); return IRQ_HANDLED; } @@ -635,9 +631,9 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len) goto out_copy; info-buf_len = len; - /* enable irq */ - gpmc_cs_configure(info-gpmc_cs, GPMC_ENABLE_IRQ, - (GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT)); + + enable_irq(info-gpmc_irq_count); + enable_irq(info-gpmc_irq_fifo); /* waiting for read to complete */ wait_for_completion(info-comp); @@ -685,12 +681,13 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd, goto out_copy; info-buf_len = len; - /* enable irq */ - gpmc_cs_configure(info-gpmc_cs, GPMC_ENABLE_IRQ, - (GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT)); + + enable_irq(info-gpmc_irq_count); + enable_irq(info-gpmc_irq_fifo); /* waiting for write to complete */ wait_for_completion(info-comp); + /* wait for data to flushed-out before reset the prefetch */ tim = 0; limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS)); @@ -1309,9 +1306,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info-nand.options = pdata-devsize; info-nand.options |= NAND_SKIP_BBTSCAN; - /* NAND write protect off */ - gpmc_cs_configure(info-gpmc_cs, GPMC_CONFIG_WP, 0); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { err = -EINVAL; @@ -1334,6 +1328,14 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) goto out_release_mem_region; } + info-gpmc_irq_fifo = platform_get_irq(pdev, 0); + if (info-gpmc_irq_fifo == -ENXIO) + dev_warn(pdev-dev, error getting FIFO IRQ\n); + + info-gpmc_irq_count = platform_get_irq(pdev, 1); + if (info-gpmc_irq_count == -ENXIO) + dev_warn(pdev-dev, error getting TERMINALCOUNT IRQ\n); + info-nand.controller = info-controller; info-nand.IO_ADDR_W = info-nand.IO_ADDR_R; @@ -1389,17 +1391,24 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) break; case NAND_OMAP_PREFETCH_IRQ: - err = request_irq(pdata-gpmc_irq, - omap_nand_irq, IRQF_SHARED, gpmc-nand, info); + err = request_irq(info-gpmc_irq_fifo, omap_nand_irq
[PATCH v2 0/3] Prepare for GPMC driver conversion
Hi, Objective of this series is to make things easy for GPMC driver conversion series by separating out more things from driver conversion series. This series, 1. Unifies NAND platform initialization functions 2. Prepares OneNAND platform code for gpmc driver migration 3. Handles additional timings in Kernel This series is based on 3.5-rc1 made on top of [PATCH v2 00/10] Prepare for GPMC driver conversion (w.r.t MTD) {http://www.mail-archive.com/linux-omap@vger.kernel.org/msg70096.html} These changes has been tested with omap3evm beagle board. Relevant GPMC peripherals that got tested by this were NAND (beagle) and OneNAND (using local patches for omap3evm) Hi Jon, If you can test these changes on boards having NAND it would be really helpful. Tony's remaining concern with this series is whether this would cause NAND filesystem corruption Regards Afzal v2: 1. Make use of timing api for setting clock activation time, and remove direct writing to register for clock activation. Peripherals making use of it were tusb6010 onenand 2. Move ensuring that async mode in OneNAND has been setup from set_sync to setup function, improve commit message Afzal Mohammed (3): ARM: OMAP2+: nand: unify init functions ARM: OMAP2+: onenand: prepare for gpmc driver migration ARM: OMAP2+: gpmc: handle additional timings arch/arm/mach-omap2/board-devkit8000.c |8 +++-- arch/arm/mach-omap2/board-flash.c | 45 ++- arch/arm/mach-omap2/board-flash.h |6 ++-- arch/arm/mach-omap2/board-igep0020.c |2 +- arch/arm/mach-omap2/board-ldp.c|4 +-- arch/arm/mach-omap2/board-omap3beagle.c|8 +++-- arch/arm/mach-omap2/board-omap3touchbook.c |8 +++-- arch/arm/mach-omap2/board-overo.c |7 +++-- arch/arm/mach-omap2/board-zoom.c |5 +-- arch/arm/mach-omap2/common-board-devices.c | 46 arch/arm/mach-omap2/common-board-devices.h |1 - arch/arm/mach-omap2/gpmc-onenand.c | 28 - arch/arm/mach-omap2/gpmc.c |6 arch/arm/mach-omap2/usb-tusb6010.c |3 +- arch/arm/plat-omap/include/plat/gpmc.h |6 15 files changed, 82 insertions(+), 101 deletions(-) -- 1.7.10.2 -- 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 v2 1/3] ARM: OMAP2+: nand: unify init functions
Helper function for updating nand platform data has been added the capability to take timing structure arguement. Usage of omap_nand_flash_init() has been replaced by modifed one, omap_nand_flash_init was doing things similar to board_nand_init except that NAND CS# were being acquired based on bootloader setting. As CS# is hardwired for a given board, acquiring gpmc CS# has been removed, and updated with the value on board. NAND CS# used in beagle board was found to be CS0. Thomas Weber thomas.weber.li...@googlemail.com reported that value of devkit8000 to be CS0. Overo board was found to be using CS0 based on u-boot, while google grep says omap3touchbook too has CS0. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-devkit8000.c |8 +++-- arch/arm/mach-omap2/board-flash.c | 45 ++- arch/arm/mach-omap2/board-flash.h |6 ++-- arch/arm/mach-omap2/board-igep0020.c |2 +- arch/arm/mach-omap2/board-ldp.c|4 +-- arch/arm/mach-omap2/board-omap3beagle.c|8 +++-- arch/arm/mach-omap2/board-omap3touchbook.c |8 +++-- arch/arm/mach-omap2/board-overo.c |7 +++-- arch/arm/mach-omap2/board-zoom.c |5 +-- arch/arm/mach-omap2/common-board-devices.c | 46 arch/arm/mach-omap2/common-board-devices.h |1 - 11 files changed, 56 insertions(+), 84 deletions(-) diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 6567c1c..6ee429a 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -59,8 +59,11 @@ #include mux.h #include hsmmc.h +#include board-flash.h #include common-board-devices.h +#defineNAND_CS 0 + #define OMAP_DM9000_GPIO_IRQ 25 #define OMAP3_DEVKIT_TS_GPIO 27 @@ -628,8 +631,9 @@ static void __init devkit8000_init(void) usb_musb_init(NULL); usbhs_init(usbhs_bdata); - omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions, -ARRAY_SIZE(devkit8000_nand_partitions)); + board_nand_init(devkit8000_nand_partitions, + ARRAY_SIZE(devkit8000_nand_partitions), NAND_CS, + NAND_BUSWIDTH_16, NULL); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal(sdrc_cke0, OMAP_PIN_OUTPUT); diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index 70a81f9..0ee820b 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -108,41 +108,41 @@ __init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs) defined(CONFIG_MTD_NAND_OMAP2_MODULE) /* Note that all values in this struct are in nanoseconds */ -static struct gpmc_timings nand_timings = { +struct gpmc_timings nand_default_timings[1] = { + { + .sync_clk = 0, - .sync_clk = 0, + .cs_on = 0, + .cs_rd_off = 36, + .cs_wr_off = 36, - .cs_on = 0, - .cs_rd_off = 36, - .cs_wr_off = 36, + .adv_on = 6, + .adv_rd_off = 24, + .adv_wr_off = 36, - .adv_on = 6, - .adv_rd_off = 24, - .adv_wr_off = 36, + .we_off = 30, + .oe_off = 48, - .we_off = 30, - .oe_off = 48, + .access = 54, + .rd_cycle = 72, + .wr_cycle = 72, - .access = 54, - .rd_cycle = 72, - .wr_cycle = 72, - - .wr_access = 30, - .wr_data_mux_bus = 0, + .wr_access = 30, + .wr_data_mux_bus = 0, + }, }; -static struct omap_nand_platform_data board_nand_data = { - .gpmc_t = nand_timings, -}; +static struct omap_nand_platform_data board_nand_data; void -__init board_nand_init(struct mtd_partition *nand_parts, - u8 nr_parts, u8 cs, int nand_type) +__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs, + int nand_type, struct gpmc_timings *gpmc_t) { board_nand_data.cs = cs; board_nand_data.parts = nand_parts; board_nand_data.nr_parts= nr_parts; board_nand_data.devsize = nand_type; + board_nand_data.gpmc_t = gpmc_t; board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT; board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs; @@ -243,5 +243,6 @@ void __init board_flash_init(struct flash_partitions partition_info[], pr_err(NAND: Unable to find configuration in GPMC\n); else board_nand_init(partition_info[2].parts, - partition_info[2].nr_parts, nandcs, nand_type); + partition_info[2].nr_parts, nandcs, + nand_type
[PATCH v2 2/3] ARM: OMAP2+: onenand: prepare for gpmc driver migration
Reorganize gpmc-onenand initialization so that changes required for gpmc driver migration can be made smooth. Ensuring sync read/write are disabled in onenand cannot be expected to work properly unless GPMC is setup, this has been removed. And invocation of set_async has been moved from set_sync to gpmc_onenand_init function; gpmc for onenand needs to be initialized to async mode (even for sync mode initially). Ensuring that onenand part has been setup for async mode has been moved now to setup function. Thanks to Jon for his suggestions on improving this change. Signed-off-by: Afzal Mohammed af...@ti.com --- v2: Move ensuring that async mode in OneNAND has been setup from set_sync to setup function, improve commit message arch/arm/mach-omap2/gpmc-onenand.c | 25 ++--- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 71d7c07..975c1f9 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -38,10 +38,9 @@ static struct platform_device gpmc_onenand_device = { .resource = gpmc_onenand_resource, }; -static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) +static int omap2_onenand_set_async_mode(int cs) { struct gpmc_timings t; - u32 reg; int err; const int t_cer = 15; @@ -55,11 +54,6 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) const int t_wpl = 40; const int t_wph = 30; - /* Ensure sync read and sync write are disabled */ - reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); - reg = ~ONENAND_SYS_CFG1_SYNC_READ ~ONENAND_SYS_CFG1_SYNC_WRITE; - writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); - memset(t, 0, sizeof(t)); t.sync_clk = 0; t.cs_on = 0; @@ -95,10 +89,6 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) if (err) return err; - /* Ensure sync read and sync write are disabled */ - reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); - reg = ~ONENAND_SYS_CFG1_SYNC_READ ~ONENAND_SYS_CFG1_SYNC_WRITE; - writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); return 0; } @@ -197,13 +187,10 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, sync_read = 1; sync_write = 1; } else - return omap2_onenand_set_async_mode(cs, onenand_base); + return 0; if (!freq) { /* Very first call freq is not known */ - err = omap2_onenand_set_async_mode(cs, onenand_base); - if (err) - return err; freq = omap2_onenand_get_freq(cfg, onenand_base, clk_dep); first_time = 1; } @@ -385,6 +372,12 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr) { struct device *dev = gpmc_onenand_device.dev; + u32 reg; + + /* Ensure sync read and sync write are disabled */ + reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); + reg = ~ONENAND_SYS_CFG1_SYNC_READ ~ONENAND_SYS_CFG1_SYNC_WRITE; + writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); /* Set sync timings in GPMC */ if (omap2_onenand_set_sync_mode(gpmc_onenand_data, onenand_base, @@ -421,6 +414,8 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) gpmc_onenand_resource.end = gpmc_onenand_resource.start + ONENAND_IO_SIZE - 1; + omap2_onenand_set_async_mode(gpmc_onenand_data-cs); + if (platform_device_register(gpmc_onenand_device) 0) { pr_err(%s: Unable to register OneNAND device\n, __func__); gpmc_cs_free(gpmc_onenand_data-cs); -- 1.7.10.2 -- 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 v2 3/3] ARM: OMAP2+: gpmc: handle additional timings
Configure busturnaround, cycle2cycledelay, waitmonitoringtime, clkactivationtime in gpmc_cs_set_timings(). This is done so that boards can configure these parameters of gpmc in Kernel instead of relying on bootloader. This needed change to two existing users that were configuring clk activation time by directly writing to registers. Thanks to Tony for making me aware of the issue being kind enough to test this change. Signed-off-by: Afzal Mohammed af...@ti.com --- v2: Make use of timings api for setting clock activation time, and remove direct writing to register for clock activation. Peripherals making use of it were tusb6010 onenand arch/arm/mach-omap2/gpmc-onenand.c |3 ++- arch/arm/mach-omap2/gpmc.c |6 ++ arch/arm/mach-omap2/usb-tusb6010.c |3 ++- arch/arm/plat-omap/include/plat/gpmc.h |6 ++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 975c1f9..476b18c 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -316,6 +316,8 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div + ticks_cez); + t.clk_activation = fclk_offset_ns; + /* Write */ if (sync_write) { t.adv_wr_off = t.adv_rd_off; @@ -349,7 +351,6 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) | (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) | (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) | - GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) | GPMC_CONFIG1_PAGE_LEN(2) | (cpu_is_omap34xx() ? 0 : (GPMC_CONFIG1_WAIT_READ_MON | diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 578fd4c..517953f 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -313,6 +313,12 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access); + GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, bus_turnaround); + GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay); + + GPMC_SET_ONE(GPMC_CS_CONFIG1, 18, 19, wait_monitoring); + GPMC_SET_ONE(GPMC_CS_CONFIG1, 25, 26, clk_activation); + if (cpu_is_omap34xx()) { GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus); GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access); diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c index db84a46..5c98755 100644 --- a/arch/arm/mach-omap2/usb-tusb6010.c +++ b/arch/arm/mach-omap2/usb-tusb6010.c @@ -174,6 +174,8 @@ static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps) tmp = t.cs_wr_off * 1000 + 7000 /* t_scsn_rdy_z */; t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps); + t.clk_activation = gpmc_ticks_to_ns(1); + return gpmc_cs_set_timings(sync_cs, t); } @@ -283,7 +285,6 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data, | GPMC_CONFIG1_READTYPE_SYNC | GPMC_CONFIG1_WRITEMULTIPLE_SUPP | GPMC_CONFIG1_WRITETYPE_SYNC - | GPMC_CONFIG1_CLKACTIVATIONTIME(1) | GPMC_CONFIG1_PAGE_LEN(2) | GPMC_CONFIG1_WAIT_READ_MON | GPMC_CONFIG1_WAIT_WRITE_MON diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 2e6e259..802fb22 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -128,6 +128,12 @@ struct gpmc_timings { u16 rd_cycle; /* Total read cycle time */ u16 wr_cycle; /* Total write cycle time */ + u16 bus_turnaround; + u16 cycle2cycle_delay; + + u16 wait_monitoring; + u16 clk_activation; + /* The following are only on OMAP3430 */ u16 wr_access; /* WRACCESSTIME */ u16 wr_data_mux_bus;/* WRDATAONADMUXBUS */ -- 1.7.10.2 -- 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 v3 0/3] Prepare for GPMC driver conversion
Hi, Objective of this series is to make things easy for GPMC driver conversion series by separating out more things from driver conversion series. This series, 1. Unifies NAND platform initialization functions 2. Prepares OneNAND platform code for gpmc driver migration 3. Handles additional timings in Kernel This series is based on 3.5-rc1 made on top of [PATCH v2 00/10] Prepare for GPMC driver conversion (w.r.t MTD) {http://www.mail-archive.com/linux-omap@vger.kernel.org/msg70096.html} These changes has been tested with omap3evm beagle board. Relevant GPMC peripherals that got tested by this were NAND (beagle) and OneNAND (using local patches for omap3evm) Regards Afzal v3: 1. Refactor OneNAND set_sync/async functions to separate out timing and configurations 2. Handle bool type timings too 3. Swap patches 2 3 due to dependency of OneNAND change on newly added bool type timings v2: 1. Make use of timing api for setting clock activation time, and remove direct writing to register for clock activation. Peripherals making use of it were tusb6010 onenand 2. Move ensuring that async mode in OneNAND has been setup from set_sync to setup function, improve commit message Afzal Mohammed (3): ARM: OMAP2+: nand: unify init functions ARM: OMAP2+: gpmc: handle additional timings ARM: OMAP2+: onenand: prepare for gpmc driver migration arch/arm/mach-omap2/board-devkit8000.c |8 +- arch/arm/mach-omap2/board-flash.c | 45 - arch/arm/mach-omap2/board-flash.h |6 +- arch/arm/mach-omap2/board-igep0020.c |2 +- arch/arm/mach-omap2/board-ldp.c|4 +- arch/arm/mach-omap2/board-omap3beagle.c|8 +- arch/arm/mach-omap2/board-omap3touchbook.c |8 +- arch/arm/mach-omap2/board-overo.c |7 +- arch/arm/mach-omap2/board-zoom.c |5 +- arch/arm/mach-omap2/common-board-devices.c | 46 -- arch/arm/mach-omap2/common-board-devices.h |1 - arch/arm/mach-omap2/gpmc-onenand.c | 137 ++-- arch/arm/mach-omap2/gpmc.c | 45 + arch/arm/mach-omap2/usb-tusb6010.c |3 +- arch/arm/plat-omap/include/plat/gpmc.h | 19 15 files changed, 193 insertions(+), 151 deletions(-) -- 1.7.10.2 -- 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 v3 1/3] ARM: OMAP2+: nand: unify init functions
Helper function for updating nand platform data has been added the capability to take timing structure arguement. Usage of omap_nand_flash_init() has been replaced by modifed one, omap_nand_flash_init was doing things similar to board_nand_init except that NAND CS# were being acquired based on bootloader setting. As CS# is hardwired for a given board, acquiring gpmc CS# has been removed, and updated with the value on board. NAND CS# used in beagle board was found to be CS0. Thomas Weber thomas.weber.li...@googlemail.com reported that value of devkit8000 to be CS0. Overo board was found to be using CS0 based on u-boot, while google grep says omap3touchbook too has CS0. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-devkit8000.c |8 +++-- arch/arm/mach-omap2/board-flash.c | 45 ++- arch/arm/mach-omap2/board-flash.h |6 ++-- arch/arm/mach-omap2/board-igep0020.c |2 +- arch/arm/mach-omap2/board-ldp.c|4 +-- arch/arm/mach-omap2/board-omap3beagle.c|8 +++-- arch/arm/mach-omap2/board-omap3touchbook.c |8 +++-- arch/arm/mach-omap2/board-overo.c |7 +++-- arch/arm/mach-omap2/board-zoom.c |5 +-- arch/arm/mach-omap2/common-board-devices.c | 46 arch/arm/mach-omap2/common-board-devices.h |1 - 11 files changed, 56 insertions(+), 84 deletions(-) diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 6567c1c..6ee429a 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -59,8 +59,11 @@ #include mux.h #include hsmmc.h +#include board-flash.h #include common-board-devices.h +#defineNAND_CS 0 + #define OMAP_DM9000_GPIO_IRQ 25 #define OMAP3_DEVKIT_TS_GPIO 27 @@ -628,8 +631,9 @@ static void __init devkit8000_init(void) usb_musb_init(NULL); usbhs_init(usbhs_bdata); - omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions, -ARRAY_SIZE(devkit8000_nand_partitions)); + board_nand_init(devkit8000_nand_partitions, + ARRAY_SIZE(devkit8000_nand_partitions), NAND_CS, + NAND_BUSWIDTH_16, NULL); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal(sdrc_cke0, OMAP_PIN_OUTPUT); diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index 70a81f9..0ee820b 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -108,41 +108,41 @@ __init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs) defined(CONFIG_MTD_NAND_OMAP2_MODULE) /* Note that all values in this struct are in nanoseconds */ -static struct gpmc_timings nand_timings = { +struct gpmc_timings nand_default_timings[1] = { + { + .sync_clk = 0, - .sync_clk = 0, + .cs_on = 0, + .cs_rd_off = 36, + .cs_wr_off = 36, - .cs_on = 0, - .cs_rd_off = 36, - .cs_wr_off = 36, + .adv_on = 6, + .adv_rd_off = 24, + .adv_wr_off = 36, - .adv_on = 6, - .adv_rd_off = 24, - .adv_wr_off = 36, + .we_off = 30, + .oe_off = 48, - .we_off = 30, - .oe_off = 48, + .access = 54, + .rd_cycle = 72, + .wr_cycle = 72, - .access = 54, - .rd_cycle = 72, - .wr_cycle = 72, - - .wr_access = 30, - .wr_data_mux_bus = 0, + .wr_access = 30, + .wr_data_mux_bus = 0, + }, }; -static struct omap_nand_platform_data board_nand_data = { - .gpmc_t = nand_timings, -}; +static struct omap_nand_platform_data board_nand_data; void -__init board_nand_init(struct mtd_partition *nand_parts, - u8 nr_parts, u8 cs, int nand_type) +__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs, + int nand_type, struct gpmc_timings *gpmc_t) { board_nand_data.cs = cs; board_nand_data.parts = nand_parts; board_nand_data.nr_parts= nr_parts; board_nand_data.devsize = nand_type; + board_nand_data.gpmc_t = gpmc_t; board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT; board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs; @@ -243,5 +243,6 @@ void __init board_flash_init(struct flash_partitions partition_info[], pr_err(NAND: Unable to find configuration in GPMC\n); else board_nand_init(partition_info[2].parts, - partition_info[2].nr_parts, nandcs, nand_type); + partition_info[2].nr_parts, nandcs, + nand_type
[PATCH v3 2/3] ARM: OMAP2+: gpmc: handle additional timings
Configure busturnaround, cycle2cycledelay, waitmonitoringtime, clkactivationtime in gpmc_cs_set_timings(). This is done so that boards can configure these parameters of gpmc in Kernel instead of relying on bootloader. Also configure bool type timings like extradelay. This needed change to two existing users that were configuring clk activation time by directly writing to registers. Thanks to Tony for making me aware of the issue being kind enough to test this change. Signed-off-by: Afzal Mohammed af...@ti.com --- v3: Handle bool type timings too v2: Make use of timing api for setting clock activation time, and remove direct writing to register for clock activation. Peripherals making use of it were tusb6010 onenand arch/arm/mach-omap2/gpmc-onenand.c |3 ++- arch/arm/mach-omap2/gpmc.c | 45 arch/arm/mach-omap2/usb-tusb6010.c |3 ++- arch/arm/plat-omap/include/plat/gpmc.h | 19 ++ 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 71d7c07..8863e0a 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -329,6 +329,8 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div + ticks_cez); + t.clk_activation = fclk_offset_ns; + /* Write */ if (sync_write) { t.adv_wr_off = t.adv_rd_off; @@ -362,7 +364,6 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) | (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) | (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) | - GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) | GPMC_CONFIG1_PAGE_LEN(2) | (cpu_is_omap34xx() ? 0 : (GPMC_CONFIG1_WAIT_READ_MON | diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 578fd4c..8b0978f 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -64,6 +64,13 @@ #define GPMC_ECC_CTRL_ECCREG8 0x008 #define GPMC_ECC_CTRL_ECCREG9 0x009 +#defineGPMC_CONFIG2_CSEXTRADELAY BIT(7) +#defineGPMC_CONFIG3_ADVEXTRADELAY BIT(7) +#defineGPMC_CONFIG4_OEEXTRADELAY BIT(7) +#defineGPMC_CONFIG4_WEEXTRADELAY BIT(23) +#defineGPMC_CONFIG6_CYCLE2CYCLEDIFFCSENBIT(6) +#defineGPMC_CONFIG6_CYCLE2CYCLESAMECSENBIT(7) + #define GPMC_CS0_OFFSET0x60 #define GPMC_CS_SIZE 0x30 @@ -220,6 +227,36 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns) return ticks * gpmc_get_fclk_period() / 1000; } +static inline void gpmc_cs_modify_reg(int cs, int reg, u32 mask, bool value) +{ + u32 l; + + l = gpmc_cs_read_reg(cs, reg); + if (value) + l |= mask; + else + l = ~mask; + gpmc_cs_write_reg(cs, reg, l); +} + +static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p) +{ + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG1, + GPMC_CONFIG1_TIME_PARA_GRAN, p-time_para_granularity); + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG2, + GPMC_CONFIG2_CSEXTRADELAY, p-cs_extra_delay); + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG3, + GPMC_CONFIG3_ADVEXTRADELAY, p-adv_extra_delay); + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4, + GPMC_CONFIG4_OEEXTRADELAY, p-oe_extra_delay); + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4, + GPMC_CONFIG4_OEEXTRADELAY, p-we_extra_delay); + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6, + GPMC_CONFIG6_CYCLE2CYCLESAMECSEN, p-cycle2cyclesamecsen); + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6, + GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN, p-cycle2cyclediffcsen); +} + #ifdef DEBUG static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, int time, const char *name) @@ -313,6 +350,12 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access); + GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, bus_turnaround); + GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay); + + GPMC_SET_ONE(GPMC_CS_CONFIG1, 18, 19, wait_monitoring); + GPMC_SET_ONE(GPMC_CS_CONFIG1, 25, 26, clk_activation); + if (cpu_is_omap34xx()) { GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus); GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access); @@ -332,6 +375,8 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t
[PATCH v3 3/3] ARM: OMAP2+: onenand: prepare for gpmc driver migration
Reorganize gpmc-onenand initialization so that changes required for gpmc driver migration can be made smooth. Ensuring sync read/write are disabled in onenand cannot be expected to work properly unless GPMC is setup, this has been removed. Refactor set_async_mode set_sync_mode functions to separate out timing calculation actual configuration (GPMC OneNAND side). Thanks to Jon for his suggestions. Signed-off-by: Afzal Mohammed af...@ti.com --- v3: Refactor set_sync/async functions to separate out timing and configurations v2: Move ensuring that async mode in OneNAND has been setup from set_sync to setup function, improve commit message arch/arm/mach-omap2/gpmc-onenand.c | 134 +++- 1 file changed, 69 insertions(+), 65 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 8863e0a..789ca8c9 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -15,6 +15,7 @@ #include linux/platform_device.h #include linux/mtd/onenand_regs.h #include linux/io.h +#include linux/err.h #include asm/mach/flash.h @@ -25,6 +26,7 @@ #defineONENAND_IO_SIZE SZ_128K +static int hf, vhf, sync_read, sync_write, latency; static struct omap_onenand_platform_data *gpmc_onenand_data; static struct resource gpmc_onenand_resource = { @@ -38,11 +40,9 @@ static struct platform_device gpmc_onenand_device = { .resource = gpmc_onenand_resource, }; -static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) +static struct gpmc_timings omap2_onenand_calc_async_timings(void) { struct gpmc_timings t; - u32 reg; - int err; const int t_cer = 15; const int t_avdp = 12; @@ -55,11 +55,6 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) const int t_wpl = 40; const int t_wph = 30; - /* Ensure sync read and sync write are disabled */ - reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); - reg = ~ONENAND_SYS_CFG1_SYNC_READ ~ONENAND_SYS_CFG1_SYNC_WRITE; - writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); - memset(t, 0, sizeof(t)); t.sync_clk = 0; t.cs_on = 0; @@ -86,12 +81,21 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph); t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez); + return t; +} + +static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base, + struct gpmc_timings *t) +{ + u32 reg; + int err; + /* Configure GPMC for asynchronous read */ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, GPMC_CONFIG1_DEVICESIZE_16 | GPMC_CONFIG1_MUXADDDATA); - err = gpmc_cs_set_timings(cs, t); + err = gpmc_cs_set_timings(cs, t); if (err) return err; @@ -103,8 +107,7 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) return 0; } -static void set_onenand_cfg(void __iomem *onenand_base, int latency, - int sync_read, int sync_write, int hf, int vhf) +static void set_onenand_cfg(void __iomem *onenand_base) { u32 reg; @@ -172,9 +175,9 @@ static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg, return freq; } -static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, - void __iomem *onenand_base, - int *freq_ptr) +static struct gpmc_timings +omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg, + int freq, bool clk_dep) { struct gpmc_timings t; const int t_cer = 15; @@ -184,28 +187,15 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, const int t_wpl = 40; const int t_wph = 30; int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo; - int div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency; - int first_time = 0, hf = 0, vhf = 0, sync_read = 0, sync_write = 0; - int err, ticks_cez; - int cs = cfg-cs, freq = *freq_ptr; - u32 reg; - bool clk_dep = false; + int div, fclk_offset_ns, fclk_offset, gpmc_clk_ns; + int ticks_cez; + int cs = cfg-cs; if (cfg-flags ONENAND_SYNC_READ) { sync_read = 1; } else if (cfg-flags ONENAND_SYNC_READWRITE) { sync_read = 1; sync_write = 1; - } else - return omap2_onenand_set_async_mode(cs, onenand_base); - - if (!freq) { - /* Very first call freq is not known */ - err = omap2_onenand_set_async_mode(cs
[PATCH v4 0/3] Prepare for GPMC driver conversion
Hi, Objective of this series is to make things easy for GPMC driver conversion series by separating out more things from driver conversion series. This series, 1. Unifies NAND platform initialization functions 2. Prepares OneNAND platform code for gpmc driver migration 3. Handles additional timings in Kernel This series is based on 3.5-rc1 made on top of [PATCH v2 00/10] Prepare for GPMC driver conversion (w.r.t MTD) {http://www.mail-archive.com/linux-omap@vger.kernel.org/msg70096.html} These changes has been tested with omap3evm beagle board. Relevant GPMC peripherals that got tested by this were NAND (beagle) and OneNAND (using local patches for omap3evm) Regards Afzal v4: 1. Reorganize OneNAND set_sync/async functions in a better way v3: 1. Refactor OneNAND set_sync/async functions to separate out timing and configurations 2. Handle bool type timings too 3. Swap patches 2 3 due to dependency of OneNAND change on newly added bool type timings v2: 1. Make use of timing api for setting clock activation time, and remove direct writing to register for clock activation. Peripherals making use of it were tusb6010 onenand 2. Move ensuring that async mode in OneNAND has been setup from set_sync to setup function, improve commit message Afzal Mohammed (3): ARM: OMAP2+: nand: unify init functions ARM: OMAP2+: gpmc: handle additional timings ARM: OMAP2+: onenand: prepare for gpmc driver migration arch/arm/mach-omap2/board-devkit8000.c |8 +- arch/arm/mach-omap2/board-flash.c | 45 arch/arm/mach-omap2/board-flash.h |6 +- arch/arm/mach-omap2/board-igep0020.c |2 +- arch/arm/mach-omap2/board-ldp.c|4 +- arch/arm/mach-omap2/board-omap3beagle.c|8 +- arch/arm/mach-omap2/board-omap3touchbook.c |8 +- arch/arm/mach-omap2/board-overo.c |7 +- arch/arm/mach-omap2/board-zoom.c |5 +- arch/arm/mach-omap2/common-board-devices.c | 46 arch/arm/mach-omap2/common-board-devices.h |1 - arch/arm/mach-omap2/gpmc-onenand.c | 156 +++- arch/arm/mach-omap2/gpmc.c | 45 arch/arm/mach-omap2/usb-tusb6010.c |3 +- arch/arm/plat-omap/include/plat/gpmc.h | 19 15 files changed, 207 insertions(+), 156 deletions(-) -- 1.7.10.2 -- 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 v4 1/3] ARM: OMAP2+: nand: unify init functions
Helper function for updating nand platform data has been added the capability to take timing structure arguement. Usage of omap_nand_flash_init() has been replaced by modifed one, omap_nand_flash_init was doing things similar to board_nand_init except that NAND CS# were being acquired based on bootloader setting. As CS# is hardwired for a given board, acquiring gpmc CS# has been removed, and updated with the value on board. NAND CS# used in beagle board was found to be CS0. Thomas Weber thomas.weber.li...@googlemail.com reported that value of devkit8000 to be CS0. Overo board was found to be using CS0 based on u-boot, while google grep says omap3touchbook too has CS0. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-devkit8000.c |8 +++-- arch/arm/mach-omap2/board-flash.c | 45 ++- arch/arm/mach-omap2/board-flash.h |6 ++-- arch/arm/mach-omap2/board-igep0020.c |2 +- arch/arm/mach-omap2/board-ldp.c|4 +-- arch/arm/mach-omap2/board-omap3beagle.c|8 +++-- arch/arm/mach-omap2/board-omap3touchbook.c |8 +++-- arch/arm/mach-omap2/board-overo.c |7 +++-- arch/arm/mach-omap2/board-zoom.c |5 +-- arch/arm/mach-omap2/common-board-devices.c | 46 arch/arm/mach-omap2/common-board-devices.h |1 - 11 files changed, 56 insertions(+), 84 deletions(-) diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 6567c1c..6ee429a 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -59,8 +59,11 @@ #include mux.h #include hsmmc.h +#include board-flash.h #include common-board-devices.h +#defineNAND_CS 0 + #define OMAP_DM9000_GPIO_IRQ 25 #define OMAP3_DEVKIT_TS_GPIO 27 @@ -628,8 +631,9 @@ static void __init devkit8000_init(void) usb_musb_init(NULL); usbhs_init(usbhs_bdata); - omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions, -ARRAY_SIZE(devkit8000_nand_partitions)); + board_nand_init(devkit8000_nand_partitions, + ARRAY_SIZE(devkit8000_nand_partitions), NAND_CS, + NAND_BUSWIDTH_16, NULL); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal(sdrc_cke0, OMAP_PIN_OUTPUT); diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index 70a81f9..0ee820b 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -108,41 +108,41 @@ __init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs) defined(CONFIG_MTD_NAND_OMAP2_MODULE) /* Note that all values in this struct are in nanoseconds */ -static struct gpmc_timings nand_timings = { +struct gpmc_timings nand_default_timings[1] = { + { + .sync_clk = 0, - .sync_clk = 0, + .cs_on = 0, + .cs_rd_off = 36, + .cs_wr_off = 36, - .cs_on = 0, - .cs_rd_off = 36, - .cs_wr_off = 36, + .adv_on = 6, + .adv_rd_off = 24, + .adv_wr_off = 36, - .adv_on = 6, - .adv_rd_off = 24, - .adv_wr_off = 36, + .we_off = 30, + .oe_off = 48, - .we_off = 30, - .oe_off = 48, + .access = 54, + .rd_cycle = 72, + .wr_cycle = 72, - .access = 54, - .rd_cycle = 72, - .wr_cycle = 72, - - .wr_access = 30, - .wr_data_mux_bus = 0, + .wr_access = 30, + .wr_data_mux_bus = 0, + }, }; -static struct omap_nand_platform_data board_nand_data = { - .gpmc_t = nand_timings, -}; +static struct omap_nand_platform_data board_nand_data; void -__init board_nand_init(struct mtd_partition *nand_parts, - u8 nr_parts, u8 cs, int nand_type) +__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs, + int nand_type, struct gpmc_timings *gpmc_t) { board_nand_data.cs = cs; board_nand_data.parts = nand_parts; board_nand_data.nr_parts= nr_parts; board_nand_data.devsize = nand_type; + board_nand_data.gpmc_t = gpmc_t; board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT; board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs; @@ -243,5 +243,6 @@ void __init board_flash_init(struct flash_partitions partition_info[], pr_err(NAND: Unable to find configuration in GPMC\n); else board_nand_init(partition_info[2].parts, - partition_info[2].nr_parts, nandcs, nand_type); + partition_info[2].nr_parts, nandcs, + nand_type
[PATCH v4 2/3] ARM: OMAP2+: gpmc: handle additional timings
Configure busturnaround, cycle2cycledelay, waitmonitoringtime, clkactivationtime in gpmc_cs_set_timings(). This is done so that boards can configure these parameters of gpmc in Kernel instead of relying on bootloader. Also configure bool type timings like extradelay. This needed change to two existing users that were configuring clk activation time by directly writing to registers. Thanks to Tony for making me aware of the issue being kind enough to test this change. Signed-off-by: Afzal Mohammed af...@ti.com --- v3: Handle bool type timings too v2: Make use of timing api for setting clock activation time, and remove direct writing to register for clock activation. Peripherals making use of it were tusb6010 onenand arch/arm/mach-omap2/gpmc-onenand.c |3 ++- arch/arm/mach-omap2/gpmc.c | 45 arch/arm/mach-omap2/usb-tusb6010.c |3 ++- arch/arm/plat-omap/include/plat/gpmc.h | 19 ++ 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 71d7c07..8863e0a 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -329,6 +329,8 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div + ticks_cez); + t.clk_activation = fclk_offset_ns; + /* Write */ if (sync_write) { t.adv_wr_off = t.adv_rd_off; @@ -362,7 +364,6 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) | (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) | (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) | - GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) | GPMC_CONFIG1_PAGE_LEN(2) | (cpu_is_omap34xx() ? 0 : (GPMC_CONFIG1_WAIT_READ_MON | diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 578fd4c..8b0978f 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -64,6 +64,13 @@ #define GPMC_ECC_CTRL_ECCREG8 0x008 #define GPMC_ECC_CTRL_ECCREG9 0x009 +#defineGPMC_CONFIG2_CSEXTRADELAY BIT(7) +#defineGPMC_CONFIG3_ADVEXTRADELAY BIT(7) +#defineGPMC_CONFIG4_OEEXTRADELAY BIT(7) +#defineGPMC_CONFIG4_WEEXTRADELAY BIT(23) +#defineGPMC_CONFIG6_CYCLE2CYCLEDIFFCSENBIT(6) +#defineGPMC_CONFIG6_CYCLE2CYCLESAMECSENBIT(7) + #define GPMC_CS0_OFFSET0x60 #define GPMC_CS_SIZE 0x30 @@ -220,6 +227,36 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns) return ticks * gpmc_get_fclk_period() / 1000; } +static inline void gpmc_cs_modify_reg(int cs, int reg, u32 mask, bool value) +{ + u32 l; + + l = gpmc_cs_read_reg(cs, reg); + if (value) + l |= mask; + else + l = ~mask; + gpmc_cs_write_reg(cs, reg, l); +} + +static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p) +{ + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG1, + GPMC_CONFIG1_TIME_PARA_GRAN, p-time_para_granularity); + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG2, + GPMC_CONFIG2_CSEXTRADELAY, p-cs_extra_delay); + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG3, + GPMC_CONFIG3_ADVEXTRADELAY, p-adv_extra_delay); + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4, + GPMC_CONFIG4_OEEXTRADELAY, p-oe_extra_delay); + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4, + GPMC_CONFIG4_OEEXTRADELAY, p-we_extra_delay); + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6, + GPMC_CONFIG6_CYCLE2CYCLESAMECSEN, p-cycle2cyclesamecsen); + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6, + GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN, p-cycle2cyclediffcsen); +} + #ifdef DEBUG static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, int time, const char *name) @@ -313,6 +350,12 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access); + GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, bus_turnaround); + GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay); + + GPMC_SET_ONE(GPMC_CS_CONFIG1, 18, 19, wait_monitoring); + GPMC_SET_ONE(GPMC_CS_CONFIG1, 25, 26, clk_activation); + if (cpu_is_omap34xx()) { GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus); GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access); @@ -332,6 +375,8 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t
[PATCH v4 3/3] ARM: OMAP2+: onenand: prepare for gpmc driver migration
Reorganize gpmc-onenand initialization so that changes required for gpmc driver migration can be made smooth. Ensuring sync read/write are disabled in onenand cannot be expected to work properly unless GPMC is setup, this has been removed. Refactor set_async_mode set_sync_mode functions to separate out timing calculation actual configuration (GPMC OneNAND side). Thanks to Jon for his suggestions. Signed-off-by: Afzal Mohammed af...@ti.com --- v4: Reorganize set_sync/async functions in a better way v3: Refactor set_sync/async functions to separate out timing and configurations v2: Move ensuring that async mode in OneNAND has been setup from set_sync to setup function, improve commit message arch/arm/mach-omap2/gpmc-onenand.c | 153 +++- 1 file changed, 83 insertions(+), 70 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 8863e0a..878182b 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -15,6 +15,7 @@ #include linux/platform_device.h #include linux/mtd/onenand_regs.h #include linux/io.h +#include linux/err.h #include asm/mach/flash.h @@ -25,6 +26,7 @@ #defineONENAND_IO_SIZE SZ_128K +static int hf, vhf, sync_read, sync_write, latency; static struct omap_onenand_platform_data *gpmc_onenand_data; static struct resource gpmc_onenand_resource = { @@ -38,11 +40,9 @@ static struct platform_device gpmc_onenand_device = { .resource = gpmc_onenand_resource, }; -static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) +static struct gpmc_timings omap2_onenand_calc_async_timings(void) { struct gpmc_timings t; - u32 reg; - int err; const int t_cer = 15; const int t_avdp = 12; @@ -55,11 +55,6 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) const int t_wpl = 40; const int t_wph = 30; - /* Ensure sync read and sync write are disabled */ - reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); - reg = ~ONENAND_SYS_CFG1_SYNC_READ ~ONENAND_SYS_CFG1_SYNC_WRITE; - writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); - memset(t, 0, sizeof(t)); t.sync_clk = 0; t.cs_on = 0; @@ -86,25 +81,30 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph); t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez); + return t; +} + +static int gpmc_set_async_mode(int cs, struct gpmc_timings *t) +{ /* Configure GPMC for asynchronous read */ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, GPMC_CONFIG1_DEVICESIZE_16 | GPMC_CONFIG1_MUXADDDATA); - err = gpmc_cs_set_timings(cs, t); - if (err) - return err; + return gpmc_cs_set_timings(cs, t); +} + +static void omap2_onenand_set_async_mode(void __iomem *onenand_base) +{ + u32 reg; /* Ensure sync read and sync write are disabled */ reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); reg = ~ONENAND_SYS_CFG1_SYNC_READ ~ONENAND_SYS_CFG1_SYNC_WRITE; writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); - - return 0; } -static void set_onenand_cfg(void __iomem *onenand_base, int latency, - int sync_read, int sync_write, int hf, int vhf) +static void set_onenand_cfg(void __iomem *onenand_base) { u32 reg; @@ -172,9 +172,9 @@ static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg, return freq; } -static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, - void __iomem *onenand_base, - int *freq_ptr) +static struct gpmc_timings +omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg, + int freq, bool clk_dep) { struct gpmc_timings t; const int t_cer = 15; @@ -184,28 +184,15 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, const int t_wpl = 40; const int t_wph = 30; int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo; - int div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency; - int first_time = 0, hf = 0, vhf = 0, sync_read = 0, sync_write = 0; - int err, ticks_cez; - int cs = cfg-cs, freq = *freq_ptr; - u32 reg; - bool clk_dep = false; + int div, fclk_offset_ns, fclk_offset, gpmc_clk_ns; + int ticks_cez; + int cs = cfg-cs; if (cfg-flags ONENAND_SYNC_READ) { sync_read = 1; } else if (cfg-flags ONENAND_SYNC_READWRITE) { sync_read = 1; sync_write = 1; - } else - return
[PATCH v6 00/13] GPMC driver conversion
Hi, This series is based on 3.5-rc1, and is dependent on [1,2,3], and has been tested on omap3evm (smsc911x) rev G C and beagle board(nand). Also using private patches, nand onenand was tested on omap3evm, rev G C respectively (as support for these were not in mainline) All boards will work using the old existing interface. Further patch series would convert all boards to use new interface. Many of GPMC peripherals depend on bootloader for configuration. This is going to be deprecated. feature-removal-schedule.txt will be updated in one of the upcoming patch series. Thanks to Tony Jon for their various suggestions. [PATCH 03/13] ARM: OMAP2+: gpmc: driver migration helper, is to be reverted once all GPMC peripherals are migrated to use driver interface. GPMC (General Purpose Memory Controller) in brief: GPMC is an unified memory controller dedicated to interfacing external memory devices like Asynchronous SRAM like memories and application specific integrated circuit devices. Asynchronous, synchronous, and page mode burst NOR flash devices NAND flash Pseudo-SRAM devices GPMC details can be referred in AM335X Technical Reference Manual @ http://www.ti.com/lit/pdf/spruh73 Regards Afzal [1] http://www.mail-archive.com/linux-omap@vger.kernel.org/msg70096.html [2] http://www.mail-archive.com/linux-omap@vger.kernel.org/msg70730.html [3] http://www.mail-archive.com/linux-omap@vger.kernel.org/msg69881.html v6: Capability flag added that stores features based on revision Macros used for finding revision Return value from memory setup function corrected Comments added to clarify handling of device type, size Bool type time setting patch removed as has been taken care in [2] Handle variable number of waitpin Warn if driver is unable to configure interrupt Enhance some of commit messages Handle shared writeprotect case Fix a bug in gpmc_create_device Get clk from hwmod Remove unwanted code v5: Make this a purely driver conversion series, i.e. gpmc-mtd interactions has been made as a separate series, so is adding hwmod entry for OMAP2/3. And modifying gpmc peripheral platform initialization has been separated out of this series, so is migrating boards to use new driver interface. GPMC driver conversion which was done in a few patches in v4 has been tranformed to series of small patches. Also care has been taken care that old interface will not break with any of these patches, so both interfaces can coexist. This helps in converting boards one-by-one gradually. Acquiring CS has been thrown out. And conclusive comments on v4 has been addressed. v4: Handle wait pin (except for interrupts), enhance configuration timing interface of GPMC to take care of all boards. Dynamic allocation of interrupt instead of static. Convert remaining peripherals to work with GPMC driver. Handle acquiring NAND CS#, adapt to HWMOD, update HWMOD OMAP2/3 entries, other minor commenst on v3. v3: Single device structure passed from platform for peripherals using multiple CS instead of using multiple device structure having a few redundant data, handle interrupts, GPMC NAND handling by GPMC NAND driver instead of GPMC driver v2: Avoid code movement that kept similar code together (for easy review) Afzal Mohammed (13): ARM: OMAP2+: gpmc: platform definitions ARM: OMAP2+: gpmc: Adapt to HWMOD ARM: OMAP2+: gpmc: driver migration helper ARM: OMAP2+: gpmc: minimal driver support ARM: OMAP2+: gpmc: resource creation helpers ARM: OMAP2+: gpmc: CS configuration helper ARM: OMAP2+: gpmc: register time setting helper ARM: OMAP2+: gpmc: holler if no configuration ARM: OMAP2+: gpmc: waitpin helper ARM: OMAP2+: gpmc: handle connected peripherals ARM: OMAP2+: gpmc: cs reconfigure helper ARM: OMAP2+: gpmc: update nand register info ARM: OMAP2+: gpmc: configure writeprotect arch/arm/mach-omap2/gpmc.c | 797 ++-- arch/arm/plat-omap/include/plat/gpmc.h | 58 +++ 2 files changed, 812 insertions(+), 43 deletions(-) -- 1.7.10.2 -- 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 v6 01/13] ARM: OMAP2+: gpmc: platform definitions
gpmc driver platform definitions Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/plat-omap/include/plat/gpmc.h | 37 1 file changed, 37 insertions(+) diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index b7c9ea6..4e799b1 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -152,6 +152,43 @@ struct gpmc_timings { struct gpmc_bool_timings bool_timings; }; +enum { + has_none, + has_period, + has_clock +}; + +struct gpmc_time_ctrl { + int type; + struct gpmc_timings timings; +}; + +struct gpmc_cs_data { + unsignedcs; + unsigned long mem_size; + unsigned long mem_offset; + boolhave_config; + unsignedconfig; + struct gpmc_time_ctrl time_ctrl; + unsignedirq_config; +}; + +struct gpmc_device_pdata { + char*name; + int id; + void*pdata; + unsignedpdata_size; + struct resource *per_res; + unsignedper_res_cnt; + struct gpmc_cs_data *cs_data; + unsignednum_cs; +}; + +struct gpmc_pdata { + unsignedwaitpin_nr; + struct gpmc_device_pdata**device_pdata; +}; + struct gpmc_nand_regs { void __iomem*gpmc_status; void __iomem*gpmc_nand_command; -- 1.7.10.2 -- 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 v6 02/13] ARM: OMAP2+: gpmc: Adapt to HWMOD
Create API for platforms to adapt gpmc to HWMOD gpmc clk is stored as timing calculation for platform code require its rate so that GPMC timing values (platform data for gpmc driver) can be calculated. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 31 +++ arch/arm/plat-omap/include/plat/gpmc.h |2 ++ 2 files changed, 33 insertions(+) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 8b0978f..f8131f8 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -27,6 +27,7 @@ #include asm/mach-types.h #include plat/gpmc.h +#include plat/omap_device.h #include plat/sdrc.h @@ -937,6 +938,36 @@ static int __init gpmc_init(void) } postcore_initcall(gpmc_init); +__init int omap_gpmc_init(struct gpmc_pdata *pdata) +{ + struct omap_hwmod *oh; + struct platform_device *pdev; + char *name = omap-gpmc; + char *oh_name = gpmc; + + oh = omap_hwmod_lookup(oh_name); + if (!oh) { + pr_err(Could not look up %s\n, oh_name); + return -ENODEV; + } + + gpmc_l3_clk = oh-_clk; + if (!gpmc_l3_clk) { + pr_err(Could not get GPMC clock\n); + return -EINVAL; + } + + pdev = omap_device_build(name, -1, oh, pdata, + sizeof(*pdata), NULL, 0, 0); + if (IS_ERR(pdev)) { + WARN(1, Can't build omap_device for %s:%s.\n, + name, oh-name); + return PTR_ERR(pdev); + } + + return 0; +} + static irqreturn_t gpmc_handle_irq(int irq, void *dev) { int i; diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 4e799b1..157753ab 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -208,6 +208,8 @@ struct gpmc_nand_regs { extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs); extern int gpmc_get_client_irq(unsigned irq_config); +extern int omap_gpmc_init(struct gpmc_pdata *pdata); + extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns); extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps); extern unsigned int gpmc_ticks_to_ns(unsigned int ticks); -- 1.7.10.2 -- 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 v6 03/13] ARM: OMAP2+: gpmc: driver migration helper
A driver is being created out of GPMC code. This is being attempted to acheive by not breaking existing interface, necessitating requirement of GPMC peripherals being able to work with using new interface as well as with the old existing interface. To not break existing, initcall is required as in old interface GPMC is configured at arch initcall and GPMC should be ready to handle old interface by that time Note: This commit has to be reverted once all boards have been converted to work with gpmc driver interface Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 18 +- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index f8131f8..f64f55a 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -941,7 +941,7 @@ postcore_initcall(gpmc_init); __init int omap_gpmc_init(struct gpmc_pdata *pdata) { struct omap_hwmod *oh; - struct platform_device *pdev; + static struct platform_device *pdev; char *name = omap-gpmc; char *oh_name = gpmc; @@ -951,6 +951,11 @@ __init int omap_gpmc_init(struct gpmc_pdata *pdata) return -ENODEV; } + if (pdev != NULL) { + omap_device_delete(pdev-archdata.od); + platform_device_unregister(pdev); + } + gpmc_l3_clk = oh-_clk; if (!gpmc_l3_clk) { pr_err(Could not get GPMC clock\n); @@ -968,6 +973,17 @@ __init int omap_gpmc_init(struct gpmc_pdata *pdata) return 0; } +static int __init gpmc_pre_init(void) +{ + static struct gpmc_device_pdata *gpmc_device_data[1]; + struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, + }; + + return omap_gpmc_init(gpmc_data); +} +postcore_initcall(gpmc_pre_init); + static irqreturn_t gpmc_handle_irq(int irq, void *dev) { int i; -- 1.7.10.2 -- 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 v6 04/13] ARM: OMAP2+: gpmc: minimal driver support
Create a minimal driver out of gpmc code. Responsibilities handled by earlier gpmc initialization is now achieved in probe. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 179 1 file changed, 132 insertions(+), 47 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index f64f55a..08fc5df 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -24,6 +24,7 @@ #include linux/io.h #include linux/module.h #include linux/interrupt.h +#include linux/platform_device.h #include asm/mach-types.h #include plat/gpmc.h @@ -31,6 +32,8 @@ #include plat/sdrc.h +#defineDRIVER_NAME omap-gpmc + /* GPMC register offsets */ #define GPMC_REVISION 0x00 #define GPMC_SYSCONFIG 0x10 @@ -86,6 +89,12 @@ #define ENABLE_PREFETCH(0x1 7) #define DMA_MPU_MODE 2 +#defineGPMC_REVISION_MAJOR(l) ((l 4) 0xf) +#defineGPMC_REVISION_MINOR(l) (l 0xf) + +#defineGPMC_HAS_WR_ACCESS 0x1 +#defineGPMC_HAS_WR_DATA_MUX_BUS0x2 + /* XXX: Only NAND irq has been considered,currently these are the only ones used */ #defineGPMC_NR_IRQ 2 @@ -122,6 +131,21 @@ struct omap3_gpmc_regs { struct gpmc_cs_config cs_context[GPMC_CS_NUM]; }; +struct gpmc_peripheral { + char*name; + int id; + void*pdata; + unsignedpdata_size; + struct resource *per_res; + unsignedper_res_cnt; + struct resource *gpmc_res; + unsignedgpmc_res_cnt; + boolhave_waitpin; + boolwaitpin_high; + unsignedwaitpin; + struct platform_device *pdev; +}; + static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ]; static struct irq_chip gpmc_irq_chip; static unsigned gpmc_irq_start; @@ -131,6 +155,10 @@ static struct resource gpmc_cs_mem[GPMC_CS_NUM]; static DEFINE_SPINLOCK(gpmc_mem_lock); static unsigned int gpmc_cs_map; /* flag for cs which are initialized */ static int gpmc_ecc_used = -EINVAL;/* cs using ecc engine */ +static struct device *gpmc_dev; +static u32 gpmc_capability; +static int gpmc_irq; +static resource_size_t phys_base, mem_size; static void __iomem *gpmc_base; @@ -472,6 +500,19 @@ static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size) return r; } +static int gpmc_cs_delete_mem(int cs) +{ + struct resource *res = gpmc_cs_mem[cs]; + int r; + + spin_lock(gpmc_mem_lock); + r = release_resource(gpmc_cs_mem[cs]); + res-start = res-end = 0; + spin_unlock(gpmc_mem_lock); + + return r; +} + int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) { struct resource *res = gpmc_cs_mem[cs]; @@ -808,7 +849,7 @@ static void gpmc_irq_noop(struct irq_data *data) { } static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; } -static int gpmc_setup_irq(int gpmc_irq) +static int gpmc_setup_irq(void) { int i; u32 regval; @@ -852,7 +893,37 @@ static int gpmc_setup_irq(int gpmc_irq) return request_irq(gpmc_irq, gpmc_handle_irq, 0, gpmc, NULL); } -static void __init gpmc_mem_init(void) +static __exit int gpmc_free_irq(void) +{ + int i; + + if (gpmc_irq) + free_irq(gpmc_irq, NULL); + + for (i = 0; i GPMC_NR_IRQ; i++) { + irq_set_handler(gpmc_client_irq[i].irq, NULL); + irq_set_chip(gpmc_client_irq[i].irq, no_irq_chip); + irq_modify_status(gpmc_client_irq[i].irq, 0, 0); + } + + irq_free_descs(gpmc_irq_start, GPMC_NR_IRQ); + + return 0; +} + +static void __devexit gpmc_mem_exit(void) +{ + int cs; + + for (cs = 0; cs GPMC_CS_NUM; cs++) { + if (!gpmc_cs_mem_enabled(cs)) + continue; + gpmc_cs_delete_mem(cs); + } + +} + +static void __devinit gpmc_mem_init(void) { int cs; unsigned long boot_rom_space = 0; @@ -879,64 +950,78 @@ static void __init gpmc_mem_init(void) } } -static int __init gpmc_init(void) +static __devinit int gpmc_probe(struct platform_device *pdev) { u32 l; - int ret = -EINVAL; - int gpmc_irq; - char *ck = NULL; - - if (cpu_is_omap24xx()) { - ck = core_l3_ck; - if (cpu_is_omap2420()) - l = OMAP2420_GPMC_BASE; - else - l = OMAP34XX_GPMC_BASE; - gpmc_irq = INT_34XX_GPMC_IRQ; - } else if (cpu_is_omap34xx()) { - ck = gpmc_fck; - l = OMAP34XX_GPMC_BASE; - gpmc_irq = INT_34XX_GPMC_IRQ; - } else
[PATCH v6 05/13] ARM: OMAP2+: gpmc: resource creation helpers
Helpers for populating given resource structure with memory interrupt information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 45 1 file changed, 45 insertions(+) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 08fc5df..e427ff4 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -950,6 +950,51 @@ static void __devinit gpmc_mem_init(void) } } +static __devinit int gpmc_setup_cs_mem(struct gpmc_cs_data *cs, + struct resource *res) +{ + unsigned long start; + int ret; + + ret = gpmc_cs_request(cs-cs, cs-mem_size, start); + if (IS_ERR_VALUE(ret)) { + dev_err(gpmc_dev, error: gpmc request on CS: %d\n, cs-cs); + return ret; + } + + res-start = start + cs-mem_offset; + res-end = res-start + cs-mem_size - 1; + res-flags = IORESOURCE_MEM; + + dev_info(gpmc_dev, memory 0x%x-0x%x on CS %d\n, res-start, + res-end, cs-cs); + + return 0; +} + +static __devinit int gpmc_setup_cs_irq(struct gpmc_cs_data *cs, + struct resource *res) +{ + int i, n; + + if (!gpmc_irq || !gpmc_irq_start) { + if (cs-irq_config) + dev_err(gpmc_dev, gpmc not able to configure irq\n); + return 0; + } + + for (i = 0, n = 0; i GPMC_NR_IRQ; i++) + if (gpmc_client_irq[i].bitmask cs-irq_config) { + res[n].start = res[n].end = gpmc_client_irq[i].irq; + res[n].flags = IORESOURCE_IRQ; + dev_info(gpmc_dev, irq %u on CS %d\n, + res[n].start, cs-cs); + n++; + } + + return n; +} + static __devinit int gpmc_probe(struct platform_device *pdev) { u32 l; -- 1.7.10.2 -- 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 v6 06/13] ARM: OMAP2+: gpmc: CS configuration helper
Helper for configuring given CS based on flags. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 39 arch/arm/plat-omap/include/plat/gpmc.h |5 2 files changed, 44 insertions(+) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index e427ff4..8f596ce 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -972,6 +972,45 @@ static __devinit int gpmc_setup_cs_mem(struct gpmc_cs_data *cs, return 0; } +static void gpmc_setup_cs_config(unsigned cs, unsigned conf) +{ + u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + + l = ~(GPMC_CONFIG1_MUXADDDATA | + GPMC_CONFIG1_WRITETYPE_SYNC | + GPMC_CONFIG1_WRITEMULTIPLE_SUPP | + GPMC_CONFIG1_READTYPE_SYNC | + GPMC_CONFIG1_READMULTIPLE_SUPP | + GPMC_CONFIG1_WRAPBURST_SUPP | + GPMC_CONFIG1_DEVICETYPE(~0) | + GPMC_CONFIG1_DEVICESIZE(~0) | + GPMC_CONFIG1_PAGE_LEN(~0)); + + /* device type size bits are cleared above, implying NOR 8 bit, +* only other options possible are NAND 16 bit respectively, +* configure if user asked for it, else default is already setup +* users has been provided with NOR 8 bit macros, nothing to be +* done here as already it has been setup above +*/ + l |= conf GPMC_CONFIG1_DEVICETYPE_NAND; + l |= conf GPMC_CONFIG1_DEVICESIZE_16; + + if (conf GPMC_CONFIG1_PAGE_LEN_8) + l |= GPMC_CONFIG1_PAGE_LEN_8; + else if (conf GPMC_CONFIG1_PAGE_LEN_16) + l |= GPMC_CONFIG1_PAGE_LEN_16; + + conf = (GPMC_CONFIG1_MUXADDDATA | + GPMC_CONFIG1_WRITETYPE_SYNC | + GPMC_CONFIG1_WRITEMULTIPLE_SUPP | + GPMC_CONFIG1_READTYPE_SYNC | + GPMC_CONFIG1_READMULTIPLE_SUPP | + GPMC_CONFIG1_WRAPBURST_SUPP); + l |= conf; + + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l); +} + static __devinit int gpmc_setup_cs_irq(struct gpmc_cs_data *cs, struct resource *res) { diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 157753ab..7187445 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -57,14 +57,19 @@ #define GPMC_CONFIG1_WRITETYPE_SYNC (1 27) #define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val 3) 25) #define GPMC_CONFIG1_PAGE_LEN(val) ((val 3) 23) +#defineGPMC_CONFIG1_PAGE_LEN_4 GPMC_CONFIG1_PAGE_LEN(0) +#defineGPMC_CONFIG1_PAGE_LEN_8 GPMC_CONFIG1_PAGE_LEN(1) +#defineGPMC_CONFIG1_PAGE_LEN_16GPMC_CONFIG1_PAGE_LEN(2) #define GPMC_CONFIG1_WAIT_READ_MON (1 22) #define GPMC_CONFIG1_WAIT_WRITE_MON (1 21) #define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val 3) 18) #define GPMC_CONFIG1_WAIT_PIN_SEL(val) ((val 3) 16) #define GPMC_CONFIG1_DEVICESIZE(val)((val 3) 12) +#defineGPMC_CONFIG1_DEVICESIZE_8 GPMC_CONFIG1_DEVICESIZE(0) #define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1) #define GPMC_CONFIG1_DEVICETYPE(val)((val 3) 10) #define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0) +#defineGPMC_CONFIG1_DEVICETYPE_NANDGPMC_CONFIG1_DEVICETYPE(2) #define GPMC_CONFIG1_MUXADDDATA (1 9) #define GPMC_CONFIG1_TIME_PARA_GRAN (1 4) #define GPMC_CONFIG1_FCLK_DIV(val) (val 3) -- 1.7.10.2 -- 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 v6 07/13] ARM: OMAP2+: gpmc: register time setting helper
Helper for setting GPMC timing by taking input as register values. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 45 1 file changed, 45 insertions(+) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 8f596ce..1998285 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -1011,6 +1011,51 @@ static void gpmc_setup_cs_config(unsigned cs, unsigned conf) gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l); } +static inline void gpmc_set_one_timing(int cs, int reg, int start, + int end, u32 val) +{ + u32 l; + unsigned mask; + + mask = (1 (end - start + 1)) - 1; + l = gpmc_cs_read_reg(cs, reg); + l = ~(mask start); + l |= val start; + gpmc_cs_write_reg(cs, reg, l); +} + +static void gpmc_cs_set_register_timings(int cs, const struct gpmc_timings *t) +{ + gpmc_set_one_timing(cs, GPMC_CS_CONFIG1, 0, 1, t-sync_clk); + gpmc_set_one_timing(cs, GPMC_CS_CONFIG1, 18, 19, t-wait_monitoring); + gpmc_set_one_timing(cs, GPMC_CS_CONFIG1, 25, 26, t-clk_activation); + + gpmc_set_one_timing(cs, GPMC_CS_CONFIG2, 0, 3, t-cs_on); + gpmc_set_one_timing(cs, GPMC_CS_CONFIG2, 8, 12, t-cs_rd_off); + gpmc_set_one_timing(cs, GPMC_CS_CONFIG2, 16, 20, t-cs_wr_off); + + gpmc_set_one_timing(cs, GPMC_CS_CONFIG3, 0, 3, t-adv_on); + gpmc_set_one_timing(cs, GPMC_CS_CONFIG3, 8, 12, t-adv_rd_off); + gpmc_set_one_timing(cs, GPMC_CS_CONFIG3, 16, 20, t-adv_wr_off); + + gpmc_set_one_timing(cs, GPMC_CS_CONFIG4, 0, 3, t-oe_on); + gpmc_set_one_timing(cs, GPMC_CS_CONFIG4, 8, 12, t-oe_off); + gpmc_set_one_timing(cs, GPMC_CS_CONFIG4, 16, 19, t-we_on); + gpmc_set_one_timing(cs, GPMC_CS_CONFIG4, 24, 28, t-we_off); + + gpmc_set_one_timing(cs, GPMC_CS_CONFIG5, 24, 27, t-page_burst_access); + gpmc_set_one_timing(cs, GPMC_CS_CONFIG6, 0, 3, t-bus_turnaround); + gpmc_set_one_timing(cs, GPMC_CS_CONFIG6, 8, 11, t-cycle2cycle_delay); + + if (gpmc_capability GPMC_HAS_WR_ACCESS) + gpmc_set_one_timing(cs, GPMC_CS_CONFIG6, 24, 28, t-wr_access); + if (gpmc_capability GPMC_HAS_WR_DATA_MUX_BUS) + gpmc_set_one_timing(cs, GPMC_CS_CONFIG6, 16, 19, + t-wr_data_mux_bus); + + gpmc_cs_bool_timings(cs, t-bool_timings); +} + static __devinit int gpmc_setup_cs_irq(struct gpmc_cs_data *cs, struct resource *res) { -- 1.7.10.2 -- 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 v6 08/13] ARM: OMAP2+: gpmc: holler if no configuration
Some of the GPMC peripherals depend on bootloader to do the configuration. This facility is deprecated, notify user about the present GPMC settings inform that that relying on bootloader for GPMC setting is deprecated. Note: This has to be reverted once Kernel is updated with sufficient details so that all the gpmc periherals can be configured in Kernel for all boards instead of relying on bootloader. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 104 1 file changed, 104 insertions(+) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 1998285..9e3960e 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -1056,6 +1056,110 @@ static void gpmc_cs_set_register_timings(int cs, const struct gpmc_timings *t) gpmc_cs_bool_timings(cs, t-bool_timings); } +static void gpmc_print_cs_config(int cs) +{ + u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + + dev_warn(gpmc_dev, GPMC CS%d depends on bootloader for config\n, cs); + dev_warn(gpmc_dev, Please update it in Kernel ASAP to prevent losing support for this peripheral\n); + dev_warn(gpmc_dev, Bootloader dependency for GPMC configuration is deprecated\n); + + dev_warn(gpmc_dev, muxadddata: %s\n, + l GPMC_CONFIG1_MUXADDDATA ? yes : no); + dev_warn(gpmc_dev, writetypesync: %s\n, + l GPMC_CONFIG1_WRITETYPE_SYNC ? yes : no); + dev_warn(gpmc_dev, writemultiple: %s\n, + l GPMC_CONFIG1_WRITEMULTIPLE_SUPP ? yes : no); + dev_warn(gpmc_dev, readtypesync: %s\n, + l GPMC_CONFIG1_READTYPE_SYNC ? yes : no); + dev_warn(gpmc_dev, readmultiple: %s\n, + l GPMC_CONFIG1_READMULTIPLE_SUPP ? yes : no); + dev_warn(gpmc_dev, wrapburst: %s\n, + l GPMC_CONFIG1_WRAPBURST_SUPP ? yes : no); + dev_warn(gpmc_dev, devicetype: %s\n, + l GPMC_CONFIG1_DEVICETYPE_NAND ? nand : nor); + dev_warn(gpmc_dev, devicesize: %d\n, + l GPMC_CONFIG1_DEVICESIZE_16 ? 16 : 8); + dev_warn(gpmc_dev, pagelength: %d\n, + l GPMC_CONFIG1_PAGE_LEN(~0) ? + (l GPMC_CONFIG1_PAGE_LEN_16 ? 16 : 8) : 4); +} +static inline unsigned gpmc_get_one_timing(int cs, int reg, int start, int end) +{ + u32 l = gpmc_cs_read_reg(cs, reg); + unsigned mask; + + mask = (1 (end - start + 1)) - 1; + l = (mask start); + return l = start; +} + +static void gpmc_print_cs_timings(int cs) +{ + dev_warn(gpmc_dev, GPMC CS%d depends on bootloader for timing\n, cs); + dev_warn(gpmc_dev, Please update it in Kernel ASAP to prevent losing support for this peripheral\n); + dev_warn(gpmc_dev, Bootloader dependency for GPMC configuration is deprecated\n); + + dev_warn(gpmc_dev, fclk period: %lups\n, gpmc_get_fclk_period()); + dev_warn(gpmc_dev, sync_clk: %u\n, + gpmc_get_one_timing(cs, GPMC_CS_CONFIG1, 0, 1)); + dev_warn(gpmc_dev, wait_monitoring: %u\n, + gpmc_get_one_timing(cs, GPMC_CS_CONFIG1, 18, 19)); + dev_warn(gpmc_dev, clk_activation: %u\n, + gpmc_get_one_timing(cs, GPMC_CS_CONFIG1, 25, 26)); + dev_warn(gpmc_dev, cs_on: %u\n, + gpmc_get_one_timing(cs, GPMC_CS_CONFIG2, 0, 3)); + dev_warn(gpmc_dev, cs_rd_off: %u\n, + gpmc_get_one_timing(cs, GPMC_CS_CONFIG2, 8, 12)); + dev_warn(gpmc_dev, cs_wr_off: %u\n, + gpmc_get_one_timing(cs, GPMC_CS_CONFIG2, 16, 20)); + dev_warn(gpmc_dev, adv_on: %u\n, + gpmc_get_one_timing(cs, GPMC_CS_CONFIG3, 0, 3)); + dev_warn(gpmc_dev, adv_rd_off: %u\n, + gpmc_get_one_timing(cs, GPMC_CS_CONFIG3, 8, 12)); + dev_warn(gpmc_dev, adv_wr_off: %u\n, + gpmc_get_one_timing(cs, GPMC_CS_CONFIG3, 16, 20)); + dev_warn(gpmc_dev, oe_on: %u\n, + gpmc_get_one_timing(cs, GPMC_CS_CONFIG4, 0, 3)); + dev_warn(gpmc_dev, oe_off: %u\n, + gpmc_get_one_timing(cs, GPMC_CS_CONFIG4, 8, 12)); + dev_warn(gpmc_dev, we_on: %u\n, + gpmc_get_one_timing(cs, GPMC_CS_CONFIG4, 16, 19)); + dev_warn(gpmc_dev, we_off: %u\n, + gpmc_get_one_timing(cs, GPMC_CS_CONFIG4, 24, 28)); + dev_warn(gpmc_dev, rd_cycle: %u\n, + gpmc_get_one_timing(cs, GPMC_CS_CONFIG5, 0, 4)); + dev_warn(gpmc_dev, wr_cycle: %u\n, + gpmc_get_one_timing(cs, GPMC_CS_CONFIG5, 8, 12)); + dev_warn(gpmc_dev, acess: %u\n, + gpmc_get_one_timing(cs, GPMC_CS_CONFIG5, 16, 20)); + dev_warn(gpmc_dev, page_burst_access: %u\n, + gpmc_get_one_timing(cs
[PATCH v6 09/13] ARM: OMAP2+: gpmc: waitpin helper
Helper for configuring waitpin. There are two parts to it; configuring at CS level and the other at device level. A device embedding multiple CS has been provided the capability to use same waitpin (different waitpins has not been supported as presently there are no GPMC peripherals doing so) Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 123 arch/arm/plat-omap/include/plat/gpmc.h |9 +++ 2 files changed, 132 insertions(+) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 9e3960e..15688da 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -75,6 +75,8 @@ #defineGPMC_CONFIG6_CYCLE2CYCLEDIFFCSENBIT(6) #defineGPMC_CONFIG6_CYCLE2CYCLESAMECSENBIT(7) +#defineGPMC_CONFIG_WAITPIN_POLARITY_SHIFT 0x8 + #define GPMC_CS0_OFFSET0x60 #define GPMC_CS_SIZE 0x30 @@ -99,6 +101,14 @@ */ #defineGPMC_NR_IRQ 2 +enum { + GPMC_WAITPIN_IDX0, + GPMC_WAITPIN_IDX1, + GPMC_WAITPIN_IDX2, + GPMC_WAITPIN_IDX3, + GPMC_MAX_NR_WAITPIN +}; + struct gpmc_client_irq { unsignedirq; u32 bitmask; @@ -146,6 +156,9 @@ struct gpmc_peripheral { struct platform_device *pdev; }; +static unsigned gpmc_waitpin_map; +static unsigned gpmc_waitpin_nr = GPMC_MAX_NR_WAITPIN; + static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ]; static struct irq_chip gpmc_irq_chip; static unsigned gpmc_irq_start; @@ -1160,6 +1173,62 @@ static void gpmc_print_cs_timings(int cs) gpmc_get_one_timing(cs, GPMC_CS_CONFIG6, 7, 7)); } +static int gpmc_setup_cs_waitpin(struct gpmc_peripheral *g_per, unsigned cs, + unsigned conf) +{ + unsigned idx; + bool polarity = 0; + u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + + switch (conf GPMC_WAITPIN_MASK) { + case GPMC_WAITPIN_0: + idx = GPMC_WAITPIN_IDX0; + break; + case GPMC_WAITPIN_1: + idx = GPMC_WAITPIN_IDX1; + break; + case GPMC_WAITPIN_2: + idx = GPMC_WAITPIN_IDX2; + break; + case GPMC_WAITPIN_3: + idx = GPMC_WAITPIN_IDX3; + break; + /* no waitpin */ + case 0: + return 0; + break; + default: + dev_err(gpmc_dev, multiple waitpins selected on CS:%u\n, cs); + return -EINVAL; + break; + } + + polarity = !!(conf GPMC_WAITPIN_ACTIVE_HIGH); + + if (g_per-have_waitpin) { + if (g_per-waitpin != idx || + g_per-waitpin_high != polarity) { + dev_err(gpmc_dev, error: conflict: waitpin %u with polarity %d on device %s.%d\n, + g_per-waitpin, g_per-waitpin_high, + g_per-name, g_per-id); + return -EBUSY; + } + } else { + g_per-have_waitpin = true; + g_per-waitpin = idx; + g_per-waitpin_high = polarity; + } + + l |= conf GPMC_CONFIG1_WAIT_WRITE_MON; + l |= conf GPMC_CONFIG1_WAIT_READ_MON; + l = ~GPMC_CONFIG1_WAIT_PIN_SEL_MASK; + l |= GPMC_CONFIG1_WAIT_PIN_SEL(idx); + + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l); + + return 0; +} + static __devinit int gpmc_setup_cs_irq(struct gpmc_cs_data *cs, struct resource *res) { @@ -1183,6 +1252,55 @@ static __devinit int gpmc_setup_cs_irq(struct gpmc_cs_data *cs, return n; } +static inline int gpmc_waitpin_is_reserved(unsigned waitpin) +{ + return gpmc_waitpin_map (0x1 waitpin); +} + +static inline void gpmc_reserve_waitpin(unsigned waitpin) +{ + gpmc_waitpin_map = ~(0x1 waitpin); + gpmc_waitpin_map |= (0x1 waitpin); +} + +static int gpmc_waitpin_request(unsigned waitpin) +{ + if (!(waitpin gpmc_waitpin_nr)) + return -ENODEV; + + if (gpmc_waitpin_is_reserved(waitpin)) + return -EBUSY; + else + gpmc_reserve_waitpin(waitpin); + + return 0; +} + +static int gpmc_setup_waitpin(struct gpmc_peripheral *g_per) +{ + int ret; + u32 l, shift; + + if (!g_per-have_waitpin) + return 0; + + ret = gpmc_waitpin_request(g_per-waitpin); + if (IS_ERR_VALUE(ret)) { + dev_err(gpmc_dev, waitpin %u reserved\n, g_per-waitpin); + return ret; + } + + l = gpmc_read_reg(GPMC_CONFIG); + shift = g_per-waitpin + GPMC_CONFIG_WAITPIN_POLARITY_SHIFT; + if (g_per-waitpin_high) + l |= 1 shift; + else + l = ~(1 shift
[PATCH v6 10/13] 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 | 142 1 file changed, 142 insertions(+) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 15688da..ac66267 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -156,6 +156,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 unsigned gpmc_waitpin_nr = GPMC_MAX_NR_WAITPIN; @@ -1229,6 +1231,37 @@ 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; + } + } else if (cs-time_ctrl.type == has_clock) + gpmc_cs_set_register_timings(cs-cs, cs-time_ctrl.timings); + else + gpmc_print_cs_timings(cs-cs); + + return 0; +} + static __devinit int gpmc_setup_cs_irq(struct gpmc_cs_data *cs, struct resource *res) { @@ -1301,11 +1334,99 @@ 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; + + ret = gpmc_setup_cs_mem(cs, res); + if (IS_ERR_VALUE(ret)) + return ret; + + ret = gpmc_setup_cs_config_timing(g_per, cs); + if (IS_ERR_VALUE(ret)) + return ret; + + num = gpmc_setup_cs_irq(cs, res + 1); /* +1 to account for memory */ + + return num + 1; /* +1 to account for memory*/ +} + +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; + + res = devm_kzalloc(gpmc_dev, sizeof(struct resource) * num, + GFP_KERNEL); + if (!res) { + dev_err(gpmc_dev, error: allocating memory\n
[PATCH v6 11/13] ARM: OMAP2+: gpmc: cs reconfigure helper
Helper for reconfiguring CS. This helps if a peripheral needs to reconfigure GPMC settings different from the one which was configured during probe. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 32 arch/arm/plat-omap/include/plat/gpmc.h |2 ++ 2 files changed, 34 insertions(+) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index ac66267..3729136 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -1420,6 +1420,38 @@ struct platform_device *gpmc_create_device(struct gpmc_peripheral *p) return p-pdev; } +static int gpmc_match_device(char *name, int id) +{ + int i; + struct gpmc_peripheral *g_per = gpmc_peripheral; + + for (i = 0; i gpmc_num_peripheral; i++, g_per++) + if (!strcmp(g_per-name, name) g_per-id == id) + return i; + + return -ENOENT; +} + +int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *c) +{ + int i; + + i = gpmc_match_device(name, id); + if (IS_ERR_VALUE(i)) { + dev_err(gpmc_dev, no device %s.%d to configure\n, name, id); + return i; + } + + if (IS_ERR_VALUE(gpmc_setup_cs_config_timing(gpmc_peripheral + i, c))) { + dev_err(gpmc_dev, error: configure device %s.%d\n, name, id); + return i; + } + + return gpmc_setup_waitpin(gpmc_peripheral + i); + +} +EXPORT_SYMBOL_GPL(gpmc_cs_reconfigure); + static __devinit int gpmc_probe(struct platform_device *pdev) { u32 l; diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 1185490..7909867 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -248,6 +248,8 @@ extern int gpmc_cs_configure(int cs, int cmd, int wval); extern int gpmc_nand_read(int cs, int cmd); extern int gpmc_nand_write(int cs, int cmd, int wval); +extern int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *c); + int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size); int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code); -- 1.7.10.2 -- 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 v6 12/13] ARM: OMAP2+: gpmc: update nand register info
GPMC has dedicated NAND handling blocks and have a few registers exclusively meant for NAND operations. These registers can be handled by OMAP NAND driver as it is meant for handling NAND on GPMC. Update OMAP NAND platform data with GPMC-NAND register details so that OMAP NAND driver can handle by itself instead of relying on GPMC exported symbols. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c |9 - arch/arm/plat-omap/include/plat/gpmc.h |1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 3729136..c8e967f 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -28,6 +28,7 @@ #include asm/mach-types.h #include plat/gpmc.h +#include plat/nand.h #include plat/omap_device.h #include plat/sdrc.h @@ -1497,12 +1498,18 @@ static __devinit int gpmc_probe(struct platform_device *pdev) gpmc_waitpin_nr = gp-waitpin_nr; /* Traverse NULL terminated array of peripheral pointers and setup */ - for (gdq = gp-device_pdata, g_per = gpmc_peripheral; *gdq; gdq++) + for (gdq = gp-device_pdata, g_per = gpmc_peripheral; *gdq; gdq++) { + if ((*gdq)-is_nand) { + struct omap_nand_platform_data *p = (*gdq)-pdata; + + gpmc_update_nand_reg(p-reg, p-cs); + } if (IS_ERR_VALUE(gpmc_setup_device(g_per, *gdq))) dev_err(gpmc_dev, gpmc setup on %s failed\n, (*gdq)-name); else g_per++; + } gpmc_num_peripheral = g_per - gpmc_peripheral; for (l = 0, g_per = gpmc_peripheral; diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 7909867..0085a01 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -196,6 +196,7 @@ struct gpmc_device_pdata { unsignedper_res_cnt; struct gpmc_cs_data *cs_data; unsignednum_cs; + boolis_nand; }; struct gpmc_pdata { -- 1.7.10.2 -- 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 v6 13/13] ARM: OMAP2+: gpmc: configure writeprotect
GPMC has a writeprotect pin that can be connected to peripherals. Default is to disable writeprotect. In case of conflicting requirement of writeprotect, it will be left in enabled state to be on safer side, along with a warning to attract user attention. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 42 arch/arm/plat-omap/include/plat/gpmc.h |2 ++ 2 files changed, 44 insertions(+) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index c8e967f..1b0b526 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -110,6 +110,12 @@ enum { GPMC_MAX_NR_WAITPIN }; +enum { + NONE, + OFF, + ON +}; + struct gpmc_client_irq { unsignedirq; u32 bitmask; @@ -161,6 +167,7 @@ static struct gpmc_peripheral gpmc_peripheral[GPMC_CS_NUM]; static unsigned gpmc_num_peripheral; static unsigned gpmc_waitpin_map; static unsigned gpmc_waitpin_nr = GPMC_MAX_NR_WAITPIN; +static unsigned gpmc_writeprotect; static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ]; static struct irq_chip gpmc_irq_chip; @@ -192,6 +199,18 @@ static u32 gpmc_read_reg(int idx) return __raw_readl(gpmc_base + idx); } +static inline void gpmc_modify_reg(int idx, u32 mask, bool value) +{ + u32 l; + + l = gpmc_read_reg(idx); + if (value) + l |= mask; + else + l = ~mask; + gpmc_write_reg(idx, l); +} + static void gpmc_cs_write_byte(int cs, int idx, u8 val) { void __iomem *reg_addr; @@ -991,6 +1010,7 @@ static __devinit int gpmc_setup_cs_mem(struct gpmc_cs_data *cs, static void gpmc_setup_cs_config(unsigned cs, unsigned conf) { u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + unsigned wp; l = ~(GPMC_CONFIG1_MUXADDDATA | GPMC_CONFIG1_WRITETYPE_SYNC | @@ -1025,6 +1045,19 @@ static void gpmc_setup_cs_config(unsigned cs, unsigned conf) l |= conf; gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l); + + if (conf GPMC_CONFIG_ENABLE_WRITEPROTECT) + wp = ON; + else + wp = OFF; + + if (gpmc_writeprotect) { + if (gpmc_writeprotect != wp) { + dev_warn(gpmc_dev, conflicting writeprotect requests, writeprotect is left enabled\n); + gpmc_writeprotect = ON; + } + } else + gpmc_writeprotect = wp; } static inline void gpmc_set_one_timing(int cs, int reg, int start, @@ -1453,6 +1486,12 @@ int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *c) } EXPORT_SYMBOL_GPL(gpmc_cs_reconfigure); +static inline void gpmc_setup_writeprotect(void) +{ + gpmc_modify_reg(GPMC_CONFIG, GPMC_CONFIG_WRITEPROTECT, + gpmc_writeprotect == ON ? false : true); +} + static __devinit int gpmc_probe(struct platform_device *pdev) { u32 l; @@ -1512,6 +1551,8 @@ static __devinit int gpmc_probe(struct platform_device *pdev) } gpmc_num_peripheral = g_per - gpmc_peripheral; + gpmc_setup_writeprotect(); + for (l = 0, g_per = gpmc_peripheral; l gpmc_num_peripheral; l++, g_per++) if (IS_ERR(gpmc_create_device(g_per))) @@ -1528,6 +1569,7 @@ static __exit int gpmc_remove(struct platform_device *pdev) for (; gpmc_num_peripheral; g_per++, gpmc_num_peripheral--) platform_device_unregister(g_per-pdev); + gpmc_writeprotect = NONE; gpmc_waitpin_map = 0; gpmc_waitpin_nr = GPMC_MAX_NR_WAITPIN; gpmc_free_irq(); diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 0085a01..3de05dc 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -79,6 +79,8 @@ #define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3)) #define GPMC_CONFIG7_CSVALID (1 6) +#defineGPMC_CONFIG_ENABLE_WRITEPROTECT (1 5) + #defineGPMC_WAITPIN_ACTIVE_HIGH(1 4) #defineGPMC_WAITPIN_ACTIVE_LOW (0 4) #defineGPMC_WAITPIN_0 (1 0) -- 1.7.10.2 -- 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 0/3] Prepare for GPMC driver conversion
Hi, Objective of this series is to make things easy for GPMC driver conversion series by separating out more things from driver conversion series. This series, 1. Unifies NAND platform initialization functions 2. Prepares OneNAND platform code for gpmc driver migration 3. Handles additional timings in Kernel This series is based on 3.5-rc1 made on top of [PATCH v2 00/10] Prepare for GPMC driver conversion (w.r.t MTD) {http://www.mail-archive.com/linux-omap@vger.kernel.org/msg70096.html} These changes has been tested with omap3evm beagle board. Relevant GPMC peripherals that got tested by this were NAND (beagle) and OneNAND (using local patches for omap3evm) Regards Afzal v5: 1. Use flags for sync_read/write, hv, vhf v4: 1. Reorganize OneNAND set_sync/async functions in a better way v3: 1. Refactor OneNAND set_sync/async functions to separate out timing and configurations 2. Handle bool type timings too 3. Swap patches 2 3 due to dependency of OneNAND change on newly added bool type timings v2: 1. Make use of timing api for setting clock activation time, and remove direct writing to register for clock activation. Peripherals making use of it were tusb6010 onenand 2. Move ensuring that async mode in OneNAND has been setup from set_sync to setup function, improve commit message Afzal Mohammed (3): ARM: OMAP2+: nand: unify init functions ARM: OMAP2+: gpmc: handle additional timings ARM: OMAP2+: onenand: prepare for gpmc driver migration arch/arm/mach-omap2/board-devkit8000.c |8 +- arch/arm/mach-omap2/board-flash.c | 45 --- arch/arm/mach-omap2/board-flash.h |6 +- arch/arm/mach-omap2/board-igep0020.c |2 +- arch/arm/mach-omap2/board-ldp.c|4 +- arch/arm/mach-omap2/board-omap3beagle.c|8 +- arch/arm/mach-omap2/board-omap3touchbook.c |8 +- arch/arm/mach-omap2/board-overo.c |7 +- arch/arm/mach-omap2/board-zoom.c |5 +- arch/arm/mach-omap2/common-board-devices.c | 46 --- arch/arm/mach-omap2/common-board-devices.h |1 - arch/arm/mach-omap2/gpmc-onenand.c | 200 arch/arm/mach-omap2/gpmc.c | 45 +++ arch/arm/mach-omap2/usb-tusb6010.c |3 +- arch/arm/plat-omap/include/plat/gpmc.h | 19 +++ 15 files changed, 235 insertions(+), 172 deletions(-) -- 1.7.10.2 -- 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 1/3] ARM: OMAP2+: nand: unify init functions
Helper function for updating nand platform data has been added the capability to take timing structure arguement. Usage of omap_nand_flash_init() has been replaced by modifed one, omap_nand_flash_init was doing things similar to board_nand_init except that NAND CS# were being acquired based on bootloader setting. As CS# is hardwired for a given board, acquiring gpmc CS# has been removed, and updated with the value on board. NAND CS# used in beagle board was found to be CS0. Thomas Weber thomas.weber.li...@googlemail.com reported that value of devkit8000 to be CS0. Overo board was found to be using CS0 based on u-boot, while google grep says omap3touchbook too has CS0. Signed-off-by: Afzal Mohammed af...@ti.com Reviewed-by: Jon Hunter jon-hun...@ti.com --- arch/arm/mach-omap2/board-devkit8000.c |8 +++-- arch/arm/mach-omap2/board-flash.c | 45 ++- arch/arm/mach-omap2/board-flash.h |6 ++-- arch/arm/mach-omap2/board-igep0020.c |2 +- arch/arm/mach-omap2/board-ldp.c|4 +-- arch/arm/mach-omap2/board-omap3beagle.c|8 +++-- arch/arm/mach-omap2/board-omap3touchbook.c |8 +++-- arch/arm/mach-omap2/board-overo.c |7 +++-- arch/arm/mach-omap2/board-zoom.c |5 +-- arch/arm/mach-omap2/common-board-devices.c | 46 arch/arm/mach-omap2/common-board-devices.h |1 - 11 files changed, 56 insertions(+), 84 deletions(-) diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 6567c1c..6ee429a 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -59,8 +59,11 @@ #include mux.h #include hsmmc.h +#include board-flash.h #include common-board-devices.h +#defineNAND_CS 0 + #define OMAP_DM9000_GPIO_IRQ 25 #define OMAP3_DEVKIT_TS_GPIO 27 @@ -628,8 +631,9 @@ static void __init devkit8000_init(void) usb_musb_init(NULL); usbhs_init(usbhs_bdata); - omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions, -ARRAY_SIZE(devkit8000_nand_partitions)); + board_nand_init(devkit8000_nand_partitions, + ARRAY_SIZE(devkit8000_nand_partitions), NAND_CS, + NAND_BUSWIDTH_16, NULL); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal(sdrc_cke0, OMAP_PIN_OUTPUT); diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index 70a81f9..0ee820b 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -108,41 +108,41 @@ __init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs) defined(CONFIG_MTD_NAND_OMAP2_MODULE) /* Note that all values in this struct are in nanoseconds */ -static struct gpmc_timings nand_timings = { +struct gpmc_timings nand_default_timings[1] = { + { + .sync_clk = 0, - .sync_clk = 0, + .cs_on = 0, + .cs_rd_off = 36, + .cs_wr_off = 36, - .cs_on = 0, - .cs_rd_off = 36, - .cs_wr_off = 36, + .adv_on = 6, + .adv_rd_off = 24, + .adv_wr_off = 36, - .adv_on = 6, - .adv_rd_off = 24, - .adv_wr_off = 36, + .we_off = 30, + .oe_off = 48, - .we_off = 30, - .oe_off = 48, + .access = 54, + .rd_cycle = 72, + .wr_cycle = 72, - .access = 54, - .rd_cycle = 72, - .wr_cycle = 72, - - .wr_access = 30, - .wr_data_mux_bus = 0, + .wr_access = 30, + .wr_data_mux_bus = 0, + }, }; -static struct omap_nand_platform_data board_nand_data = { - .gpmc_t = nand_timings, -}; +static struct omap_nand_platform_data board_nand_data; void -__init board_nand_init(struct mtd_partition *nand_parts, - u8 nr_parts, u8 cs, int nand_type) +__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs, + int nand_type, struct gpmc_timings *gpmc_t) { board_nand_data.cs = cs; board_nand_data.parts = nand_parts; board_nand_data.nr_parts= nr_parts; board_nand_data.devsize = nand_type; + board_nand_data.gpmc_t = gpmc_t; board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT; board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs; @@ -243,5 +243,6 @@ void __init board_flash_init(struct flash_partitions partition_info[], pr_err(NAND: Unable to find configuration in GPMC\n); else board_nand_init(partition_info[2].parts, - partition_info[2].nr_parts, nandcs, nand_type); + partition_info[2].nr_parts, nandcs
[PATCH v5 2/3] ARM: OMAP2+: gpmc: handle additional timings
Configure busturnaround, cycle2cycledelay, waitmonitoringtime, clkactivationtime in gpmc_cs_set_timings(). This is done so that boards can configure these parameters of gpmc in Kernel instead of relying on bootloader. Also configure bool type timings like extradelay. This needed change to two existing users that were configuring clk activation time by directly writing to registers. Thanks to Tony for making me aware of the issue being kind enough to test this change. Signed-off-by: Afzal Mohammed af...@ti.com --- v3: Handle bool type timings too v2: Make use of timing api for setting clock activation time, and remove direct writing to register for clock activation. Peripherals making use of it were tusb6010 onenand arch/arm/mach-omap2/gpmc-onenand.c |3 ++- arch/arm/mach-omap2/gpmc.c | 45 arch/arm/mach-omap2/usb-tusb6010.c |3 ++- arch/arm/plat-omap/include/plat/gpmc.h | 19 ++ 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 71d7c07..8863e0a 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -329,6 +329,8 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div + ticks_cez); + t.clk_activation = fclk_offset_ns; + /* Write */ if (sync_write) { t.adv_wr_off = t.adv_rd_off; @@ -362,7 +364,6 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) | (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) | (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) | - GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) | GPMC_CONFIG1_PAGE_LEN(2) | (cpu_is_omap34xx() ? 0 : (GPMC_CONFIG1_WAIT_READ_MON | diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 578fd4c..8b0978f 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -64,6 +64,13 @@ #define GPMC_ECC_CTRL_ECCREG8 0x008 #define GPMC_ECC_CTRL_ECCREG9 0x009 +#defineGPMC_CONFIG2_CSEXTRADELAY BIT(7) +#defineGPMC_CONFIG3_ADVEXTRADELAY BIT(7) +#defineGPMC_CONFIG4_OEEXTRADELAY BIT(7) +#defineGPMC_CONFIG4_WEEXTRADELAY BIT(23) +#defineGPMC_CONFIG6_CYCLE2CYCLEDIFFCSENBIT(6) +#defineGPMC_CONFIG6_CYCLE2CYCLESAMECSENBIT(7) + #define GPMC_CS0_OFFSET0x60 #define GPMC_CS_SIZE 0x30 @@ -220,6 +227,36 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns) return ticks * gpmc_get_fclk_period() / 1000; } +static inline void gpmc_cs_modify_reg(int cs, int reg, u32 mask, bool value) +{ + u32 l; + + l = gpmc_cs_read_reg(cs, reg); + if (value) + l |= mask; + else + l = ~mask; + gpmc_cs_write_reg(cs, reg, l); +} + +static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p) +{ + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG1, + GPMC_CONFIG1_TIME_PARA_GRAN, p-time_para_granularity); + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG2, + GPMC_CONFIG2_CSEXTRADELAY, p-cs_extra_delay); + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG3, + GPMC_CONFIG3_ADVEXTRADELAY, p-adv_extra_delay); + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4, + GPMC_CONFIG4_OEEXTRADELAY, p-oe_extra_delay); + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4, + GPMC_CONFIG4_OEEXTRADELAY, p-we_extra_delay); + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6, + GPMC_CONFIG6_CYCLE2CYCLESAMECSEN, p-cycle2cyclesamecsen); + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6, + GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN, p-cycle2cyclediffcsen); +} + #ifdef DEBUG static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, int time, const char *name) @@ -313,6 +350,12 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access); + GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, bus_turnaround); + GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay); + + GPMC_SET_ONE(GPMC_CS_CONFIG1, 18, 19, wait_monitoring); + GPMC_SET_ONE(GPMC_CS_CONFIG1, 25, 26, clk_activation); + if (cpu_is_omap34xx()) { GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus); GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access); @@ -332,6 +375,8 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t
[PATCH v5 3/3] ARM: OMAP2+: onenand: prepare for gpmc driver migration
Reorganize gpmc-onenand initialization so that changes required for gpmc driver migration can be made smooth. Ensuring sync read/write are disabled in onenand cannot be expected to work properly unless GPMC is setup, this has been removed. Refactor set_async_mode set_sync_mode functions to separate out timing calculation actual configuration (GPMC OneNAND side). Thanks to Jon for his suggestions. Signed-off-by: Afzal Mohammed af...@ti.com Reviewed-by: Jon Hunter jon-hun...@ti.com --- v5: Use flags for sync_read/write, hv, vhf v4: Reorganize set_sync/async functions in a better way v3: Refactor set_sync/async functions to separate out timing and configurations v2: Move ensuring that async mode in OneNAND has been setup from set_sync to setup function, improve commit message arch/arm/mach-omap2/gpmc-onenand.c | 197 1 file changed, 111 insertions(+), 86 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 8863e0a..c8a9487 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -15,6 +15,7 @@ #include linux/platform_device.h #include linux/mtd/onenand_regs.h #include linux/io.h +#include linux/err.h #include asm/mach/flash.h @@ -25,6 +26,14 @@ #defineONENAND_IO_SIZE SZ_128K +#defineONENAND_FLAG_SYNCREAD (1 0) +#defineONENAND_FLAG_SYNCWRITE (1 1) +#defineONENAND_FLAG_HF (1 2) +#defineONENAND_FLAG_VHF(1 3) + +static unsigned onenand_flags; +static unsigned latency; + static struct omap_onenand_platform_data *gpmc_onenand_data; static struct resource gpmc_onenand_resource = { @@ -38,11 +47,9 @@ static struct platform_device gpmc_onenand_device = { .resource = gpmc_onenand_resource, }; -static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) +static struct gpmc_timings omap2_onenand_calc_async_timings(void) { struct gpmc_timings t; - u32 reg; - int err; const int t_cer = 15; const int t_avdp = 12; @@ -55,11 +62,6 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) const int t_wpl = 40; const int t_wph = 30; - /* Ensure sync read and sync write are disabled */ - reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); - reg = ~ONENAND_SYS_CFG1_SYNC_READ ~ONENAND_SYS_CFG1_SYNC_WRITE; - writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); - memset(t, 0, sizeof(t)); t.sync_clk = 0; t.cs_on = 0; @@ -86,25 +88,30 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph); t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez); + return t; +} + +static int gpmc_set_async_mode(int cs, struct gpmc_timings *t) +{ /* Configure GPMC for asynchronous read */ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, GPMC_CONFIG1_DEVICESIZE_16 | GPMC_CONFIG1_MUXADDDATA); - err = gpmc_cs_set_timings(cs, t); - if (err) - return err; + return gpmc_cs_set_timings(cs, t); +} + +static void omap2_onenand_set_async_mode(void __iomem *onenand_base) +{ + u32 reg; /* Ensure sync read and sync write are disabled */ reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); reg = ~ONENAND_SYS_CFG1_SYNC_READ ~ONENAND_SYS_CFG1_SYNC_WRITE; writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); - - return 0; } -static void set_onenand_cfg(void __iomem *onenand_base, int latency, - int sync_read, int sync_write, int hf, int vhf) +static void set_onenand_cfg(void __iomem *onenand_base) { u32 reg; @@ -112,19 +119,19 @@ static void set_onenand_cfg(void __iomem *onenand_base, int latency, reg = ~((0x7 ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 9)); reg |= (latency ONENAND_SYS_CFG1_BRL_SHIFT) | ONENAND_SYS_CFG1_BL_16; - if (sync_read) + if (onenand_flags ONENAND_FLAG_SYNCREAD) reg |= ONENAND_SYS_CFG1_SYNC_READ; else reg = ~ONENAND_SYS_CFG1_SYNC_READ; - if (sync_write) + if (onenand_flags ONENAND_FLAG_SYNCWRITE) reg |= ONENAND_SYS_CFG1_SYNC_WRITE; else reg = ~ONENAND_SYS_CFG1_SYNC_WRITE; - if (hf) + if (onenand_flags ONENAND_FLAG_HF) reg |= ONENAND_SYS_CFG1_HF; else reg = ~ONENAND_SYS_CFG1_HF; - if (vhf) + if (onenand_flags ONENAND_FLAG_VHF) reg |= ONENAND_SYS_CFG1_VHF; else reg = ~ONENAND_SYS_CFG1_VHF; @@ -172,9 +179,9 @@ static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg, return freq; } -static int omap2_onenand_set_sync_mode(struct
[PATCH] cpufreq: OMAP: specify range for voltage scaling
Specify voltage in ranges for regulator. Range used is tolerance specified for OPP. This helps to achieve DVFS with a wider range of regulators. Cc: Kevin Hilman khil...@ti.com Cc: Sekhar Nori nsek...@ti.com Signed-off-by: Afzal Mohammed af...@ti.com --- Hi, Tolerance specified here is that of AM335X, least value of tolerance that I could find so far for OMAP family This applies on top of Kevin Hilman's patch (v2), cpufreq: OMAP: scale voltage along with frequency http://www.spinics.net/lists/linux-omap/msg65002.html Regards Afzal drivers/cpufreq/omap-cpufreq.c | 10 +++--- 1 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index 10b8e23..3cea51b 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -38,6 +38,9 @@ #include mach/hardware.h +/* OPP tolerance in percentage */ +#defineOPP_TOLERANCE 4 + #ifdef CONFIG_SMP struct lpj_info { unsigned long ref; @@ -81,7 +84,7 @@ static int omap_target(struct cpufreq_policy *policy, int r, ret = 0; struct cpufreq_freqs freqs; struct opp *opp; - unsigned long freq, volt = 0, volt_old = 0; + unsigned long freq, volt = 0, volt_old = 0, tol = 0; if (!freq_table) { dev_err(mpu_dev, %s: cpu%d: no freq table!\n, __func__, @@ -125,6 +128,7 @@ static int omap_target(struct cpufreq_policy *policy, return -EINVAL; } volt = opp_get_voltage(opp); + tol = volt * OPP_TOLERANCE / 100; volt_old = regulator_get_voltage(mpu_reg); } @@ -134,7 +138,7 @@ static int omap_target(struct cpufreq_policy *policy, /* scaling up? scale voltage before frequency */ if (mpu_reg (freqs.new freqs.old)) { - r = regulator_set_voltage(mpu_reg, volt, volt); + r = regulator_set_voltage(mpu_reg, volt - tol, volt + tol); if (r 0) { dev_warn(mpu_dev, %s: unable to scale voltage up.\n, __func__); @@ -147,7 +151,7 @@ static int omap_target(struct cpufreq_policy *policy, /* scaling down? scale voltage after frequency */ if (mpu_reg (freqs.new freqs.old)) { - r = regulator_set_voltage(mpu_reg, volt, volt); + r = regulator_set_voltage(mpu_reg, volt - tol, volt + tol); if (r 0) { dev_warn(mpu_dev, %s: unable to scale voltage down.\n, __func__); -- 1.7.1 -- 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
[RFC][PATCH 0/5] Convert GPMC to driver
Hi, Convert GPCM code to be a driver. Existing GPMC NAND platform handling has been modified to work with the new GPMC driver (patches 2 3). Patch 5 is to test the driver in OMAP3EVM. Once all the users has been converted to use this driver, would be converted to MFD type. TODO: 1. Let OMAP NAND driver deal with GPMC NAND block 2. Remove struct gpmc * stored as static 3. Convert all peripherals to use GPMC driver 4. Devise method to handle OneNAND cleanly 5. Handle acquiring CS# cases 6. Convert to MFD driver Regards Afzal Afzal Mohammed (5): ARM: OMAP2+: gpmc: driver conversion ARM: OMAP2+: nand: create platform data structure ARM: OMAP2+: gpmc-nand: populate gpmc configs mtd: nand: omap2: obtain memory from resource OMAP3EVM: Test gpmc-nand arch/arm/mach-omap2/board-devkit8000.c |6 +- arch/arm/mach-omap2/board-flash.c | 63 +- arch/arm/mach-omap2/board-flash.h | 13 +- arch/arm/mach-omap2/board-ldp.c|4 +- arch/arm/mach-omap2/board-omap3beagle.c|6 +- arch/arm/mach-omap2/board-omap3evm.c | 82 +++ arch/arm/mach-omap2/board-omap3touchbook.c |6 +- arch/arm/mach-omap2/board-overo.c |5 +- arch/arm/mach-omap2/board-zoom.c |5 +- arch/arm/mach-omap2/common-board-devices.c | 46 -- arch/arm/mach-omap2/common-board-devices.h |1 - arch/arm/mach-omap2/gpmc-nand.c| 88 +-- arch/arm/mach-omap2/gpmc.c | 1083 arch/arm/plat-omap/include/plat/gpmc.h | 34 +- arch/arm/plat-omap/include/plat/nand.h |9 +- drivers/mtd/nand/omap2.c | 19 +- 16 files changed, 869 insertions(+), 601 deletions(-) -- 1.7.9.3 -- 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
[RFC][PATCH 1/5] ARM: OMAP2+: gpmc: driver conversion
Convert GPMC code to driver. Boards using GPMC should provide driver with type of configuration, timing, GPMC address space details (if already configured, driver will retrieve, as is existing). Platform devices would the be created for each connected peripheral (peripheral details also to be passed by board so that it reaches respective driver). And GPMC driver would populate memory resource details for the driver of connected peripheral. A peripheral connected to GPMC can have multiple address spaces using different chip select. Hence GPMC driver has been provided capability to distinguish this scenario, i.e. create platform devices only once for each connected peripheral, and not for each configured chip select. The peripheral that made it necessary was tusb6010. Final destination aimed for this driver is MFD. But before that all existing GPMC users has to be converted to work with this driver. This would likely result in removal of gpmc_create_child and probably use MFD APIs instead. NAND driver for GPMC is tightly coupled with GPMC driver (GPMC has few blocks exclusively for NAND), while that is not the case for most of the other users (they need GPMCs help only for initial configuration). Currently NAND driver manage using exported GPMC symbols. This is being planned to remove later would need informing NAND driver about GPMC NAND registers. This would help to have export symbol free GPMC driver, and probably mv omap2.c gpmc-nand.c for OMAP NAND driver. Thanks to Vaibhav Hiremath for his ideas on this. Acquiring CS# for NAND is done on a few boards. It means, depending on bootloader to embed this information. Probably CS# being used can be set in the Kernel, and acquiring it can be removed. If ever this capbility is needed, GPMC driver has to be made aware of handling it. OneNAND - as it may involve reconfiguring GPMC for synchronous may need a quirk to handle or driver has to be made more intelligent to handle it. Code below comment GPMC CLK related may have to continue live in platform folders (even if the driver is moved to MFD) as input clock is beyond the control of GPMC and calculating timing for the peripheral may need other helpers. TODO (or not?) 1. NAND driver deal with GPMC NAND block 2. Remove struct gpmc * stored as static 3. Convert all peripherals to use GPMC driver 4. Devise method to handle OneNAND cleanly 5. Handle acquiring CS# cases 6. Convert to MFD driver Signed-off-by: Afzal Mohammed af...@ti.com Cc: Vaibhav Hiremath hvaib...@ti.com --- arch/arm/mach-omap2/gpmc.c | 1083 +++- arch/arm/plat-omap/include/plat/gpmc.h | 34 +- 2 files changed, 672 insertions(+), 445 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 00d5108..954fa22 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -14,8 +14,11 @@ */ #undef DEBUG +#include linux/platform_device.h + #include linux/irq.h #include linux/kernel.h +#include linux/slab.h #include linux/init.h #include linux/err.h #include linux/clk.h @@ -64,248 +67,99 @@ #define ENABLE_PREFETCH(0x1 7) #define DMA_MPU_MODE 2 -/* Structure to save gpmc cs context */ -struct gpmc_cs_config { - u32 config1; - u32 config2; - u32 config3; - u32 config4; - u32 config5; - u32 config6; - u32 config7; - int is_valid; -}; - -/* - * Structure to save/restore gpmc context - * to support core off on OMAP3 - */ -struct omap3_gpmc_regs { - u32 sysconfig; - u32 irqenable; - u32 timeout_ctrl; - u32 config; - u32 prefetch_config1; - u32 prefetch_config2; - u32 prefetch_control; - struct gpmc_cs_config cs_context[GPMC_CS_NUM]; -}; - -static struct resource gpmc_mem_root; -static struct resource gpmc_cs_mem[GPMC_CS_NUM]; -static DEFINE_SPINLOCK(gpmc_mem_lock); -static unsigned int gpmc_cs_map; /* flag for cs which are initialized */ -static int gpmc_ecc_used = -EINVAL;/* cs using ecc engine */ - -static void __iomem *gpmc_base; - -static struct clk *gpmc_l3_clk; - -static irqreturn_t gpmc_handle_irq(int irq, void *dev); -static void gpmc_write_reg(int idx, u32 val) -{ - __raw_writel(val, gpmc_base + idx); -} - -static u32 gpmc_read_reg(int idx) -{ - return __raw_readl(gpmc_base + idx); -} - -static void gpmc_cs_write_byte(int cs, int idx, u8 val) -{ - void __iomem *reg_addr; +#defineDRIVER_NAME omap-gpmc - reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx; - __raw_writeb(val, reg_addr); -} +struct gpmc_child { + char*name; + int id; + struct resource *res; + unsignednum_res; + struct resource gpmc_res[GPMC_CS_NUM]; + unsignedgpmc_num_res; + void*pdata; + unsignedpdata_size
[RFC][PATCH 2/5] ARM: OMAP2+: nand: create platform data structure
New API for updating nand platform data. This has been created by unifying the two existing ones and taking out gpmc hardware handling. From now on, platforms can call omap_nand_init to initialize platform nand structures, it's fields. Or can statically create the same. Acquiring gpmc CS has been removed. Acquiring CS probably should be avoided, if ever required, do in GPMC driver. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-devkit8000.c |6 ++- arch/arm/mach-omap2/board-flash.c | 63 ++-- arch/arm/mach-omap2/board-flash.h | 13 -- arch/arm/mach-omap2/board-ldp.c|4 +- arch/arm/mach-omap2/board-omap3beagle.c|6 ++- arch/arm/mach-omap2/board-omap3touchbook.c |6 ++- arch/arm/mach-omap2/board-overo.c |5 ++- arch/arm/mach-omap2/board-zoom.c |5 ++- arch/arm/mach-omap2/common-board-devices.c | 46 arch/arm/mach-omap2/common-board-devices.h |1 - 10 files changed, 61 insertions(+), 94 deletions(-) diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 11cd2a8..1a9ce9d 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -59,6 +59,7 @@ #include mux.h #include hsmmc.h +#include board-flash.h #include common-board-devices.h #define OMAP_DM9000_GPIO_IRQ 25 @@ -648,8 +649,9 @@ static void __init devkit8000_init(void) usb_musb_init(NULL); usbhs_init(usbhs_bdata); - omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions, -ARRAY_SIZE(devkit8000_nand_partitions)); + omap_nand_init(devkit8000_nand_partitions, + ARRAY_SIZE(devkit8000_nand_partitions), GPMC_CS_NUM + 1, + NAND_BUSWIDTH_16, NULL); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal(sdrc_cke0, OMAP_PIN_OUTPUT); diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index 0349fd2..26c70b8 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -108,45 +108,45 @@ __init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs) defined(CONFIG_MTD_NAND_OMAP2_MODULE) /* Note that all values in this struct are in nanoseconds */ -static struct gpmc_timings nand_timings = { +struct gpmc_timings nand_default_timings[1] = { + { + .sync_clk = 0, - .sync_clk = 0, + .cs_on = 0, + .cs_rd_off = 36, + .cs_wr_off = 36, - .cs_on = 0, - .cs_rd_off = 36, - .cs_wr_off = 36, + .adv_on = 6, + .adv_rd_off = 24, + .adv_wr_off = 36, - .adv_on = 6, - .adv_rd_off = 24, - .adv_wr_off = 36, + .we_off = 30, + .oe_off = 48, - .we_off = 30, - .oe_off = 48, + .access = 54, + .rd_cycle = 72, + .wr_cycle = 72, - .access = 54, - .rd_cycle = 72, - .wr_cycle = 72, - - .wr_access = 30, - .wr_data_mux_bus = 0, + .wr_access = 30, + .wr_data_mux_bus = 0, + }, }; -static struct omap_nand_platform_data board_nand_data = { - .gpmc_t = nand_timings, +static struct omap_nand_platform_data omap_nand_data = { + .gpmc_t = nand_default_timings, }; -void -__init board_nand_init(struct mtd_partition *nand_parts, - u8 nr_parts, u8 cs, int nand_type) +struct omap_nand_platform_data * +__init omap_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs, + int nand_type, struct gpmc_timings *gpmc_t) { - board_nand_data.cs = cs; - board_nand_data.parts = nand_parts; - board_nand_data.nr_parts= nr_parts; - board_nand_data.devsize = nand_type; - - board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT; - board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs; - gpmc_nand_init(board_nand_data); + omap_nand_data.cs = cs; + omap_nand_data.parts= nand_parts; + omap_nand_data.nr_parts = nr_parts; + omap_nand_data.devsize = nand_type; + omap_nand_data.gpmc_t = gpmc_t; + + return omap_nand_data; } #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */ @@ -242,6 +242,7 @@ void __init board_flash_init(struct flash_partitions partition_info[], if (nandcs GPMC_CS_NUM) pr_err(NAND: Unable to find configuration in GPMC\n); else - board_nand_init(partition_info[2].parts, - partition_info[2].nr_parts, nandcs, nand_type); + omap_nand_init(partition_info[2].parts
[RFC][PATCH 3/5] ARM: OMAP2+: gpmc-nand: populate gpmc configs
Currently gpmc is configured in platform for nand. As configuring gpmc has been moved to gpmc driver, populate details needed for the driver to configure gpmc. gpmc driver would configure based on this information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc-nand.c| 88 arch/arm/plat-omap/include/plat/nand.h |8 +-- 2 files changed, 39 insertions(+), 57 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index 386dec8..acec0ea 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -21,24 +21,29 @@ #include plat/board.h #include plat/gpmc.h -static struct resource gpmc_nand_resource = { - .flags = IORESOURCE_MEM, + +#defineGPMC_NAND_CONFIG_NUM3 + +static struct gpmc_config gpmc_nand_config[GPMC_NAND_CONFIG_NUM] = { + { GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND}, }; -static struct platform_device gpmc_nand_device = { +static struct gpmc_device_pdata gpmc_nand_info = { .name = omap2-nand, .id = 0, - .num_resources = 1, - .resource = gpmc_nand_resource, + .config = gpmc_nand_config, + .num_config = ARRAY_SIZE(gpmc_nand_config), }; -static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data) -{ - struct gpmc_timings t; - int err; +static struct gpmc_timings t; - if (!gpmc_nand_data-gpmc_t) +static struct gpmc_timings * +gpmc_nand_retime(struct omap_nand_platform_data *gpmc_nand_data) +{ + if (!gpmc_nand_data-gpmc_t) { + pr_warn(gpmc timings not provided\n); return 0; + } memset(t, 0, sizeof(t)); t.sync_clk = gpmc_nand_data-gpmc_t-sync_clk; @@ -68,56 +73,31 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_nand_data-gpmc_t-cs_wr_off); t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data-gpmc_t-wr_cycle); - /* Configure GPMC */ - if (gpmc_nand_data-devsize == NAND_BUSWIDTH_16) - gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_DEV_SIZE, 1); - else - gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_DEV_SIZE, 0); - gpmc_cs_configure(gpmc_nand_data-cs, - GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND); - err = gpmc_cs_set_timings(gpmc_nand_data-cs, t); - if (err) - return err; - - return 0; + return t; } -int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) +struct gpmc_device_pdata * +__init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) { - int err = 0; - struct device *dev = gpmc_nand_device.dev; + gpmc_nand_info.pdata = gpmc_nand_data; + gpmc_nand_info.pdata_size = sizeof(*gpmc_nand_data); - gpmc_nand_device.dev.platform_data = gpmc_nand_data; + gpmc_nand_info.cs = gpmc_nand_data-cs; + gpmc_nand_info.mem_size = NAND_IO_SIZE; - err = gpmc_cs_request(gpmc_nand_data-cs, NAND_IO_SIZE, - gpmc_nand_data-phys_base); - if (err 0) { - dev_err(dev, Cannot request GPMC CS\n); - return err; - } + gpmc_nand_info.timing = gpmc_nand_retime(gpmc_nand_data); -/* Set timings in GPMC */ - err = omap2_nand_gpmc_retime(gpmc_nand_data); - if (err 0) { - dev_err(dev, Unable to set gpmc timings: %d\n, err); - return err; - } - - /* Enable RD PIN Monitoring Reg */ - if (gpmc_nand_data-dev_ready) { - gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_RDY_BSY, 1); - } - - err = platform_device_register(gpmc_nand_device); - if (err 0) { - dev_err(dev, Unable to register NAND device\n); - goto out_free_cs; - } - - return 0; + gpmc_nand_config[1].cmd = GPMC_CONFIG_DEV_SIZE; + if (gpmc_nand_data-devsize == NAND_BUSWIDTH_16) + gpmc_nand_config[1].val = 1; + else + gpmc_nand_config[1].val = 0; -out_free_cs: - gpmc_cs_free(gpmc_nand_data-cs); + gpmc_nand_config[2].cmd = GPMC_CONFIG_RDY_BSY; + if (gpmc_nand_data-dev_ready) + gpmc_nand_config[2].val = 1; + else + gpmc_nand_config[2].val = 0; - return err; + return gpmc_nand_info; } diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h index 67fc506..d2daeba 100644 --- a/arch/arm/plat-omap/include/plat/nand.h +++ b/arch/arm/plat-omap/include/plat/nand.h @@ -35,10 +35,12 @@ struct omap_nand_platform_data { #defineNAND_IO_SIZE4 #if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE) -extern int gpmc_nand_init(struct omap_nand_platform_data
[RFC][PATCH 4/5] mtd: nand: omap2: obtain memory from resource
gpmc being converted to driver, provides drivers of peripheral connected memory space used by the peripheral as memory resource. Modify nand omap driver to obtain memory detials from resource structure. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/plat-omap/include/plat/nand.h |1 - drivers/mtd/nand/omap2.c | 19 +++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h index d2daeba..fa49fc4 100644 --- a/arch/arm/plat-omap/include/plat/nand.h +++ b/arch/arm/plat-omap/include/plat/nand.h @@ -26,7 +26,6 @@ struct omap_nand_platform_data { booldev_ready; int gpmc_irq; enum nand_ioxfer_type; - unsigned long phys_base; int devsize; enum omap_ecc ecc_opt; }; diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index b3a883e..f6c018e 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -118,6 +118,7 @@ struct omap_nand_info { int gpmc_cs; unsigned long phys_base; + unsigned long mem_size; struct completion comp; int dma_ch; int gpmc_irq; @@ -931,6 +932,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) struct omap_nand_platform_data *pdata; int err; int i, offset; + struct resource *res; pdata = pdev-dev.platform_data; if (pdata == NULL) { @@ -950,7 +952,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info-pdev = pdev; info-gpmc_cs = pdata-cs; - info-phys_base = pdata-phys_base; info-mtd.priv = info-nand; info-mtd.name = dev_name(pdev-dev); @@ -962,13 +963,23 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) /* NAND write protect off */ gpmc_cs_configure(info-gpmc_cs, GPMC_CONFIG_WP, 0); - if (!request_mem_region(info-phys_base, NAND_IO_SIZE, + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + err = -EINVAL; + dev_err(pdev-dev, error getting memory resource\n); + goto out_free_info; + } + + info-phys_base = res-start; + info-mem_size = resource_size(res); + + if (!request_mem_region(info-phys_base, info-mem_size, pdev-dev.driver-name)) { err = -EBUSY; goto out_free_info; } - info-nand.IO_ADDR_R = ioremap(info-phys_base, NAND_IO_SIZE); + info-nand.IO_ADDR_R = ioremap(info-phys_base, info-mem_size); if (!info-nand.IO_ADDR_R) { err = -ENOMEM; goto out_release_mem_region; @@ -1109,7 +1120,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) return 0; out_release_mem_region: - release_mem_region(info-phys_base, NAND_IO_SIZE); + release_mem_region(info-phys_base, info-mem_size); out_free_info: kfree(info); -- 1.7.9.3 -- 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
[TMP][PATCH 5/5] OMAP3EVM: Test gpmc-nand
Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-omap3evm.c | 82 ++ 1 file changed, 82 insertions(+) diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index a659e19..9ed48d4 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -23,6 +23,7 @@ #include linux/input/matrix_keypad.h #include linux/leds.h #include linux/interrupt.h +#include linux/mtd/nand.h #include linux/spi/spi.h #include linux/spi/ads7846.h @@ -41,6 +42,7 @@ #include asm/mach/arch.h #include asm/mach/map.h +#include plat/nand.h #include plat/board.h #include plat/usb.h #include common.h @@ -52,6 +54,7 @@ #include sdram-micron-mt46h32m32lf-6.h #include hsmmc.h #include common-board-devices.h +#include board-flash.h #define OMAP3_EVM_TS_GPIO 175 #define OMAP3_EVM_EHCI_VBUS22 @@ -102,6 +105,9 @@ static void __init omap3_evm_get_revision(void) } } +#undef CONFIG_SMSC911X +#undef CONFIG_SMSC911X_MODULE + #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) #include plat/gpmc-smsc911x.h @@ -533,6 +539,41 @@ static struct usbhs_omap_board_data usbhs_bdata __initdata = { .reset_gpio_port[2] = -EINVAL }; +/* + * NAND + */ +static struct mtd_partition omap3_evm_nand_partitions[] = { + /* All the partition sizes are listed in terms of NAND block size */ + { + .name = X-Loader-NAND, + .offset = 0, + .size = 4 * (64 * 2048), + .mask_flags = MTD_WRITEABLE,/* force read-only */ + }, + { + .name = U-Boot-NAND, + .offset = MTDPART_OFS_APPEND, /* Offset = 0x8 */ + .size = 10 * (64 * 2048), + .mask_flags = MTD_WRITEABLE,/* force read-only */ + }, + { + .name = Boot Env-NAND, + + .offset = MTDPART_OFS_APPEND, /* Offset = 0x1c */ + .size = 6 * (64 * 2048), + }, + { + .name = Kernel-NAND, + .offset = MTDPART_OFS_APPEND, /* Offset = 0x28 */ + .size = 40 * (64 * 2048), + }, + { + .name = File System - NAND, + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, /* Offset = 0x78 */ + }, +}; + #ifdef CONFIG_OMAP_MUX static struct omap_board_mux omap35x_board_mux[] __initdata = { OMAP3_MUX(SYS_NIRQ, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP | @@ -632,8 +673,30 @@ static void __init omap3_evm_wl12xx_init(void) #endif } +static struct gpmc_pdata gpmc_data; + +static struct resource gpmc_resources[] = { + { + .start = OMAP34XX_GPMC_BASE, + .end = OMAP34XX_GPMC_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device gpmc_device = { + .name = omap-gpmc, + .id = -1, + .num_resources = ARRAY_SIZE(gpmc_resources), + .resource = gpmc_resources, + .dev= { + .platform_data = gpmc_data, + } +}; + static void __init omap3_evm_init(void) { + struct omap_nand_platform_data *nand_data; + omap3_evm_get_revision(); if (cpu_is_omap3630()) @@ -684,6 +747,25 @@ static void __init omap3_evm_init(void) omap3evm_init_smsc911x(); omap3_evm_display_init(); omap3_evm_wl12xx_init(); + /* NAND */ + nand_data = omap_nand_init(omap3_evm_nand_partitions, + ARRAY_SIZE(omap3_evm_nand_partitions), + 0, NAND_BUSWIDTH_16, nand_default_timings); + if (nand_data == NULL) { + pr_err(omap_nand_init() failed\n); + return; + } + + gpmc_data.device_pdata = gpmc_nand_init(nand_data); + if (gpmc_data.device_pdata == NULL) { + pr_err(gpmc_nand_init() failed\n); + return; + } + + gpmc_data.num_device++; + gpmc_data.fclk_rate = gpmc_get_fclk_period(); + + platform_device_register(gpmc_device); } MACHINE_START(OMAP3EVM, OMAP3 EVM) -- 1.7.9.3 -- 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
[RFC][PATCH v2 0/5] Convert GPMC to driver
Hi, Convert GPCM code to be a driver. Existing GPMC NAND platform handling has been modified to work with the new GPMC driver (patches 2 3). Patch 5 is to test the driver in OMAP3EVM. TODO 1. Let NAND driver deal with GPMC NAND block 2. Remove struct gpmc * stored as static 3. Convert all peripherals to use GPMC driver 4. Devise method to handle OneNAND cleanly 5. Handle acquiring CS# cases 6. Decide on where GPMC driver should live 7. Adapt to HWMOD, use RPM 8. GPMC driver cleanup Regards Afzal Afzal Mohammed (5): ARM: OMAP2+: gpmc: driver conversion ARM: OMAP2+: nand: create platform data structure ARM: OMAP2+: gpmc-nand: populate gpmc configs mtd: nand: omap2: obtain memory from resource OMAP3EVM: Test gpmc-nand v2: Avoid code movement that kept similar code together (for easy review) arch/arm/mach-omap2/board-devkit8000.c |6 +- arch/arm/mach-omap2/board-flash.c | 63 ++--- arch/arm/mach-omap2/board-flash.h | 13 +- arch/arm/mach-omap2/board-ldp.c|4 +- arch/arm/mach-omap2/board-omap3beagle.c|6 +- arch/arm/mach-omap2/board-omap3evm.c | 82 +++ arch/arm/mach-omap2/board-omap3touchbook.c |6 +- arch/arm/mach-omap2/board-overo.c |5 +- arch/arm/mach-omap2/board-zoom.c |5 +- arch/arm/mach-omap2/common-board-devices.c | 46 arch/arm/mach-omap2/common-board-devices.h |1 - arch/arm/mach-omap2/gpmc-nand.c| 88 +++ arch/arm/mach-omap2/gpmc.c | 366 +--- arch/arm/plat-omap/include/plat/gpmc.h | 34 ++- arch/arm/plat-omap/include/plat/nand.h |9 +- drivers/mtd/nand/omap2.c | 19 +- 16 files changed, 502 insertions(+), 251 deletions(-) -- 1.7.9.3 -- 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
[RFC][PATCH v2 1/5] ARM: OMAP2+: gpmc: driver conversion
Convert GPMC code to driver. Boards using GPMC should provide driver with type of configuration, timing, CS, GPMC address space details (if already configured, driver will retrieve, as is existing). Platform devices would the be created for each connected peripheral (details also to be passed by board so that it reaches respective driver). And GPMC driver would populate memory resource details for the driver of connected peripheral. A peripheral connected to GPMC can have multiple address spaces using different chip select. Hence GPMC driver has been provided capability to distinguish this scenario, i.e. create platform devices only once for each connected peripheral, and not for each configured chip select. The peripheral that made it necessary was tusb6010. Final destination for this driver is being investigated. Before moving to the new location, all existing GPMC users has to be converted to work with this driver. NAND driver for NAND used via GPMC is tightly coupled with GPMC driver (GPMC has few blocks exclusively for NAND), while that is not the case for most of the other users (they need GPMCs help only for initial configuration). Currently NAND driver manage using exported GPMC symbols. This is being planned to remove later would need informing NAND driver about GPMC NAND registers. This would help to have export symbol free GPMC driver, and probably mv omap2.c gpmc-nand.c for OMAP NAND driver. Thanks to Vaibhav Hiremath for his ideas on this. Acquiring CS# for NAND is done on a few boards. It means, depending on bootloader to embed this information. Probably CS# being used can be set in the Kernel, and acquiring it can be removed. If ever this capbility is needed, GPMC driver has to be made aware of handling it. OneNAND - as it may involve reconfiguring GPMC for synchronous may need a quirk to handle or driver has to be made more intelligent to handle it. Code related to GPMC clock may have to continue live in platform folders (even if the driver is moved to MFD) as input clock is beyond the control of GPMC and calculating timing for the peripheral may need other helpers. TODO 1. Let NAND driver deal with GPMC NAND block 2. Remove struct gpmc * stored as static 3. Convert all peripherals to use GPMC driver 4. Devise method to handle OneNAND cleanly 5. Handle acquiring CS# cases 6. Decide on where GPMC driver should live 7. Adapt to HWMOD, use RPM 8. GPMC driver cleanup Cc: Vaibhav Hiremath hvaib...@ti.com Signed-off-by: Afzal Mohammed af...@ti.com --- v2: Avoid code movement that kept similar code together arch/arm/mach-omap2/gpmc.c | 366 arch/arm/plat-omap/include/plat/gpmc.h | 34 ++- 2 files changed, 305 insertions(+), 95 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 00d5108..8556153 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -14,8 +14,11 @@ */ #undef DEBUG +#include linux/platform_device.h + #include linux/irq.h #include linux/kernel.h +#include linux/slab.h #include linux/init.h #include linux/err.h #include linux/clk.h @@ -64,6 +67,35 @@ #define ENABLE_PREFETCH(0x1 7) #define DMA_MPU_MODE 2 +#defineDRIVER_NAME omap-gpmc + +struct gpmc_child { + char*name; + int id; + struct resource *res; + unsignednum_res; + struct resource gpmc_res[GPMC_CS_NUM]; + unsignedgpmc_num_res; + void*pdata; + unsignedpdata_size; +}; + +struct gpmc { + struct device *dev; + unsigned long fclk_period; + void __iomem*io_base; + unsigned long phys_base; + u32 memsize; + unsignedcs_map; + int ecc_used; + spinlock_t mem_lock; + struct resource mem_root; + struct resource cs_mem[GPMC_CS_NUM]; + struct gpmc_child child_device[GPMC_CS_NUM]; + unsignednum_child; + unsignednum_device; +}; + /* Structure to save gpmc cs context */ struct gpmc_cs_config { u32 config1; @@ -91,58 +123,50 @@ struct omap3_gpmc_regs { struct gpmc_cs_config cs_context[GPMC_CS_NUM]; }; -static struct resource gpmc_mem_root; -static struct resource gpmc_cs_mem[GPMC_CS_NUM]; -static DEFINE_SPINLOCK(gpmc_mem_lock); -static unsigned int gpmc_cs_map; /* flag for cs which are initialized */ -static int gpmc_ecc_used = -EINVAL;/* cs using ecc engine */ - -static void __iomem *gpmc_base; - static struct clk *gpmc_l3_clk; -static irqreturn_t gpmc_handle_irq(int irq, void *dev); +static struct gpmc *gpmc; static void gpmc_write_reg(int idx, u32 val) { - __raw_writel(val, gpmc_base + idx); + writel(val, gpmc-io_base
[RFC][PATCH v2 2/5] ARM: OMAP2+: nand: create platform data structure
New API for updating nand platform data. This has been created by unifying the two existing ones and taking out gpmc hardware handling. From now on, platforms can call omap_nand_init to initialize platform nand structures, it's fields. Or can statically create the same. Acquiring gpmc CS has been removed. Acquiring CS probably should be avoided, if ever required, do in GPMC driver. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-devkit8000.c |6 ++- arch/arm/mach-omap2/board-flash.c | 63 ++-- arch/arm/mach-omap2/board-flash.h | 13 -- arch/arm/mach-omap2/board-ldp.c|4 +- arch/arm/mach-omap2/board-omap3beagle.c|6 ++- arch/arm/mach-omap2/board-omap3touchbook.c |6 ++- arch/arm/mach-omap2/board-overo.c |5 ++- arch/arm/mach-omap2/board-zoom.c |5 ++- arch/arm/mach-omap2/common-board-devices.c | 46 arch/arm/mach-omap2/common-board-devices.h |1 - 10 files changed, 61 insertions(+), 94 deletions(-) diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 11cd2a8..1a9ce9d 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -59,6 +59,7 @@ #include mux.h #include hsmmc.h +#include board-flash.h #include common-board-devices.h #define OMAP_DM9000_GPIO_IRQ 25 @@ -648,8 +649,9 @@ static void __init devkit8000_init(void) usb_musb_init(NULL); usbhs_init(usbhs_bdata); - omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions, -ARRAY_SIZE(devkit8000_nand_partitions)); + omap_nand_init(devkit8000_nand_partitions, + ARRAY_SIZE(devkit8000_nand_partitions), GPMC_CS_NUM + 1, + NAND_BUSWIDTH_16, NULL); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal(sdrc_cke0, OMAP_PIN_OUTPUT); diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index 0349fd2..26c70b8 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -108,45 +108,45 @@ __init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs) defined(CONFIG_MTD_NAND_OMAP2_MODULE) /* Note that all values in this struct are in nanoseconds */ -static struct gpmc_timings nand_timings = { +struct gpmc_timings nand_default_timings[1] = { + { + .sync_clk = 0, - .sync_clk = 0, + .cs_on = 0, + .cs_rd_off = 36, + .cs_wr_off = 36, - .cs_on = 0, - .cs_rd_off = 36, - .cs_wr_off = 36, + .adv_on = 6, + .adv_rd_off = 24, + .adv_wr_off = 36, - .adv_on = 6, - .adv_rd_off = 24, - .adv_wr_off = 36, + .we_off = 30, + .oe_off = 48, - .we_off = 30, - .oe_off = 48, + .access = 54, + .rd_cycle = 72, + .wr_cycle = 72, - .access = 54, - .rd_cycle = 72, - .wr_cycle = 72, - - .wr_access = 30, - .wr_data_mux_bus = 0, + .wr_access = 30, + .wr_data_mux_bus = 0, + }, }; -static struct omap_nand_platform_data board_nand_data = { - .gpmc_t = nand_timings, +static struct omap_nand_platform_data omap_nand_data = { + .gpmc_t = nand_default_timings, }; -void -__init board_nand_init(struct mtd_partition *nand_parts, - u8 nr_parts, u8 cs, int nand_type) +struct omap_nand_platform_data * +__init omap_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs, + int nand_type, struct gpmc_timings *gpmc_t) { - board_nand_data.cs = cs; - board_nand_data.parts = nand_parts; - board_nand_data.nr_parts= nr_parts; - board_nand_data.devsize = nand_type; - - board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT; - board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs; - gpmc_nand_init(board_nand_data); + omap_nand_data.cs = cs; + omap_nand_data.parts= nand_parts; + omap_nand_data.nr_parts = nr_parts; + omap_nand_data.devsize = nand_type; + omap_nand_data.gpmc_t = gpmc_t; + + return omap_nand_data; } #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */ @@ -242,6 +242,7 @@ void __init board_flash_init(struct flash_partitions partition_info[], if (nandcs GPMC_CS_NUM) pr_err(NAND: Unable to find configuration in GPMC\n); else - board_nand_init(partition_info[2].parts, - partition_info[2].nr_parts, nandcs, nand_type); + omap_nand_init(partition_info[2].parts
[RFC][PATCH v2 3/5] ARM: OMAP2+: gpmc-nand: populate gpmc configs
Currently gpmc is configured in platform for nand. As configuring gpmc has been moved to gpmc driver, populate details needed for the driver to configure gpmc. gpmc driver would configure based on this information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc-nand.c| 88 arch/arm/plat-omap/include/plat/nand.h |8 +-- 2 files changed, 39 insertions(+), 57 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index 386dec8..acec0ea 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -21,24 +21,29 @@ #include plat/board.h #include plat/gpmc.h -static struct resource gpmc_nand_resource = { - .flags = IORESOURCE_MEM, + +#defineGPMC_NAND_CONFIG_NUM3 + +static struct gpmc_config gpmc_nand_config[GPMC_NAND_CONFIG_NUM] = { + { GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND}, }; -static struct platform_device gpmc_nand_device = { +static struct gpmc_device_pdata gpmc_nand_info = { .name = omap2-nand, .id = 0, - .num_resources = 1, - .resource = gpmc_nand_resource, + .config = gpmc_nand_config, + .num_config = ARRAY_SIZE(gpmc_nand_config), }; -static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data) -{ - struct gpmc_timings t; - int err; +static struct gpmc_timings t; - if (!gpmc_nand_data-gpmc_t) +static struct gpmc_timings * +gpmc_nand_retime(struct omap_nand_platform_data *gpmc_nand_data) +{ + if (!gpmc_nand_data-gpmc_t) { + pr_warn(gpmc timings not provided\n); return 0; + } memset(t, 0, sizeof(t)); t.sync_clk = gpmc_nand_data-gpmc_t-sync_clk; @@ -68,56 +73,31 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_nand_data-gpmc_t-cs_wr_off); t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data-gpmc_t-wr_cycle); - /* Configure GPMC */ - if (gpmc_nand_data-devsize == NAND_BUSWIDTH_16) - gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_DEV_SIZE, 1); - else - gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_DEV_SIZE, 0); - gpmc_cs_configure(gpmc_nand_data-cs, - GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND); - err = gpmc_cs_set_timings(gpmc_nand_data-cs, t); - if (err) - return err; - - return 0; + return t; } -int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) +struct gpmc_device_pdata * +__init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) { - int err = 0; - struct device *dev = gpmc_nand_device.dev; + gpmc_nand_info.pdata = gpmc_nand_data; + gpmc_nand_info.pdata_size = sizeof(*gpmc_nand_data); - gpmc_nand_device.dev.platform_data = gpmc_nand_data; + gpmc_nand_info.cs = gpmc_nand_data-cs; + gpmc_nand_info.mem_size = NAND_IO_SIZE; - err = gpmc_cs_request(gpmc_nand_data-cs, NAND_IO_SIZE, - gpmc_nand_data-phys_base); - if (err 0) { - dev_err(dev, Cannot request GPMC CS\n); - return err; - } + gpmc_nand_info.timing = gpmc_nand_retime(gpmc_nand_data); -/* Set timings in GPMC */ - err = omap2_nand_gpmc_retime(gpmc_nand_data); - if (err 0) { - dev_err(dev, Unable to set gpmc timings: %d\n, err); - return err; - } - - /* Enable RD PIN Monitoring Reg */ - if (gpmc_nand_data-dev_ready) { - gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_RDY_BSY, 1); - } - - err = platform_device_register(gpmc_nand_device); - if (err 0) { - dev_err(dev, Unable to register NAND device\n); - goto out_free_cs; - } - - return 0; + gpmc_nand_config[1].cmd = GPMC_CONFIG_DEV_SIZE; + if (gpmc_nand_data-devsize == NAND_BUSWIDTH_16) + gpmc_nand_config[1].val = 1; + else + gpmc_nand_config[1].val = 0; -out_free_cs: - gpmc_cs_free(gpmc_nand_data-cs); + gpmc_nand_config[2].cmd = GPMC_CONFIG_RDY_BSY; + if (gpmc_nand_data-dev_ready) + gpmc_nand_config[2].val = 1; + else + gpmc_nand_config[2].val = 0; - return err; + return gpmc_nand_info; } diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h index 67fc506..d2daeba 100644 --- a/arch/arm/plat-omap/include/plat/nand.h +++ b/arch/arm/plat-omap/include/plat/nand.h @@ -35,10 +35,12 @@ struct omap_nand_platform_data { #defineNAND_IO_SIZE4 #if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE) -extern int gpmc_nand_init(struct omap_nand_platform_data
[RFC][PATCH v2 4/5] mtd: nand: omap2: obtain memory from resource
gpmc being converted to driver, provides drivers of peripheral connected memory space used by the peripheral as memory resource. Modify nand omap driver to obtain memory detials from resource structure. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/plat-omap/include/plat/nand.h |1 - drivers/mtd/nand/omap2.c | 19 +++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h index d2daeba..fa49fc4 100644 --- a/arch/arm/plat-omap/include/plat/nand.h +++ b/arch/arm/plat-omap/include/plat/nand.h @@ -26,7 +26,6 @@ struct omap_nand_platform_data { booldev_ready; int gpmc_irq; enum nand_ioxfer_type; - unsigned long phys_base; int devsize; enum omap_ecc ecc_opt; }; diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index b3a883e..f6c018e 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -118,6 +118,7 @@ struct omap_nand_info { int gpmc_cs; unsigned long phys_base; + unsigned long mem_size; struct completion comp; int dma_ch; int gpmc_irq; @@ -931,6 +932,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) struct omap_nand_platform_data *pdata; int err; int i, offset; + struct resource *res; pdata = pdev-dev.platform_data; if (pdata == NULL) { @@ -950,7 +952,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info-pdev = pdev; info-gpmc_cs = pdata-cs; - info-phys_base = pdata-phys_base; info-mtd.priv = info-nand; info-mtd.name = dev_name(pdev-dev); @@ -962,13 +963,23 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) /* NAND write protect off */ gpmc_cs_configure(info-gpmc_cs, GPMC_CONFIG_WP, 0); - if (!request_mem_region(info-phys_base, NAND_IO_SIZE, + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + err = -EINVAL; + dev_err(pdev-dev, error getting memory resource\n); + goto out_free_info; + } + + info-phys_base = res-start; + info-mem_size = resource_size(res); + + if (!request_mem_region(info-phys_base, info-mem_size, pdev-dev.driver-name)) { err = -EBUSY; goto out_free_info; } - info-nand.IO_ADDR_R = ioremap(info-phys_base, NAND_IO_SIZE); + info-nand.IO_ADDR_R = ioremap(info-phys_base, info-mem_size); if (!info-nand.IO_ADDR_R) { err = -ENOMEM; goto out_release_mem_region; @@ -1109,7 +1120,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) return 0; out_release_mem_region: - release_mem_region(info-phys_base, NAND_IO_SIZE); + release_mem_region(info-phys_base, info-mem_size); out_free_info: kfree(info); -- 1.7.9.3 -- 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
[TMP][PATCH v2 5/5] OMAP3EVM: Test gpmc-nand
Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-omap3evm.c | 82 ++ 1 file changed, 82 insertions(+) diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index a659e19..2695663 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -23,6 +23,7 @@ #include linux/input/matrix_keypad.h #include linux/leds.h #include linux/interrupt.h +#include linux/mtd/nand.h #include linux/spi/spi.h #include linux/spi/ads7846.h @@ -41,6 +42,7 @@ #include asm/mach/arch.h #include asm/mach/map.h +#include plat/nand.h #include plat/board.h #include plat/usb.h #include common.h @@ -52,6 +54,7 @@ #include sdram-micron-mt46h32m32lf-6.h #include hsmmc.h #include common-board-devices.h +#include board-flash.h #define OMAP3_EVM_TS_GPIO 175 #define OMAP3_EVM_EHCI_VBUS22 @@ -102,6 +105,9 @@ static void __init omap3_evm_get_revision(void) } } +#undef CONFIG_SMSC911X +#undef CONFIG_SMSC911X_MODULE + #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) #include plat/gpmc-smsc911x.h @@ -533,6 +539,41 @@ static struct usbhs_omap_board_data usbhs_bdata __initdata = { .reset_gpio_port[2] = -EINVAL }; +/* + * NAND + */ +static struct mtd_partition omap3_evm_nand_partitions[] = { + /* All the partition sizes are listed in terms of NAND block size */ + { + .name = X-Loader-NAND, + .offset = 0, + .size = 4 * (64 * 2048), + .mask_flags = MTD_WRITEABLE,/* force read-only */ + }, + { + .name = U-Boot-NAND, + .offset = MTDPART_OFS_APPEND, /* Offset = 0x8 */ + .size = 10 * (64 * 2048), + .mask_flags = MTD_WRITEABLE,/* force read-only */ + }, + { + .name = Boot Env-NAND, + + .offset = MTDPART_OFS_APPEND, /* Offset = 0x1c */ + .size = 6 * (64 * 2048), + }, + { + .name = Kernel-NAND, + .offset = MTDPART_OFS_APPEND, /* Offset = 0x28 */ + .size = 40 * (64 * 2048), + }, + { + .name = File System - NAND, + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, /* Offset = 0x78 */ + }, +}; + #ifdef CONFIG_OMAP_MUX static struct omap_board_mux omap35x_board_mux[] __initdata = { OMAP3_MUX(SYS_NIRQ, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP | @@ -632,8 +673,30 @@ static void __init omap3_evm_wl12xx_init(void) #endif } +static struct gpmc_pdata gpmc_data; + +static struct resource gpmc_resources[] = { + { + .start = OMAP34XX_GPMC_BASE, + .end = OMAP34XX_GPMC_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device gpmc_device = { + .name = omap-gpmc, + .id = -1, + .num_resources = ARRAY_SIZE(gpmc_resources), + .resource = gpmc_resources, + .dev= { + .platform_data = gpmc_data, + } +}; + static void __init omap3_evm_init(void) { + struct omap_nand_platform_data *nand_data; + omap3_evm_get_revision(); if (cpu_is_omap3630()) @@ -684,6 +747,25 @@ static void __init omap3_evm_init(void) omap3evm_init_smsc911x(); omap3_evm_display_init(); omap3_evm_wl12xx_init(); + /* NAND */ + nand_data = omap_nand_init(omap3_evm_nand_partitions, + ARRAY_SIZE(omap3_evm_nand_partitions), + 0, NAND_BUSWIDTH_16, nand_default_timings); + if (nand_data == NULL) { + pr_err(omap_nand_init() failed\n); + return; + } + + gpmc_data.device_pdata = gpmc_nand_init(nand_data); + if (gpmc_data.device_pdata == NULL) { + pr_err(gpmc_nand_init() failed\n); + return; + } + + gpmc_data.num_device++; + gpmc_data.fclk_period = gpmc_get_fclk_period(); + + platform_device_register(gpmc_device); } MACHINE_START(OMAP3EVM, OMAP3 EVM) -- 1.7.9.3 -- 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 v3 0/9] Convert OMAP GPMC to driver
Hi, GPMC driver conversion series. NAND and smsc911x ethernet device has been adapted to use GPMC driver. Patches has been generated over linux-omap/master, HEAD 33fc21e Linux-omap rebuilt: Updated to v3.4-rc1, merged in most of pending branches As OMAP3EVM does not boot linux-omap/master, merge commit, 58adb29 Merge branch 'io_chain_devel_3.4' of git://git.pwsan.com/linux-2.6 into prm has to be reverted to get OMAP3EVM boot. Last patch (with subject prefix TMP - 9/9) is for testing. Once driver is acceptable, platform code for other peripherals connected via GPMC would be adapted to make use of GPMC driver. And then the board modifications. But before that HWMOD entry has to be populated for respective SoC(s ?). Now DESTINATION FOR THIS DRIVER has to be decided. Original plan was to consider GPMC as MFD. The peripheral(s) connected to GPMC being considered childs of MFD. GPMC (General Purpose Memory Controller) in brief: GPMC is an unified memory controller dedicated to interfacing external memory devices like Asynchronous SRAM like memories and application specific integrated circuit devices. Asynchronous, synchronous, and page mode burst NOR flash devices NAND flash Pseudo-SRAM devices GPMC has to be configured as required by timings of the connected peripheral. It needs to be configured only initially (only exception being resume afaik, where it needs to be reconfigured). Handling GPMC cannot be left to platform code to handle, then where can it be ? (currently it is handled by platform code). Once it is configured it can be used to handle different protocols like NAND, NOR. Various kinds of devices like ethernet, uart, usb, fpga etc can work using GPMC interface. GPMC has a seperate additional functionality of NAND handling (not manhandling ;) ). But with this series, dealing NAND block of GPMC has been separated from GPMC driver and given to NAND driver. It seems decision on where a driver should go is based more on functionality. Any suggestions on where GPMC driver could go would be very helpful. This would also help in reducing amount of platform code for OMAP. Various options that could be seen so far on where this driver can go, 1. mfd 2. misc 3. drivers/platform/arm/ (create an new one?) 4. memory (create a new one ?) If GPMC sounds similar to something else that is present in other chips, please be kind enough to let me know how this is handled by Kernel (if). GPMC details can be referred in AM335X Technical Reference Manual @ http://www.ti.com/lit/pdf/spruh73 Regards Afzal v3: Single device structure passed from platform for peripherals using multiple CS instead of using multiple device structure having a few redundant data, handle interrupts, GPMC NAND handling by GPMC NAND driver instead of GPMC driver v2: Avoid code movement that kept similar code together (for easy review) TODO: 1. Decide on destination of GPMC driver 2. Modify platform code so that remaining peripherals can be configured using GPMC driver instead of platform code doing so. 3. Remove static struct gpmc * (could be done once all other peripherals are adapted to use GPMC driver) 4. Devise method to handle OneNAND for GPMC cleanly 5. Handle acquiring CS# (if required) 6. Adapt to HWMOD, use RPM 7. Cleanup (once all peripherals make use of GPMC driver all the exported symbols can be removed, and complete removal of a few of these functions would be possible, like gpmc_nand_* can be deleted now itself) Afzal Mohammed (9): ARM: OMAP2+: gpmc: driver conversion ARM: OMAP2+: gpmc: registers for nand driver ARM: OMAP2+: nand: create platform data structure ARM: OMAP2+: gpmc-nand: populate gpmc configs ARM: OMAP2+: gpmc-smsc911x: gpmc driver information mtd: nand: omap2: obtain memory from resource mtd: nand: omap2: use gpmc provided irqs mtd: nand: omap2: handle nand on gpmc OMAP3EVM: Test gpmc-nand arch/arm/mach-omap2/board-devkit8000.c |6 +- arch/arm/mach-omap2/board-flash.c | 63 +-- arch/arm/mach-omap2/board-flash.h | 13 +- arch/arm/mach-omap2/board-ldp.c |4 +- arch/arm/mach-omap2/board-omap3beagle.c |6 +- arch/arm/mach-omap2/board-omap3evm.c| 95 +++- arch/arm/mach-omap2/board-omap3touchbook.c |6 +- arch/arm/mach-omap2/board-overo.c |5 +- arch/arm/mach-omap2/board-zoom.c|5 +- arch/arm/mach-omap2/common-board-devices.c | 46 -- arch/arm/mach-omap2/common-board-devices.h |1 - arch/arm/mach-omap2/gpmc-nand.c | 97 ++-- arch/arm/mach-omap2/gpmc-smsc911x.c | 59 +-- arch/arm/mach-omap2/gpmc.c | 543 +++ arch/arm/plat-omap/include/plat/gpmc-smsc911x.h |9 +- arch/arm/plat-omap/include/plat/gpmc.h | 66 ++- arch/arm/plat-omap/include/plat/nand.h | 10 +- drivers/mtd/nand/omap2.c
[PATCH v3 2/9] ARM: OMAP2+: gpmc: registers for nand driver
If peripheral connected is NAND, update NAND drivers platform data with NAND related register addresses so that NAND driver can handle GPMC NAND operations by itself Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 25 + arch/arm/plat-omap/include/plat/gpmc.h | 16 arch/arm/plat-omap/include/plat/nand.h |1 + 3 files changed, 42 insertions(+) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index cf5d8f3..ca7fa83 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -30,6 +30,7 @@ #include asm/mach-types.h #include plat/gpmc.h +#include plat/nand.h #include plat/sdrc.h @@ -766,6 +767,28 @@ static int __init gpmc_init(void) } postcore_initcall(gpmc_init); +static __devinit void gpmc_update_nand_reg(struct gpmc *gpmc, + struct omap_nand_platform_data *nand) +{ + int cs = nand-cs; + + nand-reg.gpmc_status = gpmc-io_base + GPMC_STATUS; + nand-reg.gpmc_nand_command = gpmc-io_base + GPMC_CS0_OFFSET + + GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs; + nand-reg.gpmc_nand_address = gpmc-io_base + GPMC_CS0_OFFSET + + GPMC_CS_NAND_ADDRESS + GPMC_CS_SIZE * cs; + nand-reg.gpmc_nand_data = gpmc-io_base + GPMC_CS0_OFFSET + + GPMC_CS_NAND_DATA + GPMC_CS_SIZE * cs; + nand-reg.gpmc_prefetch_config1 = gpmc-io_base + GPMC_PREFETCH_CONFIG1; + nand-reg.gpmc_prefetch_config2 = gpmc-io_base + GPMC_PREFETCH_CONFIG2; + nand-reg.gpmc_prefetch_control = gpmc-io_base + GPMC_PREFETCH_CONTROL; + nand-reg.gpmc_prefetch_status = gpmc-io_base + GPMC_PREFETCH_STATUS; + nand-reg.gpmc_ecc_config = gpmc-io_base + GPMC_ECC_CONFIG; + nand-reg.gpmc_ecc_control = gpmc-io_base + GPMC_ECC_CONTROL; + nand-reg.gpmc_ecc_size_config = gpmc-io_base + GPMC_ECC_SIZE_CONFIG; + nand-reg.gpmc_ecc1_result = gpmc-io_base + GPMC_ECC1_RESULT; +} + static __devinit struct resource gpmc_setup_cs_mem(struct gpmc_cs_data *p, struct gpmc_device_pdata *gdp, struct gpmc *gpmc) { @@ -1066,6 +1089,8 @@ static __devinit int gpmc_probe(struct platform_device *pdev) gpmc_mem_init(); for (gdq = gp-device_pdata, gd = gpmc-device; *gdq; gdq++, i++) { + if ((*gdq)-is_nand) + gpmc_update_nand_reg(gpmc, (*gdq)-pdata); ret = gpmc_setup_device(*gdq, gd, gpmc); if (IS_ERR_VALUE(ret)) dev_err(gpmc-dev, gpmc setup on %s failed\n, diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index fa62cdf..a320e71 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -169,6 +169,7 @@ struct gpmc_device_pdata { unsignednum_per_res; struct gpmc_cs_data *cs_data; unsignednum_cs; + boolis_nand; }; struct gpmc_pdata { @@ -179,6 +180,21 @@ struct gpmc_pdata { unsignednum_irq; }; +struct gpmc_nand_regs { + void __iomem*gpmc_status; + void __iomem*gpmc_nand_command; + void __iomem*gpmc_nand_address; + void __iomem*gpmc_nand_data; + void __iomem*gpmc_prefetch_config1; + void __iomem*gpmc_prefetch_config2; + void __iomem*gpmc_prefetch_control; + void __iomem*gpmc_prefetch_status; + void __iomem*gpmc_ecc_config; + void __iomem*gpmc_ecc_control; + void __iomem*gpmc_ecc_size_config; + void __iomem*gpmc_ecc1_result; +}; + extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns); extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps); extern unsigned int gpmc_ticks_to_ns(unsigned int ticks); diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h index 67fc506..86e4d9c 100644 --- a/arch/arm/plat-omap/include/plat/nand.h +++ b/arch/arm/plat-omap/include/plat/nand.h @@ -29,6 +29,7 @@ struct omap_nand_platform_data { unsigned long phys_base; int devsize; enum omap_ecc ecc_opt; + struct gpmc_nand_regs reg; }; /* minimum size for IO mapping */ -- 1.7.9.3 -- 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 v3 1/9] ARM: OMAP2+: gpmc: driver conversion
Convert GPMC code to driver. Boards using GPMC should provide driver with type of configuration, timing, CS, GPMC address space details (if already configured, driver will retrieve, as is existing). Platform devices would the be created for each connected peripheral (details also to be passed by board so that it reaches respective driver). And GPMC driver would populate memory resource details for the driver of connected peripheral. A peripheral connected to GPMC can have multiple address spaces using different chip select. Hence GPMC driver has been provided capability to create platform device for peripheral using mutiple CS. The peripheral that made it necessary was tusb6010. Thanks to Jon Hunter for his suggesstion on better way to handle this. Interrupts of GPMC are presented to drivers of connected peripherals as resource. A fictitious interrupt controller chip handles these interrupts at GPMC hardware level. Clients can use normal interrupt APIs. Platforms should inform GPMC driver infrastruture available for these imaginary client interrupts (like irq number). Platform information of peripheral passed to GPMC driver should indicate interrupts to be used via flags. Final destination for this driver is being investigated. Before moving to the new location, all existing GPMC users has to be converted to work with this driver. NAND driver for NAND used via GPMC is tightly coupled with GPMC driver (GPMC has few blocks exclusively for NAND), while that is not the case for most of the other users (they need GPMCs help only for initial configuration). Currently NAND driver manage using exported GPMC symbols. This is being planned to remove later would need informing NAND driver about GPMC NAND registers. This would help to have export symbol free GPMC driver, and probably mv omap2.c gpmc-nand.c for OMAP NAND driver. Thanks to Vaibhav Hiremath for his ideas on this. Acquiring CS# for NAND is done on a few boards. It means, depending on bootloader to embed this information. Probably CS# being used can be set in the Kernel, and acquiring it can be removed. If ever this capbility is needed, GPMC driver has to be made aware of handling it. OneNAND - as it may involve reconfiguring GPMC for synchronous may need a quirk to handle or driver has to be made more intelligent to handle it. Code related to GPMC clock may have to continue live in platform folders (even if the driver is moved to MFD) as input clock is beyond the control of GPMC and calculating timing for the peripheral may need other helpers. Cc: Vaibhav Hiremath hvaib...@ti.com Cc: Jon Hunter jon-hun...@ti.com Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 518 ++-- arch/arm/plat-omap/include/plat/gpmc.h | 50 ++- 2 files changed, 476 insertions(+), 92 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 00d5108..cf5d8f3 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -14,8 +14,11 @@ */ #undef DEBUG +#include linux/platform_device.h + #include linux/irq.h #include linux/kernel.h +#include linux/slab.h #include linux/init.h #include linux/err.h #include linux/clk.h @@ -64,6 +67,47 @@ #define ENABLE_PREFETCH(0x1 7) #define DMA_MPU_MODE 2 +#defineDRIVER_NAME omap-gpmc + +#defineGPMC_NR_IRQ 6 + +struct gpmc_device { + char*name; + int id; + void*pdata; + unsignedpdata_size; + struct resource *per_res; + unsignednum_per_res; + struct resource *gpmc_res; + unsignednum_gpmc_res; +}; + +struct gpmc_irq{ + unsignedirq; + u32 regval; +}; + +struct gpmc { + struct device *dev; + unsigned long fclk_period; + void __iomem*io_base; + unsigned long phys_base; + u32 memsize; + unsignedcs_map; + int ecc_used; + spinlock_t mem_lock; + struct resource mem_root; + struct resource cs_mem[GPMC_CS_NUM]; + /* XXX: Or allocate dynamically ? */ + struct gpmc_device device[GPMC_CS_NUM]; + unsignednum_device; + unsignedmaster_irq; + unsignedirq_start; + unsignednum_irq; + struct gpmc_irq irq[GPMC_NR_IRQ]; + struct irq_chip irq_chip; +}; + /* Structure to save gpmc cs context */ struct gpmc_cs_config { u32 config1; @@ -91,58 +135,50 @@ struct omap3_gpmc_regs { struct gpmc_cs_config cs_context[GPMC_CS_NUM]; }; -static struct resource gpmc_mem_root; -static struct resource gpmc_cs_mem[GPMC_CS_NUM]; -static
[PATCH v3 3/9] ARM: OMAP2+: nand: create platform data structure
New API for updating nand platform data. This has been created by unifying the two existing ones and taking out gpmc hardware handling. From now on, platforms can call omap_nand_init to initialize platform nand structures, it's fields. Or can statically create the same. Acquiring gpmc CS has been removed. Acquiring CS probably should be avoided, if ever required, do in GPMC driver. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-devkit8000.c |6 ++- arch/arm/mach-omap2/board-flash.c | 63 ++-- arch/arm/mach-omap2/board-flash.h | 13 -- arch/arm/mach-omap2/board-ldp.c|4 +- arch/arm/mach-omap2/board-omap3beagle.c|6 ++- arch/arm/mach-omap2/board-omap3touchbook.c |6 ++- arch/arm/mach-omap2/board-overo.c |5 ++- arch/arm/mach-omap2/board-zoom.c |5 ++- arch/arm/mach-omap2/common-board-devices.c | 46 arch/arm/mach-omap2/common-board-devices.h |1 - 10 files changed, 61 insertions(+), 94 deletions(-) diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index a2010f0..adfcfc1 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -59,6 +59,7 @@ #include mux.h #include hsmmc.h +#include board-flash.h #include common-board-devices.h #define OMAP_DM9000_GPIO_IRQ 25 @@ -648,8 +649,9 @@ static void __init devkit8000_init(void) usb_musb_init(NULL); usbhs_init(usbhs_bdata); - omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions, -ARRAY_SIZE(devkit8000_nand_partitions)); + omap_nand_init(devkit8000_nand_partitions, + ARRAY_SIZE(devkit8000_nand_partitions), GPMC_CS_NUM + 1, + NAND_BUSWIDTH_16, NULL); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal(sdrc_cke0, OMAP_PIN_OUTPUT); diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index 0349fd2..26c70b8 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -108,45 +108,45 @@ __init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs) defined(CONFIG_MTD_NAND_OMAP2_MODULE) /* Note that all values in this struct are in nanoseconds */ -static struct gpmc_timings nand_timings = { +struct gpmc_timings nand_default_timings[1] = { + { + .sync_clk = 0, - .sync_clk = 0, + .cs_on = 0, + .cs_rd_off = 36, + .cs_wr_off = 36, - .cs_on = 0, - .cs_rd_off = 36, - .cs_wr_off = 36, + .adv_on = 6, + .adv_rd_off = 24, + .adv_wr_off = 36, - .adv_on = 6, - .adv_rd_off = 24, - .adv_wr_off = 36, + .we_off = 30, + .oe_off = 48, - .we_off = 30, - .oe_off = 48, + .access = 54, + .rd_cycle = 72, + .wr_cycle = 72, - .access = 54, - .rd_cycle = 72, - .wr_cycle = 72, - - .wr_access = 30, - .wr_data_mux_bus = 0, + .wr_access = 30, + .wr_data_mux_bus = 0, + }, }; -static struct omap_nand_platform_data board_nand_data = { - .gpmc_t = nand_timings, +static struct omap_nand_platform_data omap_nand_data = { + .gpmc_t = nand_default_timings, }; -void -__init board_nand_init(struct mtd_partition *nand_parts, - u8 nr_parts, u8 cs, int nand_type) +struct omap_nand_platform_data * +__init omap_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs, + int nand_type, struct gpmc_timings *gpmc_t) { - board_nand_data.cs = cs; - board_nand_data.parts = nand_parts; - board_nand_data.nr_parts= nr_parts; - board_nand_data.devsize = nand_type; - - board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT; - board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs; - gpmc_nand_init(board_nand_data); + omap_nand_data.cs = cs; + omap_nand_data.parts= nand_parts; + omap_nand_data.nr_parts = nr_parts; + omap_nand_data.devsize = nand_type; + omap_nand_data.gpmc_t = gpmc_t; + + return omap_nand_data; } #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */ @@ -242,6 +242,7 @@ void __init board_flash_init(struct flash_partitions partition_info[], if (nandcs GPMC_CS_NUM) pr_err(NAND: Unable to find configuration in GPMC\n); else - board_nand_init(partition_info[2].parts, - partition_info[2].nr_parts, nandcs, nand_type); + omap_nand_init(partition_info[2].parts
[PATCH v3 4/9] ARM: OMAP2+: gpmc-nand: populate gpmc configs
Currently gpmc is configured in platform for nand. As configuring gpmc has been moved to gpmc driver, populate details needed for the driver to configure gpmc. gpmc driver would configure based on this information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc-nand.c| 97 ++-- arch/arm/plat-omap/include/plat/nand.h |8 ++- 2 files changed, 48 insertions(+), 57 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index 386dec8..85de31f 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -21,24 +21,38 @@ #include plat/board.h #include plat/gpmc.h -static struct resource gpmc_nand_resource = { - .flags = IORESOURCE_MEM, + +#defineGPMC_NAND_CONFIG_NUM4 +#defineIDX_DEV_SIZE2 +#defineIDX_RDY_BSY 3 + +static struct gpmc_config gpmc_nand_config[GPMC_NAND_CONFIG_NUM] = { + { GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND}, + { GPMC_CONFIG_WP, 0}, }; -static struct platform_device gpmc_nand_device = { +static struct gpmc_cs_data gpmc_nand_cs_info = { + .config = gpmc_nand_config, + .num_config = ARRAY_SIZE(gpmc_nand_config), + .irq_flags = GPMC_IRQ_FIFOEVENT | GPMC_IRQ_TERMINALCOUNT, +}; + +static struct gpmc_device_pdata gpmc_nand_info = { .name = omap2-nand, .id = 0, - .num_resources = 1, - .resource = gpmc_nand_resource, + .cs_data= gpmc_nand_cs_info, + .num_cs = 1, }; -static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data) -{ - struct gpmc_timings t; - int err; +static struct gpmc_timings t; - if (!gpmc_nand_data-gpmc_t) +static struct gpmc_timings * +gpmc_nand_retime(struct omap_nand_platform_data *gpmc_nand_data) +{ + if (!gpmc_nand_data-gpmc_t) { + pr_warn(gpmc timings not provided\n); return 0; + } memset(t, 0, sizeof(t)); t.sync_clk = gpmc_nand_data-gpmc_t-sync_clk; @@ -68,56 +82,31 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_nand_data-gpmc_t-cs_wr_off); t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data-gpmc_t-wr_cycle); - /* Configure GPMC */ - if (gpmc_nand_data-devsize == NAND_BUSWIDTH_16) - gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_DEV_SIZE, 1); - else - gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_DEV_SIZE, 0); - gpmc_cs_configure(gpmc_nand_data-cs, - GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND); - err = gpmc_cs_set_timings(gpmc_nand_data-cs, t); - if (err) - return err; - - return 0; + return t; } -int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) +struct gpmc_device_pdata * +__init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) { - int err = 0; - struct device *dev = gpmc_nand_device.dev; + gpmc_nand_info.pdata = gpmc_nand_data; + gpmc_nand_info.pdata_size = sizeof(*gpmc_nand_data); - gpmc_nand_device.dev.platform_data = gpmc_nand_data; + gpmc_nand_cs_info.cs = gpmc_nand_data-cs; + gpmc_nand_cs_info.mem_size = NAND_IO_SIZE; - err = gpmc_cs_request(gpmc_nand_data-cs, NAND_IO_SIZE, - gpmc_nand_data-phys_base); - if (err 0) { - dev_err(dev, Cannot request GPMC CS\n); - return err; - } + gpmc_nand_cs_info.timing = gpmc_nand_retime(gpmc_nand_data); -/* Set timings in GPMC */ - err = omap2_nand_gpmc_retime(gpmc_nand_data); - if (err 0) { - dev_err(dev, Unable to set gpmc timings: %d\n, err); - return err; - } - - /* Enable RD PIN Monitoring Reg */ - if (gpmc_nand_data-dev_ready) { - gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_RDY_BSY, 1); - } - - err = platform_device_register(gpmc_nand_device); - if (err 0) { - dev_err(dev, Unable to register NAND device\n); - goto out_free_cs; - } - - return 0; + gpmc_nand_config[IDX_DEV_SIZE].cmd = GPMC_CONFIG_DEV_SIZE; + if (gpmc_nand_data-devsize == NAND_BUSWIDTH_16) + gpmc_nand_config[IDX_DEV_SIZE].val = 1; + else + gpmc_nand_config[IDX_DEV_SIZE].val = 0; -out_free_cs: - gpmc_cs_free(gpmc_nand_data-cs); + gpmc_nand_config[IDX_RDY_BSY].cmd = GPMC_CONFIG_RDY_BSY; + if (gpmc_nand_data-dev_ready) + gpmc_nand_config[IDX_RDY_BSY].val = 1; + else + gpmc_nand_config[IDX_RDY_BSY].val = 0; - return err; + return gpmc_nand_info; } diff --git a/arch/arm/plat-omap/include/plat/nand.h
[PATCH v3 5/9] ARM: OMAP2+: gpmc-smsc911x: gpmc driver information
gpmc has been converted to driver. And all gpmc related configuration would be done by gpmc driver. Provide gpmc driver with sufficient information so that it can configure. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc-smsc911x.c | 59 --- arch/arm/plat-omap/include/plat/gpmc-smsc911x.h |9 +++- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-smsc911x.c b/arch/arm/mach-omap2/gpmc-smsc911x.c index b6c77be..52192a9 100644 --- a/arch/arm/mach-omap2/gpmc-smsc911x.c +++ b/arch/arm/mach-omap2/gpmc-smsc911x.c @@ -24,13 +24,8 @@ #include plat/gpmc.h #include plat/gpmc-smsc911x.h -static struct resource gpmc_smsc911x_resources[] = { - [0] = { - .flags = IORESOURCE_MEM, - }, - [1] = { - .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, - }, +static struct resource gpmc_smsc911x_resources = { + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, }; static struct smsc911x_platform_config gpmc_smsc911x_config = { @@ -44,26 +39,42 @@ static struct smsc911x_platform_config gpmc_smsc911x_config = { * assume that pin multiplexing is done in the board-*.c file, * or in the bootloader. */ -void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg) +__init struct gpmc_device_pdata * +gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg) { - struct platform_device *pdev; - unsigned long cs_mem_base; int ret; + struct gpmc_device_pdata *gpmc_pdev; + struct gpmc_cs_data *gpmc_cs; - if (gpmc_cs_request(gpmc_cfg-cs, SZ_16M, cs_mem_base) 0) { - pr_err(Failed to request GPMC mem region\n); - return; + gpmc_pdev = kzalloc(sizeof(*gpmc_pdev), GFP_KERNEL); + if (gpmc_pdev == NULL) + return gpmc_pdev; + + gpmc_cs = kzalloc(sizeof(*gpmc_cs), GFP_KERNEL); + if (gpmc_pdev == NULL) { + kfree(gpmc_pdev); + return NULL; } - gpmc_smsc911x_resources[0].start = cs_mem_base + 0x0; - gpmc_smsc911x_resources[0].end = cs_mem_base + 0xff; + gpmc_pdev-cs_data = gpmc_cs; + gpmc_pdev-num_cs = 1; + gpmc_pdev-name = smsc911x; + gpmc_pdev-id = gpmc_cfg-id; + gpmc_pdev-pdata = gpmc_smsc911x_config; + gpmc_pdev-pdata_size = sizeof(gpmc_smsc911x_config); + + gpmc_cs-cs = gpmc_cfg-cs; + gpmc_cs-mem_size = 0xff; + + gpmc_pdev-per_res = gpmc_smsc911x_resources; + gpmc_pdev-num_per_res = 1; if (gpio_request_one(gpmc_cfg-gpio_irq, GPIOF_IN, smsc911x irq)) { pr_err(Failed to request IRQ GPIO%d\n, gpmc_cfg-gpio_irq); goto free1; } - gpmc_smsc911x_resources[1].start = gpio_to_irq(gpmc_cfg-gpio_irq); + gpmc_smsc911x_resources.start = gpio_to_irq(gpmc_cfg-gpio_irq); if (gpio_is_valid(gpmc_cfg-gpio_reset)) { ret = gpio_request_one(gpmc_cfg-gpio_reset, @@ -81,21 +92,15 @@ void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg) gpmc_smsc911x_config.flags = gpmc_cfg-flags ? : SMSC911X_USE_16BIT; - pdev = platform_device_register_resndata(NULL, smsc911x, gpmc_cfg-id, -gpmc_smsc911x_resources, ARRAY_SIZE(gpmc_smsc911x_resources), -gpmc_smsc911x_config, sizeof(gpmc_smsc911x_config)); - if (!pdev) { - pr_err(Unable to register platform device\n); - gpio_free(gpmc_cfg-gpio_reset); - goto free2; - } - - return; + return gpmc_pdev; free2: gpio_free(gpmc_cfg-gpio_irq); free1: - gpmc_cs_free(gpmc_cfg-cs); + kfree(gpmc_cs); + kfree(gpmc_pdev); pr_err(Could not initialize smsc911x device\n); + + return NULL; } diff --git a/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h b/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h index ea6c9c8..66dc7f1 100644 --- a/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h +++ b/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h @@ -11,6 +11,8 @@ * published by the Free Software Foundation. */ +#includeplat/gpmc.h + #ifndef __ASM_ARCH_OMAP_GPMC_SMSC911X_H__ struct omap_smsc911x_platform_data { @@ -23,12 +25,15 @@ struct omap_smsc911x_platform_data { #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) -extern void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d); +extern struct gpmc_device_pdata * +gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d); #else -static inline void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d) +static inline struct gpmc_device_pdata * +gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d) { + return NULL; } #endif -- 1.7.9.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord
[PATCH v3 6/9] mtd: nand: omap2: obtain memory from resource
gpmc being converted to driver, provides drivers of peripheral connected memory space used by the peripheral as memory resource. Modify nand omap driver to obtain memory detials from resource structure. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/plat-omap/include/plat/nand.h |1 - drivers/mtd/nand/omap2.c | 20 ++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h index 30c61c9..570c4f4 100644 --- a/arch/arm/plat-omap/include/plat/nand.h +++ b/arch/arm/plat-omap/include/plat/nand.h @@ -26,7 +26,6 @@ struct omap_nand_platform_data { booldev_ready; int gpmc_irq; enum nand_ioxfer_type; - unsigned long phys_base; int devsize; enum omap_ecc ecc_opt; struct gpmc_nand_regs reg; diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index c2b0bba..be4b321 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -118,6 +118,7 @@ struct omap_nand_info { int gpmc_cs; unsigned long phys_base; + unsigned long mem_size; struct completion comp; int dma_ch; int gpmc_irq; @@ -931,6 +932,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) struct omap_nand_platform_data *pdata; int err; int i, offset; + struct resource *res; pdata = pdev-dev.platform_data; if (pdata == NULL) { @@ -950,7 +952,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info-pdev = pdev; info-gpmc_cs = pdata-cs; - info-phys_base = pdata-phys_base; info-mtd.priv = info-nand; info-mtd.name = dev_name(pdev-dev); @@ -959,16 +960,23 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info-nand.options = pdata-devsize; info-nand.options |= NAND_SKIP_BBTSCAN; - /* NAND write protect off */ - gpmc_cs_configure(info-gpmc_cs, GPMC_CONFIG_WP, 0); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + err = -EINVAL; + dev_err(pdev-dev, error getting memory resource\n); + goto out_free_info; + } + + info-phys_base = res-start; + info-mem_size = resource_size(res); - if (!request_mem_region(info-phys_base, NAND_IO_SIZE, + if (!request_mem_region(info-phys_base, info-mem_size, pdev-dev.driver-name)) { err = -EBUSY; goto out_free_info; } - info-nand.IO_ADDR_R = ioremap(info-phys_base, NAND_IO_SIZE); + info-nand.IO_ADDR_R = ioremap(info-phys_base, info-mem_size); if (!info-nand.IO_ADDR_R) { err = -ENOMEM; goto out_release_mem_region; @@ -1110,7 +1118,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) return 0; out_release_mem_region: - release_mem_region(info-phys_base, NAND_IO_SIZE); + release_mem_region(info-phys_base, info-mem_size); out_free_info: kfree(info); -- 1.7.9.3 -- 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 v3 7/9] mtd: nand: omap2: use gpmc provided irqs
GPMC driver provides it's clientsd with interrupts that can be used through struct resource. Make use of it for irq mode functionality. Signed-off-by: Afzal Mohammed af...@ti.com --- drivers/mtd/nand/omap2.c | 67 +- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index be4b321..440536b 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -121,7 +121,8 @@ struct omap_nand_info { unsigned long mem_size; struct completion comp; int dma_ch; - int gpmc_irq; + int gpmc_irq_fifo; + int gpmc_irq_count; enum { OMAP_NAND_IO_READ = 0, /* read */ OMAP_NAND_IO_WRITE, /* write */ @@ -472,13 +473,11 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev) { struct omap_nand_info *info = (struct omap_nand_info *) dev; u32 bytes; - u32 irq_stat; - irq_stat = gpmc_read_status(GPMC_GET_IRQ_STATUS); bytes = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT); bytes = bytes 0xFFFC; /* io in multiple of 4 bytes */ if (info-iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */ - if (irq_stat 0x2) + if (this_irq == info-gpmc_irq_count) goto done; if (info-buf_len (info-buf_len bytes)) @@ -495,20 +494,17 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev) (u32 *)info-buf, bytes 2); info-buf = info-buf + bytes; - if (irq_stat 0x2) + if (this_irq == info-gpmc_irq_count) goto done; } - gpmc_cs_configure(info-gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat); return IRQ_HANDLED; done: complete(info-comp); - /* disable irq */ - gpmc_cs_configure(info-gpmc_cs, GPMC_ENABLE_IRQ, 0); - /* clear status */ - gpmc_cs_configure(info-gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat); + disable_irq_nosync(info-gpmc_irq_fifo); + disable_irq_nosync(info-gpmc_irq_count); return IRQ_HANDLED; } @@ -542,9 +538,9 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len) goto out_copy; info-buf_len = len; - /* enable irq */ - gpmc_cs_configure(info-gpmc_cs, GPMC_ENABLE_IRQ, - (GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT)); + + enable_irq(info-gpmc_irq_count); + enable_irq(info-gpmc_irq_fifo); /* waiting for read to complete */ wait_for_completion(info-comp); @@ -591,12 +587,13 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd, goto out_copy; info-buf_len = len; - /* enable irq */ - gpmc_cs_configure(info-gpmc_cs, GPMC_ENABLE_IRQ, - (GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT)); + + enable_irq(info-gpmc_irq_count); + enable_irq(info-gpmc_irq_fifo); /* waiting for write to complete */ wait_for_completion(info-comp); + /* wait for data to flushed-out before reset the prefetch */ tim = 0; limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS)); @@ -982,6 +979,14 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) goto out_release_mem_region; } + info-gpmc_irq_fifo = platform_get_irq(pdev, 0); + if (info-gpmc_irq_fifo == -ENXIO) + dev_warn(pdev-dev, error getting FIFO IRQ\n); + + info-gpmc_irq_count = platform_get_irq(pdev, 1); + if (info-gpmc_irq_fifo == -ENXIO) + dev_warn(pdev-dev, error getting TERMINALCOUNT IRQ\n); + info-nand.controller = info-controller; info-nand.IO_ADDR_W = info-nand.IO_ADDR_R; @@ -1037,17 +1042,24 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) break; case NAND_OMAP_PREFETCH_IRQ: - err = request_irq(pdata-gpmc_irq, - omap_nand_irq, IRQF_SHARED, gpmc-nand, info); + err = request_irq(info-gpmc_irq_fifo, omap_nand_irq, + IRQF_SHARED, gpmc-nand-fifo, info); if (err) { dev_err(pdev-dev, requesting irq(%d) error:%d, - pdata-gpmc_irq, err); + info-gpmc_irq_fifo, err); goto out_release_mem_region; - } else { - info-gpmc_irq = pdata-gpmc_irq; - info-nand.read_buf = omap_read_buf_irq_pref; - info-nand.write_buf
[PATCH v3 8/9] mtd: nand: omap2: handle nand on gpmc
GPMC driver has been modified to fill NAND platform data with GPMC NAND register details. As these registers are accessible in NAND driver itself, configure NAND in GPMC by itself. Note: Verfying that other CS have not yet enabled for prefetch ecc has to be incorporated. Currently this causes no issues as there are no boards that use NAND on multiple CS. With GPMC modifications, perhaps it would be better to consider NAND connected on multiple CS as a single peripheral using multiple CS. This would make handling multiple CS issues easier. Signed-off-by: Afzal Mohammed af...@ti.com --- drivers/mtd/nand/omap2.c | 209 -- 1 file changed, 165 insertions(+), 44 deletions(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 440536b..34fb726 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -129,8 +129,79 @@ struct omap_nand_info { } iomode; u_char *buf; int buf_len; + struct gpmc_nand_regs reg; }; +#definePREFETCH_CONFIG1_CS_SHIFT 24 +#defineECC_CONFIG_CS_SHIFT 1 +#defineCS_MASK 0x7 +#defineENABLE_PREFETCH (0x1 7) +#defineDMA_MPU_MODE_SHIFT 2 +#defineECCSIZE1_SHIFT 22 +#defineECC1RESULTSIZE 0x1 +#defineECC_CLEAR_SHIFT 8 +#defineECC10x1 + +/** + * omap_prefetch_enable - configures and starts prefetch transfer + * @cs: cs (chip select) number + * @fifo_th: fifo threshold to be used for read/ write + * @dma_mode: dma mode enable (1) or disable (0) + * @u32_count: number of bytes to be transferred + * @is_write: prefetch read(0) or write post(1) mode + */ +static int omap_prefetch_enable(int cs, int fifo_th, int dma_mode, + unsigned int u32_count, int is_write, struct omap_nand_info *info) +{ + u32 val; + + if (fifo_th PREFETCH_FIFOTHRESHOLD_MAX) { + pr_err(gpmc: fifo threshold is not supported\n); + return -1; + } else if (!(readl(info-reg.gpmc_prefetch_control))) { + /* Set the amount of bytes to be prefetched */ + writel(u32_count, info-reg.gpmc_prefetch_config2); + + /* Set dma/mpu mode, the prefetch read / post write and +* enable the engine. Set which cs is has requested for. +*/ + val = ((cs PREFETCH_CONFIG1_CS_SHIFT) | + PREFETCH_FIFOTHRESHOLD(fifo_th) | + ENABLE_PREFETCH | + (dma_mode DMA_MPU_MODE_SHIFT) | + (0x1 is_write)); + writel(val, info-reg.gpmc_prefetch_config1); + + /* Start the prefetch engine */ + writel(0x1, info-reg.gpmc_prefetch_control); + } else { + return -EBUSY; + } + + return 0; +} + +/** + * omap_prefetch_reset - disables and stops the prefetch engine + */ +static int omap_prefetch_reset(int cs, struct omap_nand_info *info) +{ + u32 config1; + + /* check if the same module/cs is trying to reset */ + config1 = readl(info-reg.gpmc_prefetch_config1); + if (((config1 PREFETCH_CONFIG1_CS_SHIFT) CS_MASK) != cs) + return -EINVAL; + + /* Stop the PFPW engine */ + writel(0x0, info-reg.gpmc_prefetch_control); + + /* Reset/disable the PFPW engine */ + writel(0x0, info-reg.gpmc_prefetch_config1); + + return 0; +} + /** * omap_hwcontrol - hardware specific access to control-lines * @mtd: MTD device structure @@ -149,13 +220,13 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) if (cmd != NAND_CMD_NONE) { if (ctrl NAND_CLE) - gpmc_nand_write(info-gpmc_cs, GPMC_NAND_COMMAND, cmd); + writeb(cmd, info-reg.gpmc_nand_command); else if (ctrl NAND_ALE) - gpmc_nand_write(info-gpmc_cs, GPMC_NAND_ADDRESS, cmd); + writeb(cmd, info-reg.gpmc_nand_address); else /* NAND_NCE */ - gpmc_nand_write(info-gpmc_cs, GPMC_NAND_DATA, cmd); + writeb(cmd, info-reg.gpmc_nand_data); } } @@ -189,7 +260,8 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len) iowrite8(*p++, info-nand.IO_ADDR_W); /* wait until buffer is available for write */ do { - status = gpmc_read_status(GPMC_STATUS_BUFFER); + status = readl(info-reg.gpmc_status) + GPMC_STATUS_BUFF_EMPTY; } while (!status
[TMP] OMAP3EVM: Test gpmc nand smsc911x
Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-omap3evm.c | 95 +- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index 49df127..60938af 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -23,6 +23,7 @@ #include linux/input/matrix_keypad.h #include linux/leds.h #include linux/interrupt.h +#include linux/mtd/nand.h #include linux/spi/spi.h #include linux/spi/ads7846.h @@ -41,6 +42,7 @@ #include asm/mach/arch.h #include asm/mach/map.h +#include plat/nand.h #include plat/board.h #include plat/usb.h #include common.h @@ -52,6 +54,7 @@ #include sdram-micron-mt46h32m32lf-6.h #include hsmmc.h #include common-board-devices.h +#include board-flash.h #define OMAP3_EVM_TS_GPIO 175 #define OMAP3_EVM_EHCI_VBUS22 @@ -102,6 +105,36 @@ static void __init omap3_evm_get_revision(void) } } +static struct gpmc_device_pdata *gpmc_data_array[3]; +static struct gpmc_device_pdata **gpmc_data_cur = gpmc_data_array; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_data_array, +}; + +static struct resource gpmc_resources[] = { + { + .start = OMAP34XX_GPMC_BASE, + .end = OMAP34XX_GPMC_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_34XX_GPMC_IRQ, + .end = INT_34XX_GPMC_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device gpmc_device = { + .name = omap-gpmc, + .id = -1, + .num_resources = ARRAY_SIZE(gpmc_resources), + .resource = gpmc_resources, + .dev= { + .platform_data = gpmc_data, + } +}; + #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) #include plat/gpmc-smsc911x.h @@ -114,6 +147,8 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = { static inline void __init omap3evm_init_smsc911x(void) { + struct gpmc_device_pdata *gpmc_smsc911x_info; + /* Configure ethernet controller reset gpio */ if (cpu_is_omap3430()) { if (get_omap3_evm_rev() == OMAP3EVM_BOARD_GEN_1) @@ -122,7 +157,11 @@ static inline void __init omap3evm_init_smsc911x(void) smsc911x_cfg.gpio_reset = OMAP3EVM_GEN2_ETHR_GPIO_RST; } - gpmc_smsc911x_init(smsc911x_cfg); + gpmc_smsc911x_info = gpmc_smsc911x_init(smsc911x_cfg); + if (gpmc_smsc911x_info) + *gpmc_data_cur++ = gpmc_smsc911x_info; + else + pr_err(error: unable to initilaize gpmc smsc911x\n); } #else @@ -523,6 +562,41 @@ static struct usbhs_omap_board_data usbhs_bdata __initdata = { .reset_gpio_port[2] = -EINVAL }; +/* + * NAND + */ +static struct mtd_partition omap3_evm_nand_partitions[] = { + /* All the partition sizes are listed in terms of NAND block size */ + { + .name = X-Loader-NAND, + .offset = 0, + .size = 4 * (64 * 2048), + .mask_flags = MTD_WRITEABLE,/* force read-only */ + }, + { + .name = U-Boot-NAND, + .offset = MTDPART_OFS_APPEND, /* Offset = 0x8 */ + .size = 10 * (64 * 2048), + .mask_flags = MTD_WRITEABLE,/* force read-only */ + }, + { + .name = Boot Env-NAND, + + .offset = MTDPART_OFS_APPEND, /* Offset = 0x1c */ + .size = 6 * (64 * 2048), + }, + { + .name = Kernel-NAND, + .offset = MTDPART_OFS_APPEND, /* Offset = 0x28 */ + .size = 40 * (64 * 2048), + }, + { + .name = File System - NAND, + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, /* Offset = 0x78 */ + }, +}; + #ifdef CONFIG_OMAP_MUX static struct omap_board_mux omap35x_board_mux[] __initdata = { OMAP3_MUX(SYS_NIRQ, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP | @@ -630,6 +704,8 @@ static struct regulator_consumer_supply dummy_supplies[] = { static void __init omap3_evm_init(void) { + struct omap_nand_platform_data *nand_data; + omap3_evm_get_revision(); regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); @@ -681,6 +757,23 @@ static void __init omap3_evm_init(void) omap3evm_init_smsc911x(); omap3_evm_display_init(); omap3_evm_wl12xx_init(); + /* NAND */ + nand_data = omap_nand_init(omap3_evm_nand_partitions, + ARRAY_SIZE(omap3_evm_nand_partitions), + 0
[PATCH 00/39] OMAP GPMC driver conversion
Hi, GPMC driver conversion patch series. Some peripherals has GPMC helper functions, these has been modified to cater to the needs of GPMC driver. All the boards using GPMC has been adapted to use the new GPMC driver. GPMC HWMOD entry for OMAP2/3 has been added. On OMAP3, kernel does spit omap_hwmod: gpmc: cannot be enabled for reset (3), but peripherals connected via GPMC are working. Really shaky about OMAP2 GPMC HWMOD entry. Would be helpful if someone can help me in resolving warning on OMAP3 verify whether OMAP2 entry is proper. The series adapts to HWMOD. Drivers, NAND OneNAND of OMAP has been modified to make use of GPMC changes cleaned up the now unnecessary exported symbol usages. This series has been made on top of, 5e136da Linux-omap rebuilt: Updated to -rc5, A patch by Javier Martinez Canillas jav...@dowhile0.org, OMAP3: igep0020: Add support for Micron NAND Flash storage memory, has also been incorporated into the series as this was necessary for igep0020 board. This has been tested on omap3 evm (SMSC911x) beagle board (NAND) I would need help to get these changes tested on other boards using GPMC. Expected problematic boards are those having OMAP2xxx SoCs, apollon board. In the case of apollon, in addition to it being OMAP2xxx, it was modified to use gpmc_smc91x_init instead of directly writing to configuration registers. Additional features that currently boards in mainline does not make use of like, waitpin interrupt handling, changes to leverage revision 6 IP differences has not been incorporated. GPMC driver now provides NAND driver with GPMC-NAND registers so that OMAP NAND driver can handle those by itself instead of using exported symbols. Acquiring CS for NAND has also been incorporated, it has been made as a separate patch as it is felt that this should probably go away, explained in the relevant patch. GPMC (General Purpose Memory Controller) in brief: GPMC is an unified memory controller dedicated to interfacing external memory devices like Asynchronous SRAM like memories and application specific integrated circuit devices. Asynchronous, synchronous, and page mode burst NOR flash devices NAND flash Pseudo-SRAM devices GPMC details can be referred in AM335X Technical Reference Manual @ http://www.ti.com/lit/pdf/spruh73 v4: Handle wait pin (except for interrupts), enhance configuration timing interface of GPMC to take care of all boards. Dynamic allocation of interrupt instead of static. Convert remaining peripherals to work with GPMC driver. Handle acquiring NAND CS#, adapt to HWMOD, update HWMOD OMAP2/3 entries, other minor commenst on v3. v3: Single device structure passed from platform for peripherals using multiple CS instead of using multiple device structure having a few redundant data, handle interrupts, GPMC NAND handling by GPMC NAND driver instead of GPMC driver v2: Avoid code movement that kept similar code together (for easy review) TODO: Cleanup Regards Afzal Afzal Mohammed (38): ARM: OMAP2+: gpmc: driver conversion ARM: OMAP2+: gpmc: Adapt to HWMOD ARM: OMAP2+: gpmc: register details for nand driver ARM: OMAP2+: gpmc: Acquire NAND CS value ARM: OMAP2+: nand: create platform data structure ARM: OMAP2+: onenand: return value in init function ARM: OMAP2+: gpmc-nand: Adapt to use gpmc driver ARM: OMAP2+: gpmc-onenand: Adapt to use gpmc driver ARM: OMAP2+: flash: Adapt to gpmc driver ARM: OMAP2+: gpmc-smsc911x: Adapt to use gpmc driver ARM: OMAP2+: gpmc-smc91x: Adapt to use gpmc driver ARM: OMAP2+: gpmc-tusb6010: Adapt to gpmc driver ARM: OMAP3: hwmod data: add gpmc ARM: OMAP2xxx: hwmod data: add gpmc mtd: nand: omap2: obtain memory from resource mtd: nand: omap2: use gpmc provided irqs mtd: nand: omap2: handle nand on gpmc mtd: onenand: omap: obtain memory from resource ARM: OMAP2+: board omap3evm: gpmc driver adaptation ARM: OMAP2+: board omap3beagle: gpmc driver adaptation ARM: OMAP2+: board apollon: gpmc driver adaptation ARM: OMAP2+: board h4: gpmc driver adaptation ARM: OMAP2+: board 3630sdp: gpmc driver adaptation ARM: OMAP2+: board 3430sdp: gpmc driver adaptation ARM: OMAP2+: board 2430sdp: gpmc driver adaptation ARM: OMAP2+: board cm-t3517: gpmc driver adaptation ARM: OMAP2+: board cm-t35: gpmc driver adaptation ARM: OMAP2+: board ldp: gpmc driver adaptation ARM: OMAP2+: board n8x0: gpmc driver adaptation ARM: OMAP2+: board omap3logic: gpmc driver adaptation ARM: OMAP2+: board omap3pandora: gpmc driver adaptation ARM: OMAP2+: board omap3stalker: gpmc driver adaptation ARM: OMAP2+: board omap4pcm049: gpmc driver adaptation ARM: OMAP2+: board overo: gpmc driver adaptation ARM: OMAP2+: board rm680: gpmc driver adaptation ARM: OMAP2+: board rx51: gpmc driver adaptation ARM: OMAP2+: board zoom-debugboard: gpmc driver adaptation ARM: OMAP2+: board igep0020: gpmc driver adaptation Javier Martinez Canillas (1): OMAP3: igep0020: Add support
[PATCH 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
Create API for platforms to adapt gpmc to HWMOD Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 52 +++- arch/arm/plat-omap/include/plat/gpmc.h |1 + 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 12916f3..c8d07bb 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -33,6 +33,8 @@ #include plat/sdrc.h +#include plat/omap_device.h + /* GPMC register offsets */ #define GPMC_REVISION 0x00 #define GPMC_SYSCONFIG 0x10 @@ -276,6 +278,31 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns) return ticks * gpmc_get_fclk_period() / 1000; } +int __init omap_init_gpmc(struct gpmc_pdata *pdata) +{ + struct omap_hwmod *oh; + struct platform_device *pdev; + char *name = omap-gpmc; + char *oh_name = gpmc; + + pdata-clk_prd = gpmc_get_fclk_period(); + + oh = omap_hwmod_lookup(oh_name); + if (!oh) { + pr_err(Could not look up %s\n, oh_name); + return -ENODEV; + } + + pdev = omap_device_build(name, -1, oh, pdata, + sizeof(*pdata), NULL, 0, 0); + if (IS_ERR(pdev)) { + WARN(1, Can't build omap_device for %s:%s.\n, + name, oh-name); + return PTR_ERR(pdev); + } + + return 0; +} #ifdef DEBUG static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, int time, const char *name) @@ -843,24 +870,19 @@ static __devinit void gpmc_mem_init(void) static int __init gpmc_init(void) { - int ret = -EINVAL; - char *ck = NULL; - - if (cpu_is_omap24xx()) { - ck = core_l3_ck; - } else if (cpu_is_omap34xx()) { - ck = gpmc_fck; - } else if (cpu_is_omap44xx()) { - ck = gpmc_ck; - } + char *oh_name = gpmc; + struct omap_hwmod *oh; - if (WARN_ON(!ck)) - return ret; + oh = omap_hwmod_lookup(oh_name); + if (!oh) { + pr_err(Could not look up %s\n, oh_name); + return -ENODEV; + } - gpmc_l3_clk = clk_get(NULL, ck); + gpmc_l3_clk = clk_get(NULL, oh-main_clk); if (IS_ERR(gpmc_l3_clk)) { - printk(KERN_ERR Could not get GPMC clock %s\n, ck); - BUG(); + pr_err(error: clk_get on %s\n, oh-main_clk); + return -EINVAL; } clk_enable(gpmc_l3_clk); diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 2eedd99..c5cf020 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -217,6 +217,7 @@ struct gpmc_pdata { }; extern int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs); +extern int omap_init_gpmc(struct gpmc_pdata *pdata); extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns); extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps); -- 1.7.10 -- 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 01/39] ARM: OMAP2+: gpmc: driver conversion
Convert GPMC code to driver. Boards using GPMC should provide driver with type of configuration, timing, CS. Platform devices would then be created for each connected peripheral (details also to be passed by board so that it reaches respective driver). And GPMC driver would populate memory resource details for the connected peripheral driver. Boards should inform gpmc driver with platform data destined for peripheral driver. gpmc driver will provide the same information to peripheral driver. A peripheral connected to GPMC can have multiple address spaces using different chip select. Hence GPMC driver has been provided capability to create platform device for peripheral using mutiple CS. The peripheral that made it necessary was tusb6010. Interrupts of GPMC are presented to drivers of connected peripherals as resource. A fictitious interrupt controller chip handles these interrupts at GPMC hardware level. Clients can use normal interrupt APIs. Platform information of peripheral passed to GPMC driver should indicate interrupts to be used via flags. Driver is capable of configuring waitpin, waitpin details has to be provided per CS. Wait pin has been considered as exclusive resource as multiple peripherals should not using the same pin, at the same it is valid for mutiple CS to use same waitpin provided they are a part of single peripheral (eg. tusb6010) An exported symbol for reconfiguring GPMC settings has been provided. OneNAND is the one that neccessitated this. Acquiring CS# for NAND is done on a few boards. It means, depending on bootloader to embed this information. Probably CS# being used can be set in the Kernel, and acquiring it can be removed. If ever this capbility is needed, GPMC driver has to be made aware of handling it. Modifications has been made keeping in mind that the driver would have to move to driver folder. This explains requirement of clk_prd field; even though clk_prd variable is not necessary as gpmc_get_fclk_period is present in the same file as of now, this will help in moving the driver easily to drivers folder. Code related to GPMC clock may have to continue live in platform folders as input clock is beyond the control of GPMC and calculating timing for the peripheral may need other helpers. This explains presence of 'gpmc_cs_calc_divider' along with 'gpmc_calc_divider', both doing same work, latter meant to go with driver, former for calculation in platform code. Thanks to Vaibhav Hiremath Jonathan Hunter on their various good suggestions which resulted in improving the code. Cc: Vaibhav Hiremath hvaib...@ti.com Cc: Jon Hunter jon-hun...@ti.com Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 877 arch/arm/plat-omap/include/plat/gpmc.h | 93 +++- 2 files changed, 872 insertions(+), 98 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 580e684..12916f3 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -14,8 +14,11 @@ */ #undef DEBUG +#include linux/platform_device.h + #include linux/irq.h #include linux/kernel.h +#include linux/slab.h #include linux/init.h #include linux/err.h #include linux/clk.h @@ -53,6 +56,45 @@ #define GPMC_CS0_OFFSET0x60 #define GPMC_CS_SIZE 0x30 +/* GPMC register bits */ +#defineGPMC_CONFIG1_TIMEPARAGRANULARITYBIT(4) +#defineGPMC_CONFIG1_DEVICETYPE_NAND GPMC_CONFIG1_DEVICETYPE(0x2) +#defineGPMC_CONFIG1_WAIT_PIN_SEL_MASK GPMC_CONFIG1_WAIT_PIN_SEL(0x3) +#defineGPMC_CONFIG1_WAIT_MON_TIME(val) ((val 0x3) 18) +#defineGPMC_CONFIG1_WRITEMULTIPLE BIT(28) +#defineGPMC_CONFIG1_READMULTIPLE BIT(30) +#defineGPMC_CONFIG1_WRAPBURST BIT(31) +#defineGPMC_CONFIG_WAITPIN_POLARITY_SHIFT 0x8 +#defineGPMC_CONFIG1_WAITPIN_MONITOR_TIME(val) ((val 0x3) 18) +#defineGPMC_CONFIG1_WAITPIN_MONITOR_TIME_1 \ + GPMC_CONFIG1_WAITPIN_MONITOR_TIME(0x1) +#defineGPMC_CONFIG1_WAITPIN_MONITOR_TIME_2 \ + GPMC_CONFIG1_WAITPIN_MONITOR_TIME(0x2) +#defineGPMC_CONFIG1_CLOCKACTIVATION_TIME(val) ((val 0x3) 25) +#defineGPMC_CONFIG1_CLOCKACTIVATION_TIME_1 \ + GPMC_CONFIG1_CLOCKACTIVATION_TIME(0x1) +#defineGPMC_CONFIG1_CLOCKACTIVATION_TIME_2 \ + GPMC_CONFIG1_CLOCKACTIVATION_TIME(0x2) + +#defineGPMC_CONFIG2_CSEXTRADELAY BIT(7) + +#defineGPMC_CONFIG3_ADVEXTRADELAY BIT(7) + +#defineGPMC_CONFIG4_OEEXTRADELAY BIT(7) +#defineGPMC_CONFIG4_WEEXTRADELAY BIT(23) + +#defineGPMC_CONFIG6_CYCLE2CYCLEDIFFCSENBIT(6) +#defineGPMC_CONFIG6_CYCLE2CYCLESAMECSENBIT(7) + +#define
[PATCH 03/39] ARM: OMAP2+: gpmc: register details for nand driver
If peripheral connected is NAND, update NAND drivers platform data with NAND related register addresses so that NAND driver can handle GPMC NAND operations by itself Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 25 + arch/arm/plat-omap/include/plat/gpmc.h | 16 arch/arm/plat-omap/include/plat/nand.h |1 + 3 files changed, 42 insertions(+) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index c8d07bb..657ce95 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -30,6 +30,7 @@ #include asm/mach-types.h #include plat/gpmc.h +#include plat/nand.h #include plat/sdrc.h @@ -891,6 +892,28 @@ static int __init gpmc_init(void) } postcore_initcall(gpmc_init); +static __devinit void gpmc_update_nand_reg(struct gpmc *gpmc, + struct omap_nand_platform_data *nand) +{ + int cs = nand-cs; + + nand-reg.gpmc_status = gpmc-io_base + GPMC_STATUS; + nand-reg.gpmc_nand_command = gpmc-io_base + GPMC_CS0_OFFSET + + GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs; + nand-reg.gpmc_nand_address = gpmc-io_base + GPMC_CS0_OFFSET + + GPMC_CS_NAND_ADDRESS + GPMC_CS_SIZE * cs; + nand-reg.gpmc_nand_data = gpmc-io_base + GPMC_CS0_OFFSET + + GPMC_CS_NAND_DATA + GPMC_CS_SIZE * cs; + nand-reg.gpmc_prefetch_config1 = gpmc-io_base + GPMC_PREFETCH_CONFIG1; + nand-reg.gpmc_prefetch_config2 = gpmc-io_base + GPMC_PREFETCH_CONFIG2; + nand-reg.gpmc_prefetch_control = gpmc-io_base + GPMC_PREFETCH_CONTROL; + nand-reg.gpmc_prefetch_status = gpmc-io_base + GPMC_PREFETCH_STATUS; + nand-reg.gpmc_ecc_config = gpmc-io_base + GPMC_ECC_CONFIG; + nand-reg.gpmc_ecc_control = gpmc-io_base + GPMC_ECC_CONTROL; + nand-reg.gpmc_ecc_size_config = gpmc-io_base + GPMC_ECC_SIZE_CONFIG; + nand-reg.gpmc_ecc1_result = gpmc-io_base + GPMC_ECC1_RESULT; +} + static inline int gpmc_waitpin_is_reserved(struct gpmc *gpmc, unsigned waitpin) { return gpmc-waitpin_map (0x1 waitpin); @@ -1427,6 +1450,8 @@ static __devinit int gpmc_probe(struct platform_device *pdev) for (i = 0, gdq = gp-device_pdata, gd = gpmc-device; (i gp-num_device) (*gdq); i++, gdq++) { + if ((*gdq)-is_nand) + gpmc_update_nand_reg(gpmc, (*gdq)-pdata); ret = gpmc_setup_device(gpmc, gd, *gdq); if (IS_ERR_VALUE(ret)) dev_err(gpmc-dev, gpmc setup on %s failed\n, diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index c5cf020..976a8f0 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -207,6 +207,7 @@ struct gpmc_device_pdata { unsignedper_res_cnt; struct gpmc_cs_data *cs_data; unsignednum_cs; + boolis_nand; }; struct gpmc_pdata { @@ -216,6 +217,21 @@ struct gpmc_pdata { struct gpmc_device_pdata**device_pdata; }; +struct gpmc_nand_regs { + void __iomem*gpmc_status; + void __iomem*gpmc_nand_command; + void __iomem*gpmc_nand_address; + void __iomem*gpmc_nand_data; + void __iomem*gpmc_prefetch_config1; + void __iomem*gpmc_prefetch_config2; + void __iomem*gpmc_prefetch_control; + void __iomem*gpmc_prefetch_status; + void __iomem*gpmc_ecc_config; + void __iomem*gpmc_ecc_control; + void __iomem*gpmc_ecc_size_config; + void __iomem*gpmc_ecc1_result; +}; + extern int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs); extern int omap_init_gpmc(struct gpmc_pdata *pdata); diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h index 67fc506..86e4d9c 100644 --- a/arch/arm/plat-omap/include/plat/nand.h +++ b/arch/arm/plat-omap/include/plat/nand.h @@ -29,6 +29,7 @@ struct omap_nand_platform_data { unsigned long phys_base; int devsize; enum omap_ecc ecc_opt; + struct gpmc_nand_regs reg; }; /* minimum size for IO mapping */ -- 1.7.10 -- 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 04/39] ARM: OMAP2+: gpmc: Acquire NAND CS value
Some boards depend on bootloader to update chip select value for NAND. It is felt that Kernel should not depend on bootloader to get CS, as for a particular board CS is hardwired and is fixed, hence this can directly be updated in Kernel. But as CS value for boards that depend on this behaviour is not available, educate gpmc driver to acquire chip select value for NAND. this ideally should be removed once CS for those boards are available. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 32 +++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 657ce95..ecd3384 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -892,6 +892,30 @@ static int __init gpmc_init(void) } postcore_initcall(gpmc_init); +static __devinit int gpmc_acquire_nand_cs(struct gpmc *gpmc, + struct gpmc_device_pdata *gdp) +{ + int cs = 0; + struct omap_nand_platform_data *nand = gdp-pdata; + + if ((nand-cs = 0) (nand-cs GPMC_CS_NUM)) + return 0; + + while (cs GPMC_CS_NUM) { + u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + + if ((l GPMC_CONFIG1_DEVICETYPE(~0)) == + GPMC_CONFIG1_DEVICETYPE_NAND) { + dev_info(gpmc-dev, found NAND on CS: %d\n, cs); + nand-cs = cs; + gdp-cs_data-cs = cs; + return 0; + } + cs++; + } + return -ENODEV; +} + static __devinit void gpmc_update_nand_reg(struct gpmc *gpmc, struct omap_nand_platform_data *nand) { @@ -1450,8 +1474,14 @@ static __devinit int gpmc_probe(struct platform_device *pdev) for (i = 0, gdq = gp-device_pdata, gd = gpmc-device; (i gp-num_device) (*gdq); i++, gdq++) { - if ((*gdq)-is_nand) + if ((*gdq)-is_nand) { + ret = gpmc_acquire_nand_cs(gpmc, *gdq); + if (IS_ERR_VALUE(ret)) { + dev_err(gpmc-dev, CS error: %d\n, ret); + continue; + } gpmc_update_nand_reg(gpmc, (*gdq)-pdata); + } ret = gpmc_setup_device(gpmc, gd, *gdq); if (IS_ERR_VALUE(ret)) dev_err(gpmc-dev, gpmc setup on %s failed\n, -- 1.7.10 -- 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 05/39] ARM: OMAP2+: nand: create platform data structure
New API for updating nand platform data. This has been created by unifying the two existing ones and taking out gpmc hardware handling. From now on, platforms can call omap_nand_init to initialize platform nand structures, it's fields. Or can statically create the same. Acquiring gpmc CS for has been removed. Acquiring CS is done in GPMC driver. To leverage this feature, pass CS # as any value outside the allowed range of 0 - 7 (this is valid only for connected NAND), eg. GPMC_CS_NUM (8) Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-devkit8000.c |6 ++- arch/arm/mach-omap2/board-flash.c | 61 ++-- arch/arm/mach-omap2/board-flash.h | 13 -- arch/arm/mach-omap2/board-ldp.c|4 +- arch/arm/mach-omap2/board-omap3beagle.c|6 ++- arch/arm/mach-omap2/board-omap3touchbook.c |6 ++- arch/arm/mach-omap2/board-overo.c |5 ++- arch/arm/mach-omap2/board-zoom.c |5 ++- arch/arm/mach-omap2/common-board-devices.c | 46 - arch/arm/mach-omap2/common-board-devices.h |1 - 10 files changed, 60 insertions(+), 93 deletions(-) diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index a2010f0..aa352d1 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -59,6 +59,7 @@ #include mux.h #include hsmmc.h +#include board-flash.h #include common-board-devices.h #define OMAP_DM9000_GPIO_IRQ 25 @@ -648,8 +649,9 @@ static void __init devkit8000_init(void) usb_musb_init(NULL); usbhs_init(usbhs_bdata); - omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions, -ARRAY_SIZE(devkit8000_nand_partitions)); + board_nand_init(devkit8000_nand_partitions, + ARRAY_SIZE(devkit8000_nand_partitions), GPMC_CS_NUM, + NAND_BUSWIDTH_16, NULL); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal(sdrc_cke0, OMAP_PIN_OUTPUT); diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index 0349fd2..091aaf6 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -108,45 +108,45 @@ __init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs) defined(CONFIG_MTD_NAND_OMAP2_MODULE) /* Note that all values in this struct are in nanoseconds */ -static struct gpmc_timings nand_timings = { +struct gpmc_timings nand_default_timings[1] = { + { + .sync_clk = 0, - .sync_clk = 0, + .cs_on = 0, + .cs_rd_off = 36, + .cs_wr_off = 36, - .cs_on = 0, - .cs_rd_off = 36, - .cs_wr_off = 36, + .adv_on = 6, + .adv_rd_off = 24, + .adv_wr_off = 36, - .adv_on = 6, - .adv_rd_off = 24, - .adv_wr_off = 36, + .we_off = 30, + .oe_off = 48, - .we_off = 30, - .oe_off = 48, + .access = 54, + .rd_cycle = 72, + .wr_cycle = 72, - .access = 54, - .rd_cycle = 72, - .wr_cycle = 72, - - .wr_access = 30, - .wr_data_mux_bus = 0, + .wr_access = 30, + .wr_data_mux_bus = 0, + }, }; -static struct omap_nand_platform_data board_nand_data = { - .gpmc_t = nand_timings, +static struct omap_nand_platform_data omap_nand_data = { + .gpmc_t = nand_default_timings, }; -void -__init board_nand_init(struct mtd_partition *nand_parts, - u8 nr_parts, u8 cs, int nand_type) +struct omap_nand_platform_data * +__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs, + int nand_type, struct gpmc_timings *gpmc_t) { - board_nand_data.cs = cs; - board_nand_data.parts = nand_parts; - board_nand_data.nr_parts= nr_parts; - board_nand_data.devsize = nand_type; - - board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT; - board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs; - gpmc_nand_init(board_nand_data); + omap_nand_data.cs = cs; + omap_nand_data.parts= nand_parts; + omap_nand_data.nr_parts = nr_parts; + omap_nand_data.devsize = nand_type; + omap_nand_data.gpmc_t = gpmc_t; + + return omap_nand_data; } #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */ @@ -243,5 +243,6 @@ void __init board_flash_init(struct flash_partitions partition_info[], pr_err(NAND: Unable to find configuration in GPMC\n); else board_nand_init(partition_info[2].parts, - partition_info[2].nr_parts, nandcs, nand_type
[PATCH 06/39] ARM: OMAP2+: onenand: return value in init function
Modify board_onenand_init to return platform data. This would be required for boards to be able to pass it to gpmc driver so that it finally reaches onenand driver. Also un-static the function so that boards can use it. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-flash.c | 14 -- arch/arm/mach-omap2/board-flash.h | 12 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index 091aaf6..8727c05 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -87,22 +87,16 @@ static struct omap_onenand_platform_data board_onenand_data = { .dma_channel= -1, /* disable DMA in OMAP OneNAND driver */ }; -static void -__init board_onenand_init(struct mtd_partition *onenand_parts, - u8 nr_parts, u8 cs) +struct omap_onenand_platform_data * __init +board_onenand_init(struct mtd_partition *onenand_parts, u8 nr_parts, u8 cs) { board_onenand_data.cs = cs; board_onenand_data.parts= onenand_parts; board_onenand_data.nr_parts = nr_parts; - gpmc_onenand_init(board_onenand_data); -} -#else -static void -__init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs) -{ + return board_onenand_data; } -#endif /* CONFIG_MTD_ONENAND_OMAP2 || CONFIG_MTD_ONENAND_OMAP2_MODULE */ +#endif #if defined(CONFIG_MTD_NAND_OMAP2) || \ defined(CONFIG_MTD_NAND_OMAP2_MODULE) diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h index 052964c..75ba49f 100644 --- a/arch/arm/mach-omap2/board-flash.h +++ b/arch/arm/mach-omap2/board-flash.h @@ -52,3 +52,15 @@ board_nand_init(struct mtd_partition *nand_parts, return NULL; } #endif + +#if defined(CONFIG_MTD_ONENAND_OMAP2) || \ + defined(CONFIG_MTD_ONENAND_OMAP2_MODULE) +extern struct omap_onenand_platform_data * __init +board_onenand_init(struct mtd_partition *onenand_parts, u8 nr_parts, u8 cs); +#else +static inline struct omap_onenand_platform_data * +__init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs) +{ + return NULL; +} +#endif -- 1.7.10 -- 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 07/39] ARM: OMAP2+: gpmc-nand: Adapt to use gpmc driver
Currently gpmc is configured in platform for nand. As configuring gpmc has been moved to gpmc driver, populate details needed for the driver to configure gpmc. gpmc driver would configure based on this information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc-nand.c| 84 arch/arm/plat-omap/include/plat/nand.h |8 +-- 2 files changed, 35 insertions(+), 57 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index 386dec8..190cdc1 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -21,24 +21,30 @@ #include plat/board.h #include plat/gpmc.h -static struct resource gpmc_nand_resource = { - .flags = IORESOURCE_MEM, + +static struct gpmc_cs_data gpmc_nand_cs_info = { + .have_config= true, + .config = GPMC_DEVICETYPE_NAND, + .irq_config = GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT, }; -static struct platform_device gpmc_nand_device = { +static struct gpmc_device_pdata gpmc_nand_info = { .name = omap2-nand, .id = 0, - .num_resources = 1, - .resource = gpmc_nand_resource, + .cs_data= gpmc_nand_cs_info, + .num_cs = 1, + .is_nand= true, }; -static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data) -{ - struct gpmc_timings t; - int err; +static struct gpmc_timings t; - if (!gpmc_nand_data-gpmc_t) +static struct gpmc_timings * +gpmc_nand_retime(struct omap_nand_platform_data *gpmc_nand_data) +{ + if (!gpmc_nand_data-gpmc_t) { + pr_warn(gpmc timings not provided\n); return 0; + } memset(t, 0, sizeof(t)); t.sync_clk = gpmc_nand_data-gpmc_t-sync_clk; @@ -68,56 +74,26 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_nand_data-gpmc_t-cs_wr_off); t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data-gpmc_t-wr_cycle); - /* Configure GPMC */ - if (gpmc_nand_data-devsize == NAND_BUSWIDTH_16) - gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_DEV_SIZE, 1); - else - gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_DEV_SIZE, 0); - gpmc_cs_configure(gpmc_nand_data-cs, - GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND); - err = gpmc_cs_set_timings(gpmc_nand_data-cs, t); - if (err) - return err; - - return 0; + return t; } -int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) +struct gpmc_device_pdata * +__init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) { - int err = 0; - struct device *dev = gpmc_nand_device.dev; + gpmc_nand_info.pdata = gpmc_nand_data; + gpmc_nand_info.pdata_size = sizeof(*gpmc_nand_data); - gpmc_nand_device.dev.platform_data = gpmc_nand_data; + gpmc_nand_cs_info.cs = gpmc_nand_data-cs; + gpmc_nand_cs_info.mem_size = NAND_IO_SIZE; - err = gpmc_cs_request(gpmc_nand_data-cs, NAND_IO_SIZE, - gpmc_nand_data-phys_base); - if (err 0) { - dev_err(dev, Cannot request GPMC CS\n); - return err; - } + gpmc_nand_cs_info.timing = gpmc_nand_retime(gpmc_nand_data); -/* Set timings in GPMC */ - err = omap2_nand_gpmc_retime(gpmc_nand_data); - if (err 0) { - dev_err(dev, Unable to set gpmc timings: %d\n, err); - return err; - } - - /* Enable RD PIN Monitoring Reg */ - if (gpmc_nand_data-dev_ready) { - gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_RDY_BSY, 1); - } - - err = platform_device_register(gpmc_nand_device); - if (err 0) { - dev_err(dev, Unable to register NAND device\n); - goto out_free_cs; - } - - return 0; + if (gpmc_nand_data-devsize == NAND_BUSWIDTH_16) + gpmc_nand_cs_info.config |= GPMC_DEVICESIZE_16; -out_free_cs: - gpmc_cs_free(gpmc_nand_data-cs); + if (gpmc_nand_data-dev_ready) + gpmc_nand_cs_info.config |= GPMC_WAIT_READ_MON | + GPMC_WAIT_WRITE_MON; - return err; + return gpmc_nand_info; } diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h index 86e4d9c..30c61c9 100644 --- a/arch/arm/plat-omap/include/plat/nand.h +++ b/arch/arm/plat-omap/include/plat/nand.h @@ -36,10 +36,12 @@ struct omap_nand_platform_data { #defineNAND_IO_SIZE4 #if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE) -extern int gpmc_nand_init(struct omap_nand_platform_data *d); +extern struct gpmc_device_pdata * +gpmc_nand_init(struct
[PATCH 08/39] ARM: OMAP2+: gpmc-onenand: Adapt to use gpmc driver
Currently gpmc is configured in platform for onenand. As configuring gpmc has been moved to gpmc driver, populate details needed for the driver to configure gpmc. gpmc driver would configure based on this information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc-onenand.c| 111 +++-- arch/arm/plat-omap/include/plat/onenand.h |7 +- 2 files changed, 61 insertions(+), 57 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index a0fa9bb..d7775d5 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -25,9 +25,17 @@ static struct omap_onenand_platform_data *gpmc_onenand_data; -static struct platform_device gpmc_onenand_device = { +#define ONENAND_IO_SIZESZ_128K + +static struct gpmc_cs_data gpmc_onenand_cs_info = { + .mem_size = ONENAND_IO_SIZE, +}; + +static struct gpmc_device_pdata gpmc_onenand_info = { .name = omap2-onenand, .id = -1, + .cs_data= gpmc_onenand_cs_info, + .num_cs = 1, }; static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) @@ -79,13 +87,17 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez); /* Configure GPMC for asynchronous read */ - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, - GPMC_CONFIG1_DEVICESIZE_16 | - GPMC_CONFIG1_MUXADDDATA); - - err = gpmc_cs_set_timings(cs, t); - if (err) + gpmc_onenand_cs_info.have_config = true; + gpmc_onenand_cs_info.config = GPMC_DEVICESIZE_16 | + GPMC_MUXADDDATA | + GPMC_DEVICETYPE_NOR; + gpmc_onenand_cs_info.timing = t; + err = gpmc_cs_reconfigure(gpmc_onenand_info.name, + gpmc_onenand_info.id, gpmc_onenand_cs_info); + if (err) { + pr_err(%s: gpmc_cs_reconfigure failed\n, __func__); return err; + } /* Ensure sync read and sync write are disabled */ reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); @@ -180,7 +192,6 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, int first_time = 0, hf = 0, vhf = 0, sync_read = 0, sync_write = 0; int err, ticks_cez; int cs = cfg-cs, freq = *freq_ptr; - u32 reg; bool clk_dep = false; if (cfg-flags ONENAND_SYNC_READ) { @@ -276,27 +287,10 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, sync_read, sync_write, hf, vhf); if (div == 1) { - reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2); - reg |= (1 7); - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg); - reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3); - reg |= (1 7); - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg); - reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4); - reg |= (1 7); - reg |= (1 23); - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg); - } else { - reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2); - reg = ~(1 7); - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg); - reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3); - reg = ~(1 7); - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg); - reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4); - reg = ~(1 7); - reg = ~(1 23); - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg); + t.control.cs_extra_delay = true; + t.control.adv_extra_delay = true; + t.control.oe_extra_delay = true; + t.control.we_extra_delay = true; } /* Set synchronous read timings */ @@ -348,24 +342,31 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, } /* Configure GPMC for synchronous read */ - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, - GPMC_CONFIG1_WRAPBURST_SUPP | - GPMC_CONFIG1_READMULTIPLE_SUPP | - (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) | - (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) | - (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) | - GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) | - GPMC_CONFIG1_PAGE_LEN(2) | - (cpu_is_omap34xx() ? 0 : - (GPMC_CONFIG1_WAIT_READ_MON | -GPMC_CONFIG1_WAIT_PIN_SEL(0
[PATCH 09/39] ARM: OMAP2+: flash: Adapt to gpmc driver
gpmc driver has been converted to driver. Modify board_flash_init so that it can setup gpmc driver platform details for boards Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-3430sdp.c |2 +- arch/arm/mach-omap2/board-3630sdp.c |3 +- arch/arm/mach-omap2/board-flash.c | 89 +++ arch/arm/mach-omap2/board-flash.h | 11 +++-- 4 files changed, 58 insertions(+), 47 deletions(-) diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index da75f23..ac2e398 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -620,7 +620,7 @@ static void __init omap_3430sdp_init(void) omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL); usb_musb_init(NULL); board_smc91x_init(); - board_flash_init(sdp_flash_partitions, chip_sel_3430, 0); + board_flash_init(sdp_flash_partitions, chip_sel_3430, 0, NULL); sdp3430_display_init(); enable_board_wakeup_source(); usbhs_init(usbhs_bdata); diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c index 6ef350d..74195b7 100644 --- a/arch/arm/mach-omap2/board-3630sdp.c +++ b/arch/arm/mach-omap2/board-3630sdp.c @@ -204,7 +204,8 @@ static void __init omap_sdp_init(void) h8mbx00u0mer0em_sdrc_params); zoom_display_init(); board_smc91x_init(); - board_flash_init(sdp_flash_partitions, chip_sel_sdp, NAND_BUSWIDTH_16); + board_flash_init(sdp_flash_partitions, chip_sel_sdp, + NAND_BUSWIDTH_16, NULL); enable_board_wakeup_source(); usbhs_init(usbhs_bdata); } diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index 8727c05..8deead9 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -39,46 +39,33 @@ static struct physmap_flash_data board_nor_data = { .width = 2, }; -static struct resource board_nor_resource = { - .flags = IORESOURCE_MEM, +static struct gpmc_cs_data gpmc_nor_cs_data = { }; -static struct platform_device board_nor_device = { +static struct gpmc_device_pdata gpmc_nor_data = { .name = physmap-flash, .id = 0, - .dev= { - .platform_data = board_nor_data, - }, - .num_resources = 1, - .resource = board_nor_resource, + .cs_data= gpmc_nor_cs_data, + .num_cs = 1, }; -static void -__init board_nor_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs) +static __init struct gpmc_device_pdata * +gpmc_nor_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs) { - int err; - board_nor_data.parts= nor_parts; board_nor_data.nr_parts = nr_parts; - /* Configure start address and size of NOR device */ - if (omap_rev() = OMAP3430_REV_ES1_0) { - err = gpmc_cs_request(cs, FLASH_SIZE_SDPV2 - 1, - (unsigned long *)board_nor_resource.start); - board_nor_resource.end = board_nor_resource.start - + FLASH_SIZE_SDPV2 - 1; - } else { - err = gpmc_cs_request(cs, FLASH_SIZE_SDPV1 - 1, - (unsigned long *)board_nor_resource.start); - board_nor_resource.end = board_nor_resource.start - + FLASH_SIZE_SDPV1 - 1; - } - if (err 0) { - pr_err(NOR: Can't request GPMC CS\n); - return; - } - if (platform_device_register(board_nor_device) 0) - pr_err(Unable to register NOR device\n); + gpmc_nor_cs_data.cs = cs; + + if (omap_rev() = OMAP3430_REV_ES1_0) + gpmc_nor_cs_data.mem_size = FLASH_SIZE_SDPV2; + else + gpmc_nor_cs_data.mem_size = FLASH_SIZE_SDPV1; + + gpmc_nor_data.pdata = board_nor_data; + gpmc_nor_data.pdata_size = sizeof(board_nor_data); + + return gpmc_nor_data; } #if defined(CONFIG_MTD_ONENAND_OMAP2) || \ @@ -183,8 +170,11 @@ unmap: * * @return - void. */ -void __init board_flash_init(struct flash_partitions partition_info[], - char chip_sel_board[][GPMC_CS_NUM], int nand_type) +__init struct gpmc_device_pdata **board_flash_init( + struct flash_partitions partition_info[], + char chip_sel_board[][GPMC_CS_NUM], + int nand_type, + struct gpmc_device_pdata **gpmc_data) { u8 cs = 0; u8 norcs = GPMC_CS_NUM + 1; @@ -193,13 +183,18 @@ void __init board_flash_init(struct flash_partitions partition_info[], u8 idx; unsigned char *config_sel = NULL; + if (gpmc_data
[PATCH 10/39] ARM: OMAP2+: gpmc-smsc911x: Adapt to use gpmc driver
gpmc has been converted to driver. And all gpmc related configuration would be done by gpmc driver. Provide gpmc driver with sufficient information so that it can configure. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc-smsc911x.c | 59 --- arch/arm/plat-omap/include/plat/gpmc-smsc911x.h |9 +++- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-smsc911x.c b/arch/arm/mach-omap2/gpmc-smsc911x.c index b6c77be..2c89685 100644 --- a/arch/arm/mach-omap2/gpmc-smsc911x.c +++ b/arch/arm/mach-omap2/gpmc-smsc911x.c @@ -24,13 +24,8 @@ #include plat/gpmc.h #include plat/gpmc-smsc911x.h -static struct resource gpmc_smsc911x_resources[] = { - [0] = { - .flags = IORESOURCE_MEM, - }, - [1] = { - .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, - }, +static struct resource gpmc_smsc911x_resources = { + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, }; static struct smsc911x_platform_config gpmc_smsc911x_config = { @@ -44,26 +39,42 @@ static struct smsc911x_platform_config gpmc_smsc911x_config = { * assume that pin multiplexing is done in the board-*.c file, * or in the bootloader. */ -void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg) +__init struct gpmc_device_pdata * +gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg) { - struct platform_device *pdev; - unsigned long cs_mem_base; int ret; + struct gpmc_device_pdata *gpmc_pdev; + struct gpmc_cs_data *gpmc_cs; - if (gpmc_cs_request(gpmc_cfg-cs, SZ_16M, cs_mem_base) 0) { - pr_err(Failed to request GPMC mem region\n); - return; + gpmc_pdev = kzalloc(sizeof(*gpmc_pdev), GFP_KERNEL); + if (gpmc_pdev == NULL) + return gpmc_pdev; + + gpmc_cs = kzalloc(sizeof(*gpmc_cs), GFP_KERNEL); + if (gpmc_pdev == NULL) { + kfree(gpmc_pdev); + return NULL; } - gpmc_smsc911x_resources[0].start = cs_mem_base + 0x0; - gpmc_smsc911x_resources[0].end = cs_mem_base + 0xff; + gpmc_pdev-cs_data = gpmc_cs; + gpmc_pdev-num_cs = 1; + gpmc_pdev-name = smsc911x; + gpmc_pdev-id = gpmc_cfg-id; + gpmc_pdev-pdata = gpmc_smsc911x_config; + gpmc_pdev-pdata_size = sizeof(gpmc_smsc911x_config); + + gpmc_cs-cs = gpmc_cfg-cs; + gpmc_cs-mem_size = 0x100; + + gpmc_pdev-per_res = gpmc_smsc911x_resources; + gpmc_pdev-per_res_cnt = 1; if (gpio_request_one(gpmc_cfg-gpio_irq, GPIOF_IN, smsc911x irq)) { pr_err(Failed to request IRQ GPIO%d\n, gpmc_cfg-gpio_irq); goto free1; } - gpmc_smsc911x_resources[1].start = gpio_to_irq(gpmc_cfg-gpio_irq); + gpmc_smsc911x_resources.start = gpio_to_irq(gpmc_cfg-gpio_irq); if (gpio_is_valid(gpmc_cfg-gpio_reset)) { ret = gpio_request_one(gpmc_cfg-gpio_reset, @@ -81,21 +92,15 @@ void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg) gpmc_smsc911x_config.flags = gpmc_cfg-flags ? : SMSC911X_USE_16BIT; - pdev = platform_device_register_resndata(NULL, smsc911x, gpmc_cfg-id, -gpmc_smsc911x_resources, ARRAY_SIZE(gpmc_smsc911x_resources), -gpmc_smsc911x_config, sizeof(gpmc_smsc911x_config)); - if (!pdev) { - pr_err(Unable to register platform device\n); - gpio_free(gpmc_cfg-gpio_reset); - goto free2; - } - - return; + return gpmc_pdev; free2: gpio_free(gpmc_cfg-gpio_irq); free1: - gpmc_cs_free(gpmc_cfg-cs); + kfree(gpmc_cs); + kfree(gpmc_pdev); pr_err(Could not initialize smsc911x device\n); + + return NULL; } diff --git a/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h b/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h index ea6c9c8..66dc7f1 100644 --- a/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h +++ b/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h @@ -11,6 +11,8 @@ * published by the Free Software Foundation. */ +#includeplat/gpmc.h + #ifndef __ASM_ARCH_OMAP_GPMC_SMSC911X_H__ struct omap_smsc911x_platform_data { @@ -23,12 +25,15 @@ struct omap_smsc911x_platform_data { #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) -extern void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d); +extern struct gpmc_device_pdata * +gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d); #else -static inline void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d) +static inline struct gpmc_device_pdata * +gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d) { + return NULL; } #endif -- 1.7.10 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord
[PATCH 11/39] ARM: OMAP2+: gpmc-smc91x: Adapt to use gpmc driver
Currently gpmc is configured in platform for smc91x. As configuring gpmc has been moved to gpmc driver, populate details needed for the driver to configure gpmc. gpmc driver would configure based on this information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-2430sdp.c |2 +- arch/arm/mach-omap2/board-3430sdp.c |1 + arch/arm/mach-omap2/board-3630sdp.c |1 + arch/arm/mach-omap2/gpmc-smc91x.c | 87 +++-- arch/arm/plat-omap/include/plat/gpmc-smc91x.h | 10 ++- 5 files changed, 47 insertions(+), 54 deletions(-) diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index e658f83..68679a8 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -175,7 +175,7 @@ static struct omap_smc91x_platform_data board_smc91x_data = { .gpio_irq = 149, .flags = GPMC_MUX_ADD_DATA | GPMC_TIMINGS_SMC91C96 | IORESOURCE_IRQ_LOWLEVEL, - + .skip_timing= true, }; static void __init board_smc91x_init(void) diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index ac2e398..367a466 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -434,6 +434,7 @@ static struct omap_smc91x_platform_data board_smc91x_data = { .cs = 3, .flags = GPMC_MUX_ADD_DATA | GPMC_TIMINGS_SMC91C96 | IORESOURCE_IRQ_LOWLEVEL, + .skip_timing= true, }; static void __init board_smc91x_init(void) diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c index 74195b7..143e47f 100644 --- a/arch/arm/mach-omap2/board-3630sdp.c +++ b/arch/arm/mach-omap2/board-3630sdp.c @@ -32,6 +32,7 @@ static struct omap_smc91x_platform_data board_smc91x_data = { .cs = 3, .flags = GPMC_MUX_ADD_DATA | IORESOURCE_IRQ_LOWLEVEL, + .skip_timing= true, }; static void __init board_smc91x_init(void) diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c index ba10c24..9389df1 100644 --- a/arch/arm/mach-omap2/gpmc-smc91x.c +++ b/arch/arm/mach-omap2/gpmc-smc91x.c @@ -23,13 +23,8 @@ static struct omap_smc91x_platform_data *gpmc_cfg; -static struct resource gpmc_smc91x_resources[] = { - [0] = { - .flags = IORESOURCE_MEM, - }, - [1] = { - .flags = IORESOURCE_IRQ, - }, +static struct resource gpmc_smc91x_resource = { + .flags = IORESOURCE_IRQ, }; static struct smc91x_platdata gpmc_smc91x_info = { @@ -38,14 +33,17 @@ static struct smc91x_platdata gpmc_smc91x_info = { .ledb = RPC_LED_TX_RX, }; -static struct platform_device gpmc_smc91x_device = { +static struct gpmc_cs_data gpmc_smc91x_cs_data; + +static struct gpmc_device_pdata gpmc_smc91x_data = { .name = smc91x, .id = -1, - .dev= { - .platform_data = gpmc_smc91x_info, - }, - .num_resources = ARRAY_SIZE(gpmc_smc91x_resources), - .resource = gpmc_smc91x_resources, + .pdata = gpmc_smc91x_info, + .pdata_size = sizeof(gpmc_smc91x_info), + .per_res= gpmc_smc91x_resource, + .per_res_cnt= 1, + .cs_data= gpmc_smc91x_cs_data, + .num_cs = 1, }; /* @@ -54,9 +52,10 @@ static struct platform_device gpmc_smc91x_device = { * http://www.smsc.com/main/catalog/lan91c96.html * REVISIT: Level shifters can add at least to the access latency. */ -static int smc91c96_gpmc_retime(void) +static void smc91c96_gpmc_retime(void) { - struct gpmc_timings t; + /* GPMC timing configuration after this function dies, hence static */ + static struct gpmc_timings t; const int t3 = 10; /* Figure 12.2 read and 12.4 write */ const int t4_r = 20;/* Figure 12.2 read */ const int t4_w = 5; /* Figure 12.4 write */ @@ -65,7 +64,6 @@ static int smc91c96_gpmc_retime(void) const int t7 = 5; /* Figure 12.4 write */ const int t8 = 5; /* Figure 12.4 write */ const int t20 = 185;/* Figure 12.2 read and 12.4 write */ - u32 l; memset(t, 0, sizeof(t)); @@ -93,16 +91,17 @@ static int smc91c96_gpmc_retime(void) t.cs_wr_off = t.we_off + t4_w; t.wr_cycle = t20 - t.we_on; - l = GPMC_CONFIG1_DEVICESIZE_16; + gpmc_smc91x_cs_data.have_config = true; + gpmc_smc91x_cs_data.config = GPMC_DEVICESIZE_16; if (gpmc_cfg-flags GPMC_MUX_ADD_DATA) - l |= GPMC_CONFIG1_MUXADDDATA; + gpmc_smc91x_cs_data.config |= GPMC_MUXADDDATA; if (gpmc_cfg-flags GPMC_READ_MON) - l |= GPMC_CONFIG1_WAIT_READ_MON
[PATCH 12/39] ARM: OMAP2+: gpmc-tusb6010: Adapt to gpmc driver
Currently gpmc is configured in platform for tusb6010. As configuring gpmc has been moved to gpmc driver, populate details needed for the driver to configure gpmc. gpmc driver would configure based on this information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/usb-tusb6010.c | 177 ++-- include/linux/usb/musb.h |4 +- 2 files changed, 70 insertions(+), 111 deletions(-) diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c index db84a46..d7817d2 100644 --- a/arch/arm/mach-omap2/usb-tusb6010.c +++ b/arch/arm/mach-omap2/usb-tusb6010.c @@ -22,6 +22,24 @@ #include mux.h +static struct resource tusb_resources = { + .name = mc, + .flags = IORESOURCE_IRQ, +}; + +#defineTUSB_GPMC_CS_ASYNC_IDX 1 +#defineTUSB_GPMC_CS_SYNC_IDX 2 +#defineTUSB_GPMC_CS_NUM2 + +static struct gpmc_cs_data gpmc_tusb_cs_data[TUSB_GPMC_CS_NUM]; + +static struct gpmc_device_pdata gpmc_tusb_data = { + .name = musb-tusb, + .id = -1, + .per_res= tusb_resources, + .per_res_cnt= 1, +}; + static u8 async_cs, sync_cs; static unsignedrefclk_psec; @@ -51,9 +69,9 @@ next_clk(unsigned t1_NS, unsigned t2_ps, unsigned fclk_ps) /* NOTE: timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */ -static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps) +static void tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps) { - struct gpmc_timings t; + static struct gpmc_timings t; unsignedt_acsnh_advnh = sysclk_ps + 3000; unsignedtmp; @@ -106,12 +124,12 @@ static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps) tmp = t.cs_wr_off * 1000 + 7000 /* t_acsn_rdy_z */; t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps); - return gpmc_cs_set_timings(async_cs, t); + gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].timing = t; } static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps) { - struct gpmc_timings t; + static struct gpmc_timings t; unsignedt_scsnh_advnh = sysclk_ps + 3000; unsignedtmp; @@ -174,71 +192,30 @@ static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps) tmp = t.cs_wr_off * 1000 + 7000 /* t_scsn_rdy_z */; t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps); - return gpmc_cs_set_timings(sync_cs, t); + gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].timing = t; + + return 0; } extern unsigned long gpmc_get_fclk_period(void); /* tusb driver calls this when it changes the chip's clocking */ -int tusb6010_platform_retime(unsigned is_refclk) +static int tusb6010_platform_retime(unsigned is_refclk) { - static const char error[] = - KERN_ERR tusb6010 %s retime error %d\n; - unsignedfclk_ps = gpmc_get_fclk_period(); unsignedsysclk_ps; - int status; if (!refclk_psec || fclk_ps == 0) return -ENODEV; sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60; - status = tusb_set_async_mode(sysclk_ps, fclk_ps); - if (status 0) { - printk(error, async, status); - goto done; - } - status = tusb_set_sync_mode(sysclk_ps, fclk_ps); - if (status 0) - printk(error, sync, status); -done: - return status; + tusb_set_async_mode(sysclk_ps, fclk_ps); + return tusb_set_sync_mode(sysclk_ps, fclk_ps); } -EXPORT_SYMBOL_GPL(tusb6010_platform_retime); - -static struct resource tusb_resources[] = { - /* Order is significant! The start/end fields -* are updated during setup.. -*/ - { /* Asynchronous access */ - .flags = IORESOURCE_MEM, - }, - { /* Synchronous access */ - .flags = IORESOURCE_MEM, - }, - { /* IRQ */ - .name = mc, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 tusb_dmamask = ~(u32)0; - -static struct platform_device tusb_device = { - .name = musb-tusb, - .id = -1, - .dev = { - .dma_mask = tusb_dmamask, - .coherent_dma_mask = 0x, - }, - .num_resources = ARRAY_SIZE(tusb_resources), - .resource = tusb_resources, -}; - /* this may be called only from board-*.c setup code */ -int __init +__init struct gpmc_device_pdata * tusb6010_setup_interface(struct musb_hdrc_platform_data *data, unsigned ps_refclk, unsigned waitpin, unsigned async, unsigned sync, @@ -249,82 +226,72 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data, KERN_ERR tusb6010 init error %d, %d\n
[PATCH 13/39] ARM: OMAP3: hwmod data: add gpmc
Add gpmc hwmod and associated interconnect data Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 52 1 file changed, 52 insertions(+) diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 0c65079..4da8394 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1981,6 +1981,40 @@ static struct omap_hwmod omap3xxx_usb_tll_hs_hwmod = { }; /* + * 'gpmc' class + * general purpose memory controller + */ + +static struct omap_hwmod_class_sysconfig omap3xxx_gpmc_sysc = { + .rev_offs = 0x, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE | + SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), + .sysc_fields= omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap3xxx_gpmc_hwmod_class = { + .name = gpmc, + .sysc = omap3xxx_gpmc_sysc, +}; + +static struct omap_hwmod_irq_info omap3xxx_gpmc_irqs[] = { + { .irq = 20 }, + { .irq = -1 } +}; + +static struct omap_hwmod omap3xxx_gpmc_hwmod = { + .name = gpmc, + .class = omap3xxx_gpmc_hwmod_class, + .clkdm_name = l3_init_clkdm, + .mpu_irqs = omap3xxx_gpmc_irqs, + .main_clk = gpmc_fck, + .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET, +}; + +/* * interfaces */ @@ -3059,6 +3093,23 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__usb_tll_hs = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +static struct omap_hwmod_addr_space omap3xxx_gpmc_addrs[] = { + { + .pa_start = 0x6E00, + .pa_end = 0x6E000FFF, + .flags = ADDR_TYPE_RT + }, + { } +}; + +static struct omap_hwmod_ocp_if omap3xxx_l3_main__gpmc = { + .master = omap3xxx_l3_main_hwmod, + .slave = omap3xxx_gpmc_hwmod, + .clk= core_l3_ick, + .addr = omap3xxx_gpmc_addrs, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = { omap3xxx_l3_main__l4_core, omap3xxx_l3_main__l4_per, @@ -3103,6 +3154,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = { omap34xx_l4_core__mcspi2, omap34xx_l4_core__mcspi3, omap34xx_l4_core__mcspi4, + omap3xxx_l3_main__gpmc, NULL, }; -- 1.7.10 -- 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 14/39] ARM: OMAP2xxx: hwmod data: add gpmc
Add gpmc hwmod and associated interconnect data Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/omap_hwmod_2420_data.c | 18 + arch/arm/mach-omap2/omap_hwmod_2430_data.c | 18 + arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c | 41 arch/arm/mach-omap2/omap_hwmod_common_data.h |1 + arch/arm/mach-omap2/prcm-common.h |2 + 5 files changed, 80 insertions(+) diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index 2c087ff..55c8c7b 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -428,6 +428,23 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__mcbsp2 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +static struct omap_hwmod_addr_space omap2420_gpmc_addrs[] = { + { + .pa_start = 0x6800A000, + .pa_end = 0x6800AFFF, + .flags = ADDR_TYPE_RT + }, + { } +}; + +static struct omap_hwmod_ocp_if omap2420_l3__gpmc = { + .master = omap2xxx_l3_main_hwmod, + .slave = omap2xxx_gpmc_hwmod, + .clk= core_l3_ck, + .addr = omap2420_gpmc_addrs, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = { omap2xxx_l3_main__l4_core, omap2xxx_mpu__l3_main, @@ -468,6 +485,7 @@ static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = { omap2420_l4_core__mailbox, omap2420_l4_core__mcbsp1, omap2420_l4_core__mcbsp2, + omap2420_l3__gpmc, NULL, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index 71d9f88..dd224cca 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -838,6 +838,23 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp5 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +static struct omap_hwmod_addr_space omap2430_gpmc_addrs[] = { + { + .pa_start = 0x6E00, + .pa_end = 0x6E000FFF, + .flags = ADDR_TYPE_RT + }, + { } +}; + +static struct omap_hwmod_ocp_if omap2430_l3__gpmc = { + .master = omap2xxx_l3_main_hwmod, + .slave = omap2xxx_gpmc_hwmod, + .clk= core_l3_ck, + .addr = omap2430_gpmc_addrs, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = { omap2xxx_l3_main__l4_core, omap2xxx_mpu__l3_main, @@ -886,6 +903,7 @@ static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = { omap2430_l4_core__mcbsp3, omap2430_l4_core__mcbsp4, omap2430_l4_core__mcbsp5, + omap2430_l3__gpmc, NULL, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c index 45aaa07..e75da40 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c @@ -175,6 +175,26 @@ struct omap_hwmod_class omap2xxx_mcspi_class = { }; /* + * 'gpmc' class + * general purpose memory controller + */ + +static struct omap_hwmod_class_sysconfig omap2xxx_gpmc_sysc = { + .rev_offs = 0x, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE | + SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), + .sysc_fields= omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap2xxx_gpmc_hwmod_class = { + .name = gpmc, + .sysc = omap2xxx_gpmc_sysc, +}; + +/* * IP blocks */ @@ -732,3 +752,24 @@ struct omap_hwmod omap2xxx_mcspi2_hwmod = { .class = omap2xxx_mcspi_class, .dev_attr = omap_mcspi2_dev_attr, }; + +/* gpmc */ +static struct omap_hwmod_irq_info omap2xxx_gpmc_irqs[] = { + { .irq = 20 }, + { .irq = -1 } +}; + +struct omap_hwmod omap2xxx_gpmc_hwmod = { + .name = gpmc, + .class = omap2xxx_gpmc_hwmod_class, + .mpu_irqs = omap2xxx_gpmc_irqs, + .main_clk = gpmc_fck, + .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET, + .prcm = { + .omap2 = { + .prcm_reg_id = 3, + .module_bit = OMAP24XX_EN_GPMC_MASK, + .module_offs = CORE_MOD, + }, + }, +}; diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.h b/arch/arm/mach-omap2/omap_hwmod_common_data.h index 7aa9156..63e0134
[PATCH 15/39] mtd: nand: omap2: obtain memory from resource
gpmc being converted to driver, provides drivers of peripheral connected memory space used by the peripheral as memory resource. Modify nand omap driver to obtain memory detials from resource structure. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/plat-omap/include/plat/nand.h |1 - drivers/mtd/nand/omap2.c | 20 ++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h index 30c61c9..570c4f4 100644 --- a/arch/arm/plat-omap/include/plat/nand.h +++ b/arch/arm/plat-omap/include/plat/nand.h @@ -26,7 +26,6 @@ struct omap_nand_platform_data { booldev_ready; int gpmc_irq; enum nand_ioxfer_type; - unsigned long phys_base; int devsize; enum omap_ecc ecc_opt; struct gpmc_nand_regs reg; diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index c2b0bba..be4b321 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -118,6 +118,7 @@ struct omap_nand_info { int gpmc_cs; unsigned long phys_base; + unsigned long mem_size; struct completion comp; int dma_ch; int gpmc_irq; @@ -931,6 +932,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) struct omap_nand_platform_data *pdata; int err; int i, offset; + struct resource *res; pdata = pdev-dev.platform_data; if (pdata == NULL) { @@ -950,7 +952,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info-pdev = pdev; info-gpmc_cs = pdata-cs; - info-phys_base = pdata-phys_base; info-mtd.priv = info-nand; info-mtd.name = dev_name(pdev-dev); @@ -959,16 +960,23 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info-nand.options = pdata-devsize; info-nand.options |= NAND_SKIP_BBTSCAN; - /* NAND write protect off */ - gpmc_cs_configure(info-gpmc_cs, GPMC_CONFIG_WP, 0); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + err = -EINVAL; + dev_err(pdev-dev, error getting memory resource\n); + goto out_free_info; + } + + info-phys_base = res-start; + info-mem_size = resource_size(res); - if (!request_mem_region(info-phys_base, NAND_IO_SIZE, + if (!request_mem_region(info-phys_base, info-mem_size, pdev-dev.driver-name)) { err = -EBUSY; goto out_free_info; } - info-nand.IO_ADDR_R = ioremap(info-phys_base, NAND_IO_SIZE); + info-nand.IO_ADDR_R = ioremap(info-phys_base, info-mem_size); if (!info-nand.IO_ADDR_R) { err = -ENOMEM; goto out_release_mem_region; @@ -1110,7 +1118,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) return 0; out_release_mem_region: - release_mem_region(info-phys_base, NAND_IO_SIZE); + release_mem_region(info-phys_base, info-mem_size); out_free_info: kfree(info); -- 1.7.10 -- 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 16/39] mtd: nand: omap2: use gpmc provided irqs
GPMC driver provides it's clientsd with interrupts that can be used through struct resource. Make use of it for irq mode functionality. Signed-off-by: Afzal Mohammed af...@ti.com --- drivers/mtd/nand/omap2.c | 67 +- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index be4b321..440536b 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -121,7 +121,8 @@ struct omap_nand_info { unsigned long mem_size; struct completion comp; int dma_ch; - int gpmc_irq; + int gpmc_irq_fifo; + int gpmc_irq_count; enum { OMAP_NAND_IO_READ = 0, /* read */ OMAP_NAND_IO_WRITE, /* write */ @@ -472,13 +473,11 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev) { struct omap_nand_info *info = (struct omap_nand_info *) dev; u32 bytes; - u32 irq_stat; - irq_stat = gpmc_read_status(GPMC_GET_IRQ_STATUS); bytes = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT); bytes = bytes 0xFFFC; /* io in multiple of 4 bytes */ if (info-iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */ - if (irq_stat 0x2) + if (this_irq == info-gpmc_irq_count) goto done; if (info-buf_len (info-buf_len bytes)) @@ -495,20 +494,17 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev) (u32 *)info-buf, bytes 2); info-buf = info-buf + bytes; - if (irq_stat 0x2) + if (this_irq == info-gpmc_irq_count) goto done; } - gpmc_cs_configure(info-gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat); return IRQ_HANDLED; done: complete(info-comp); - /* disable irq */ - gpmc_cs_configure(info-gpmc_cs, GPMC_ENABLE_IRQ, 0); - /* clear status */ - gpmc_cs_configure(info-gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat); + disable_irq_nosync(info-gpmc_irq_fifo); + disable_irq_nosync(info-gpmc_irq_count); return IRQ_HANDLED; } @@ -542,9 +538,9 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len) goto out_copy; info-buf_len = len; - /* enable irq */ - gpmc_cs_configure(info-gpmc_cs, GPMC_ENABLE_IRQ, - (GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT)); + + enable_irq(info-gpmc_irq_count); + enable_irq(info-gpmc_irq_fifo); /* waiting for read to complete */ wait_for_completion(info-comp); @@ -591,12 +587,13 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd, goto out_copy; info-buf_len = len; - /* enable irq */ - gpmc_cs_configure(info-gpmc_cs, GPMC_ENABLE_IRQ, - (GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT)); + + enable_irq(info-gpmc_irq_count); + enable_irq(info-gpmc_irq_fifo); /* waiting for write to complete */ wait_for_completion(info-comp); + /* wait for data to flushed-out before reset the prefetch */ tim = 0; limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS)); @@ -982,6 +979,14 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) goto out_release_mem_region; } + info-gpmc_irq_fifo = platform_get_irq(pdev, 0); + if (info-gpmc_irq_fifo == -ENXIO) + dev_warn(pdev-dev, error getting FIFO IRQ\n); + + info-gpmc_irq_count = platform_get_irq(pdev, 1); + if (info-gpmc_irq_fifo == -ENXIO) + dev_warn(pdev-dev, error getting TERMINALCOUNT IRQ\n); + info-nand.controller = info-controller; info-nand.IO_ADDR_W = info-nand.IO_ADDR_R; @@ -1037,17 +1042,24 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) break; case NAND_OMAP_PREFETCH_IRQ: - err = request_irq(pdata-gpmc_irq, - omap_nand_irq, IRQF_SHARED, gpmc-nand, info); + err = request_irq(info-gpmc_irq_fifo, omap_nand_irq, + IRQF_SHARED, gpmc-nand-fifo, info); if (err) { dev_err(pdev-dev, requesting irq(%d) error:%d, - pdata-gpmc_irq, err); + info-gpmc_irq_fifo, err); goto out_release_mem_region; - } else { - info-gpmc_irq = pdata-gpmc_irq; - info-nand.read_buf = omap_read_buf_irq_pref; - info-nand.write_buf
[PATCH 17/39] mtd: nand: omap2: handle nand on gpmc
GPMC driver has been modified to fill NAND platform data with GPMC NAND register details. As these registers are accessible in NAND driver itself, configure NAND in GPMC by itself. Note: Verfying that other CS have not yet enabled for prefetch ecc has to be incorporated. Currently this causes no issues as there are no boards that use NAND on multiple CS. With GPMC modifications, perhaps it would be better to consider NAND connected on multiple CS as a single peripheral using multiple CS. This would make handling multiple CS issues easier. Signed-off-by: Afzal Mohammed af...@ti.com --- drivers/mtd/nand/omap2.c | 209 -- 1 file changed, 165 insertions(+), 44 deletions(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 440536b..34fb726 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -129,8 +129,79 @@ struct omap_nand_info { } iomode; u_char *buf; int buf_len; + struct gpmc_nand_regs reg; }; +#definePREFETCH_CONFIG1_CS_SHIFT 24 +#defineECC_CONFIG_CS_SHIFT 1 +#defineCS_MASK 0x7 +#defineENABLE_PREFETCH (0x1 7) +#defineDMA_MPU_MODE_SHIFT 2 +#defineECCSIZE1_SHIFT 22 +#defineECC1RESULTSIZE 0x1 +#defineECC_CLEAR_SHIFT 8 +#defineECC10x1 + +/** + * omap_prefetch_enable - configures and starts prefetch transfer + * @cs: cs (chip select) number + * @fifo_th: fifo threshold to be used for read/ write + * @dma_mode: dma mode enable (1) or disable (0) + * @u32_count: number of bytes to be transferred + * @is_write: prefetch read(0) or write post(1) mode + */ +static int omap_prefetch_enable(int cs, int fifo_th, int dma_mode, + unsigned int u32_count, int is_write, struct omap_nand_info *info) +{ + u32 val; + + if (fifo_th PREFETCH_FIFOTHRESHOLD_MAX) { + pr_err(gpmc: fifo threshold is not supported\n); + return -1; + } else if (!(readl(info-reg.gpmc_prefetch_control))) { + /* Set the amount of bytes to be prefetched */ + writel(u32_count, info-reg.gpmc_prefetch_config2); + + /* Set dma/mpu mode, the prefetch read / post write and +* enable the engine. Set which cs is has requested for. +*/ + val = ((cs PREFETCH_CONFIG1_CS_SHIFT) | + PREFETCH_FIFOTHRESHOLD(fifo_th) | + ENABLE_PREFETCH | + (dma_mode DMA_MPU_MODE_SHIFT) | + (0x1 is_write)); + writel(val, info-reg.gpmc_prefetch_config1); + + /* Start the prefetch engine */ + writel(0x1, info-reg.gpmc_prefetch_control); + } else { + return -EBUSY; + } + + return 0; +} + +/** + * omap_prefetch_reset - disables and stops the prefetch engine + */ +static int omap_prefetch_reset(int cs, struct omap_nand_info *info) +{ + u32 config1; + + /* check if the same module/cs is trying to reset */ + config1 = readl(info-reg.gpmc_prefetch_config1); + if (((config1 PREFETCH_CONFIG1_CS_SHIFT) CS_MASK) != cs) + return -EINVAL; + + /* Stop the PFPW engine */ + writel(0x0, info-reg.gpmc_prefetch_control); + + /* Reset/disable the PFPW engine */ + writel(0x0, info-reg.gpmc_prefetch_config1); + + return 0; +} + /** * omap_hwcontrol - hardware specific access to control-lines * @mtd: MTD device structure @@ -149,13 +220,13 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) if (cmd != NAND_CMD_NONE) { if (ctrl NAND_CLE) - gpmc_nand_write(info-gpmc_cs, GPMC_NAND_COMMAND, cmd); + writeb(cmd, info-reg.gpmc_nand_command); else if (ctrl NAND_ALE) - gpmc_nand_write(info-gpmc_cs, GPMC_NAND_ADDRESS, cmd); + writeb(cmd, info-reg.gpmc_nand_address); else /* NAND_NCE */ - gpmc_nand_write(info-gpmc_cs, GPMC_NAND_DATA, cmd); + writeb(cmd, info-reg.gpmc_nand_data); } } @@ -189,7 +260,8 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len) iowrite8(*p++, info-nand.IO_ADDR_W); /* wait until buffer is available for write */ do { - status = gpmc_read_status(GPMC_STATUS_BUFFER); + status = readl(info-reg.gpmc_status) + GPMC_STATUS_BUFF_EMPTY; } while (!status
[PATCH 18/39] mtd: onenand: omap: obtain memory from resource
gpmc being converted to driver, provides drivers of peripheral connected memory space used by the peripheral as memory resource. Modify nand omap driver to obtain memory detials from resource structure. And so remove usage of gpmc exported symbols. Signed-off-by: Afzal Mohammed af...@ti.com --- drivers/mtd/onenand/omap2.c | 29 - 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index 398a827..3ff893d 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -48,13 +48,13 @@ #define DRIVER_NAME omap2-onenand -#define ONENAND_IO_SIZESZ_128K #define ONENAND_BUFRAM_SIZE(1024 * 5) struct omap2_onenand { struct platform_device *pdev; int gpmc_cs; unsigned long phys_base; + unsigned int mem_size; int gpio_irq; struct mtd_info mtd; struct onenand_chip onenand; @@ -626,6 +626,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) struct omap2_onenand *c; struct onenand_chip *this; int r; + struct resource *res; pdata = pdev-dev.platform_data; if (pdata == NULL) { @@ -647,20 +648,24 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) c-gpio_irq = 0; } - r = gpmc_cs_request(c-gpmc_cs, ONENAND_IO_SIZE, c-phys_base); - if (r 0) { - dev_err(pdev-dev, Cannot request GPMC CS\n); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + r = -EINVAL; + dev_err(pdev-dev, error getting memory resource\n); goto err_kfree; } - if (request_mem_region(c-phys_base, ONENAND_IO_SIZE, + c-phys_base = res-start; + c-mem_size = resource_size(res); + + if (request_mem_region(c-phys_base, c-mem_size, pdev-dev.driver-name) == NULL) { - dev_err(pdev-dev, Cannot reserve memory region at 0x%08lx, - size: 0x%x\n, c-phys_base, ONENAND_IO_SIZE); + dev_err(pdev-dev, Cannot reserve memory region at 0x%08lx, size: 0x%x\n, + c-phys_base, c-mem_size); r = -EBUSY; - goto err_free_cs; + goto err_kfree; } - c-onenand.base = ioremap(c-phys_base, ONENAND_IO_SIZE); + c-onenand.base = ioremap(c-phys_base, c-mem_size); if (c-onenand.base == NULL) { r = -ENOMEM; goto err_release_mem_region; @@ -776,9 +781,7 @@ err_release_gpio: err_iounmap: iounmap(c-onenand.base); err_release_mem_region: - release_mem_region(c-phys_base, ONENAND_IO_SIZE); -err_free_cs: - gpmc_cs_free(c-gpmc_cs); + release_mem_region(c-phys_base, c-mem_size); err_kfree: kfree(c); @@ -800,7 +803,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev) gpio_free(c-gpio_irq); } iounmap(c-onenand.base); - release_mem_region(c-phys_base, ONENAND_IO_SIZE); + release_mem_region(c-phys_base, c-mem_size); gpmc_cs_free(c-gpmc_cs); kfree(c); -- 1.7.10 -- 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 19/39] ARM: OMAP2+: board omap3evm: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-omap3evm.c | 14 +- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index fd1b481..b00765e 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -43,6 +43,7 @@ #include plat/board.h #include plat/usb.h +#include plat/gpmc.h #include common.h #include plat/mcspi.h #include video/omapdss.h @@ -102,6 +103,12 @@ static void __init omap3_evm_get_revision(void) } } +static struct gpmc_device_pdata *gpmc_device_data[1]; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; + #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) #include plat/gpmc-smsc911x.h @@ -122,7 +129,11 @@ static inline void __init omap3evm_init_smsc911x(void) smsc911x_cfg.gpio_reset = OMAP3EVM_GEN2_ETHR_GPIO_RST; } - gpmc_smsc911x_init(smsc911x_cfg); + *gpmc_device_data = gpmc_smsc911x_init(smsc911x_cfg); + if (*gpmc_device_data) + gpmc_data.num_device++; + else + pr_err(error: unable to initilaize gpmc smsc911x\n); } #else @@ -679,6 +690,7 @@ static void __init omap3_evm_init(void) usbhs_init(usbhs_bdata); omap_ads7846_init(1, OMAP3_EVM_TS_GPIO, 310, NULL); omap3evm_init_smsc911x(); + omap_init_gpmc(gpmc_data); omap3_evm_display_init(); omap3_evm_wl12xx_init(); } -- 1.7.10 -- 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 20/39] ARM: OMAP2+: board omap3beagle: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-omap3beagle.c | 18 +- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 671ac1c..74bc7f6 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -517,8 +517,16 @@ static void __init beagle_opp_init(void) return; } +static struct gpmc_device_pdata *gpmc_device_data[1]; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; + static void __init omap3_beagle_init(void) { + struct omap_nand_platform_data *nand_data; + omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); omap3_beagle_init_rev(); @@ -543,9 +551,17 @@ static void __init omap3_beagle_init(void) usb_musb_init(NULL); usbhs_init(usbhs_bdata); - board_nand_init(omap3beagle_nand_partitions, + nand_data = board_nand_init(omap3beagle_nand_partitions, ARRAY_SIZE(omap3beagle_nand_partitions), GPMC_CS_NUM, NAND_BUSWIDTH_16, NULL); + if (nand_data != NULL) { + *gpmc_device_data = gpmc_nand_init(nand_data); + if (*gpmc_device_data) + gpmc_data.num_device++; + } else + pr_err(error: %s: nand init\n, __func__); + + omap_init_gpmc(gpmc_data); /* Ensure msecure is mux'd to be able to set the RTC. */ omap_mux_init_signal(sys_drm_msecure, OMAP_PIN_OFF_OUTPUT_HIGH); -- 1.7.10 -- 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 21/39] ARM: OMAP2+: board apollon: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. It is believed that apollon board was added before gpmc-smc91x helper functions were added. Reuse the now available gpmc_smc91x_init adapted for gpmc driver. Note: Timing values were hardcoded and written onto registers, whether making use of gpmc_smc91x_init would configure timing properly has to be tested. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-apollon.c | 152 +-- 1 file changed, 38 insertions(+), 114 deletions(-) diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index 768ece2..6a402e1 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c @@ -39,6 +39,7 @@ #include plat/board.h #include common.h #include plat/gpmc.h +#include plat/gpmc-smc91x.h #include video/omapdss.h #include video/omap-panel-generic-dpi.h @@ -58,6 +59,12 @@ #define APOLLON_ETH_CS 1 #define APOLLON_ETHR_GPIO_IRQ 74 +static struct gpmc_device_pdata *gpmc_device_data[2]; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; + static struct mtd_partition apollon_partitions[] = { { .name = X-Loader + U-Boot, @@ -97,57 +104,26 @@ static struct onenand_platform_data apollon_flash_data = { .nr_parts = ARRAY_SIZE(apollon_partitions), }; -static struct resource apollon_flash_resource[] = { - [0] = { - .flags = IORESOURCE_MEM, - }, +static struct gpmc_cs_data apollon_gpmc_onenand_cs_data = { + .cs = APOLLON_FLASH_CS, + .mem_size = SZ_128K, }; -static struct platform_device apollon_onenand_device = { +static struct gpmc_device_pdata apollon_gpmc_onenand_data = { .name = onenand-flash, .id = -1, - .dev= { - .platform_data = apollon_flash_data, - }, - .num_resources = ARRAY_SIZE(apollon_flash_resource), - .resource = apollon_flash_resource, -}; - -static void __init apollon_flash_init(void) -{ - unsigned long base; - - if (gpmc_cs_request(APOLLON_FLASH_CS, SZ_128K, base) 0) { - printk(KERN_ERR Cannot request OneNAND GPMC CS\n); - return; - } - apollon_flash_resource[0].start = base; - apollon_flash_resource[0].end = base + SZ_128K - 1; -} - -static struct smc91x_platdata appolon_smc91x_info = { - .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT, - .leda = RPC_LED_100_10, - .ledb = RPC_LED_TX_RX, + .pdata = apollon_flash_data, + .pdata_size = sizeof(apollon_flash_data), + .cs_data= apollon_gpmc_onenand_cs_data, + .num_cs = 1, }; -static struct resource apollon_smc91x_resources[] = { - [0] = { - .flags = IORESOURCE_MEM, - }, - [1] = { - .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, - }, -}; - -static struct platform_device apollon_smc91x_device = { - .name = smc91x, - .id = -1, - .dev= { - .platform_data = appolon_smc91x_info, - }, - .num_resources = ARRAY_SIZE(apollon_smc91x_resources), - .resource = apollon_smc91x_resources, +static struct omap_smc91x_platform_data apollon_smc91x_data = { + .gpio_irq = APOLLON_ETHR_GPIO_IRQ, + .cs = APOLLON_ETH_CS, + .wait_pin = GPMC_WAITPIN_1, + .flags = GPMC_TIMINGS_SMC91C96 | IORESOURCE_IRQ_HIGHEDGE | + GPMC_MUXADDDATA, }; static struct omap_led_config apollon_led_config[] = { @@ -185,74 +161,9 @@ static struct platform_device apollon_led_device = { }; static struct platform_device *apollon_devices[] __initdata = { - apollon_onenand_device, - apollon_smc91x_device, apollon_led_device, }; -static inline void __init apollon_init_smc91x(void) -{ - unsigned long base; - - unsigned int rate; - struct clk *gpmc_fck; - int eth_cs; - int err; - - gpmc_fck = clk_get(NULL, gpmc_fck); /* Always on ENABLE_ON_INIT */ - if (IS_ERR(gpmc_fck)) { - WARN_ON(1); - return; - } - - clk_enable(gpmc_fck); - rate = clk_get_rate(gpmc_fck); - - eth_cs = APOLLON_ETH_CS; - - /* Make sure CS1 timings are correct */ - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, 0x00011200); - - if (rate = 16000) { - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F); - gpmc_cs_write_reg(eth_cs
[PATCH 22/39] ARM: OMAP2+: board h4: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. Remove unused h4_init_debug too. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-h4.c | 130 +--- 1 file changed, 15 insertions(+), 115 deletions(-) diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index 0bbbabe..7926082 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -186,22 +186,24 @@ static struct physmap_flash_data h4_flash_data = { .nr_parts = ARRAY_SIZE(h4_partitions), }; -static struct resource h4_flash_resource = { - .flags = IORESOURCE_MEM, +static struct gpmc_cs_data h4_gpmc_cs_flash_data = { + .cs = H4_FLASH_CS, + .mem_size = SZ_64M, }; -static struct platform_device h4_flash_device = { +static struct gpmc_device_pdata h4_gpmc_flash_data = { .name = physmap-flash, .id = 0, - .dev= { - .platform_data = h4_flash_data, - }, - .num_resources = 1, - .resource = h4_flash_resource, + .pdata = h4_flash_data, + .pdata_size = sizeof(h4_flash_data), + .cs_data= h4_gpmc_cs_flash_data, + .num_cs = 1, }; -static struct platform_device *h4_devices[] __initdata = { - h4_flash_device, +static struct gpmc_device_pdata *gpmc_device_data[1]; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, }; static struct panel_generic_dpi_data h4_panel_data = { @@ -226,109 +228,6 @@ static struct omap_dss_board_info h4_dss_data = { .default_device = h4_lcd_device, }; -/* 2420 Sysboot setup (2430 is different) */ -static u32 get_sysboot_value(void) -{ - return (omap_ctrl_readl(OMAP24XX_CONTROL_STATUS) - (OMAP2_SYSBOOT_5_MASK | OMAP2_SYSBOOT_4_MASK | -OMAP2_SYSBOOT_3_MASK | OMAP2_SYSBOOT_2_MASK | -OMAP2_SYSBOOT_1_MASK | OMAP2_SYSBOOT_0_MASK)); -} - -/* H4-2420's always used muxed mode, H4-2422's always use non-muxed - * - * Note: OMAP-GIT doesn't correctly do is_cpu_omap2422 and is_cpu_omap2423 - * correctly. The macro needs to look at production_id not just hawkeye. - */ -static u32 is_gpmc_muxed(void) -{ - u32 mux; - mux = get_sysboot_value(); - if ((mux 0xF) == 0xd) - return 1; /* NAND config (could be either) */ - if (mux 0x2) /* if mux'ed */ - return 1; - else - return 0; -} - -static inline void __init h4_init_debug(void) -{ - int eth_cs; - unsigned long cs_mem_base; - unsigned int muxed, rate; - struct clk *gpmc_fck; - - eth_cs = H4_SMC91X_CS; - - gpmc_fck = clk_get(NULL, gpmc_fck); /* Always on ENABLE_ON_INIT */ - if (IS_ERR(gpmc_fck)) { - WARN_ON(1); - return; - } - - clk_enable(gpmc_fck); - rate = clk_get_rate(gpmc_fck); - clk_disable(gpmc_fck); - clk_put(gpmc_fck); - - if (is_gpmc_muxed()) - muxed = 0x200; - else - muxed = 0; - - /* Make sure CS1 timings are correct */ - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, - 0x00011000 | muxed); - - if (rate = 16000) { - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x04C4); - } else if (rate = 13000) { - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x04C4); - } else {/* rate = 1 */ - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x03C2); - } - - if (gpmc_cs_request(eth_cs, SZ_16M, cs_mem_base) 0) { - printk(KERN_ERR Failed to request GPMC mem for smc91x\n); - goto out; - } - - udelay(100); - - omap_mux_init_gpio(92, 0); - if (debug_card_init(cs_mem_base, H4_ETHR_GPIO_IRQ) 0) - gpmc_cs_free(eth_cs); - -out: - clk_disable(gpmc_fck); - clk_put
[PATCH 23/39] ARM: OMAP2+: board 3630sdp: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-3630sdp.c | 23 +++ 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c index 143e47f..4e0298a 100644 --- a/arch/arm/mach-omap2/board-3630sdp.c +++ b/arch/arm/mach-omap2/board-3630sdp.c @@ -27,18 +27,29 @@ #include mux.h #include sdram-hynix-h8mbx00u0mer-0em.h +static struct gpmc_device_pdata *gpmc_device_data[4]; +static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; + #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE) static struct omap_smc91x_platform_data board_smc91x_data = { .cs = 3, .flags = GPMC_MUX_ADD_DATA | IORESOURCE_IRQ_LOWLEVEL, .skip_timing= true, + .gpio_irq = 158, }; static void __init board_smc91x_init(void) { - board_smc91x_data.gpio_irq = 158; - gpmc_smc91x_init(board_smc91x_data); + *gpmc_cur = gpmc_smc91x_init(board_smc91x_data); + if (*gpmc_cur) + gpmc_data.num_device++, gpmc_cur++; + else + pr_err(error: unable to initilaize gpmc smsc911x\n); } #else @@ -204,9 +215,13 @@ static void __init omap_sdp_init(void) omap_sdrc_init(h8mbx00u0mer0em_sdrc_params, h8mbx00u0mer0em_sdrc_params); zoom_display_init(); + board_smc91x_init(); - board_flash_init(sdp_flash_partitions, chip_sel_sdp, - NAND_BUSWIDTH_16, NULL); + gpmc_data.num_device += board_flash_init(sdp_flash_partitions, + chip_sel_sdp, NAND_BUSWIDTH_16, + gpmc_cur) - gpmc_cur; + omap_init_gpmc(gpmc_data); + enable_board_wakeup_source(); usbhs_init(usbhs_bdata); } -- 1.7.10 -- 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 24/39] ARM: OMAP2+: board 3430sdp: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-3430sdp.c | 17 +++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 367a466..cea5ca5 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -59,6 +59,12 @@ #define TWL4030_MSECURE_GPIO 22 +static struct gpmc_device_pdata *gpmc_device_data[4]; +static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; static uint32_t board_keymap[] = { KEY(0, 0, KEY_LEFT), KEY(0, 1, KEY_RIGHT), @@ -444,7 +450,11 @@ static void __init board_smc91x_init(void) else board_smc91x_data.gpio_irq = 29; - gpmc_smc91x_init(board_smc91x_data); + *gpmc_cur = gpmc_smc91x_init(board_smc91x_data); + if (*gpmc_cur) + gpmc_data.num_device++, gpmc_cur++; + else + pr_err(error: unable to initilaize gpmc smsc911x\n); } #else @@ -621,7 +631,10 @@ static void __init omap_3430sdp_init(void) omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL); usb_musb_init(NULL); board_smc91x_init(); - board_flash_init(sdp_flash_partitions, chip_sel_3430, 0, NULL); + gpmc_data.num_device += board_flash_init(sdp_flash_partitions, + chip_sel_3430, 0, gpmc_cur) - gpmc_cur; + omap_init_gpmc(gpmc_data); + sdp3430_display_init(); enable_board_wakeup_source(); usbhs_init(usbhs_bdata); -- 1.7.10 -- 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 25/39] ARM: OMAP2+: board 2430sdp: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-2430sdp.c | 42 +-- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index 68679a8..d94ada4 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -46,9 +46,16 @@ #include hsmmc.h #include common-board-devices.h -#define SDP2430_CS0_BASE 0x0400 +#define SDP2430_FLASH_CS 0 #define SECONDARY_LCD_GPIO 147 +static struct gpmc_device_pdata *gpmc_device_data[2]; +static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; + static struct mtd_partition sdp2430_partitions[] = { /* bootloader (U-Boot, etc) in first sector */ { @@ -86,24 +93,18 @@ static struct physmap_flash_data sdp2430_flash_data = { .nr_parts = ARRAY_SIZE(sdp2430_partitions), }; -static struct resource sdp2430_flash_resource = { - .start = SDP2430_CS0_BASE, - .end= SDP2430_CS0_BASE + SZ_64M - 1, - .flags = IORESOURCE_MEM, +static struct gpmc_cs_data sdp2430_gpmc_cs_flash_data = { + .cs = SDP2430_FLASH_CS, + .mem_size = SZ_64M, }; -static struct platform_device sdp2430_flash_device = { +static struct gpmc_device_pdata sdp2430_gpmc_flash_device = { .name = physmap-flash, .id = 0, - .dev = { - .platform_data = sdp2430_flash_data, - }, - .num_resources = 1, - .resource = sdp2430_flash_resource, -}; - -static struct platform_device *sdp2430_devices[] __initdata = { - sdp2430_flash_device, + .pdata = sdp2430_flash_data, + .pdata_size = sizeof(sdp2430_flash_data), + .cs_data= sdp2430_gpmc_cs_flash_data, + .num_cs = 1, }; /* LCD */ @@ -181,7 +182,11 @@ static struct omap_smc91x_platform_data board_smc91x_data = { static void __init board_smc91x_init(void) { omap_mux_init_gpio(149, OMAP_PIN_INPUT); - gpmc_smc91x_init(board_smc91x_data); + *gpmc_cur = gpmc_smc91x_init(board_smc91x_data); + if (*gpmc_cur) + gpmc_data.num_device++, gpmc_cur++; + else + pr_err(error: unable to initilaize gpmc smsc911x\n); } #else @@ -276,7 +281,9 @@ static void __init omap_2430sdp_init(void) omap2430_i2c_init(); - platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices)); + *gpmc_cur++ = sdp2430_gpmc_flash_device; + gpmc_data.num_device++; + omap_serial_init(); omap_sdrc_init(NULL, NULL); omap_hsmmc_init(mmc); @@ -286,6 +293,7 @@ static void __init omap_2430sdp_init(void) usb_musb_init(NULL); board_smc91x_init(); + omap_init_gpmc(gpmc_data); /* Turn off secondary LCD backlight */ gpio_request_one(SECONDARY_LCD_GPIO, GPIOF_OUT_INIT_LOW, -- 1.7.10 -- 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 26/39] ARM: OMAP2+: board cm-t3517: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-cm-t3517.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c index 9e66e16..6aa6b4a 100644 --- a/arch/arm/mach-omap2/board-cm-t3517.c +++ b/arch/arm/mach-omap2/board-cm-t3517.c @@ -234,6 +234,11 @@ static struct mtd_partition cm_t3517_nand_partitions[] = { }, }; +static struct gpmc_device_pdata *gpmc_device_data[1]; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; static struct omap_nand_platform_data cm_t3517_nand_data = { .parts = cm_t3517_nand_partitions, .nr_parts = ARRAY_SIZE(cm_t3517_nand_partitions), @@ -242,8 +247,8 @@ static struct omap_nand_platform_data cm_t3517_nand_data = { static void __init cm_t3517_init_nand(void) { - if (gpmc_nand_init(cm_t3517_nand_data) 0) - pr_err(CM-T3517: NAND initialization failed\n); + *gpmc_device_data = gpmc_nand_init(cm_t3517_nand_data); + gpmc_data.num_device++; } #else static inline void cm_t3517_init_nand(void) {} @@ -289,6 +294,7 @@ static void __init cm_t3517_init(void) omap_board_config_size = ARRAY_SIZE(cm_t3517_config); cm_t3517_init_leds(); cm_t3517_init_nand(); + omap_init_gpmc(gpmc_data); cm_t3517_init_rtc(); cm_t3517_init_usbh(); cm_t3517_init_hecc(); -- 1.7.10 -- 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 27/39] ARM: OMAP2+: board cm-t35: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-cm-t35.c | 21 +++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index 909a8b9..5b0b637 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -66,6 +66,13 @@ #include linux/smsc911x.h #include plat/gpmc-smsc911x.h +static struct gpmc_device_pdata *gpmc_device_data[2]; +static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; + static struct omap_smsc911x_platform_data cm_t35_smsc911x_cfg = { .id = 0, .cs = CM_T35_SMSC911X_CS, @@ -99,8 +106,17 @@ static void __init cm_t35_init_ethernet(void) regulator_register_fixed(1, sb_t35_smsc911x_supplies, ARRAY_SIZE(sb_t35_smsc911x_supplies)); - gpmc_smsc911x_init(cm_t35_smsc911x_cfg); - gpmc_smsc911x_init(sb_t35_smsc911x_cfg); + *gpmc_cur = gpmc_smsc911x_init(cm_t35_smsc911x_cfg); + if (*gpmc_cur) + gpmc_data.num_device++, gpmc_cur++; + else + pr_err(error: initilaizing gpmc smsc911x instance 1\n); + + *gpmc_cur = gpmc_smsc911x_init(sb_t35_smsc911x_cfg); + if (*gpmc_cur) + gpmc_data.num_device++, gpmc_cur++; + else + pr_err(error: initilaizing gpmc smsc911x instance 2\n); } #else static inline void __init cm_t35_init_ethernet(void) { return; } @@ -658,6 +674,7 @@ static void __init cm_t3x_common_init(void) cm_t35_init_i2c(); omap_ads7846_init(1, CM_T35_GPIO_PENDOWN, 0, NULL); cm_t35_init_ethernet(); + omap_init_gpmc(gpmc_data); cm_t35_init_led(); cm_t35_init_display(); -- 1.7.10 -- 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 28/39] ARM: OMAP2+: board ldp: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-ldp.c | 26 +++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index b76f28d..1ebc024 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -43,6 +43,7 @@ #include asm/delay.h #include plat/usb.h #include plat/gpmc-smsc911x.h +#include plat/nand.h #include video/omapdss.h #include video/omap-panel-generic-dpi.h @@ -58,6 +59,13 @@ #define DEBUG_BASE 0x0800 #define LDP_ETHR_START DEBUG_BASE +static struct gpmc_device_pdata *gpmc_device_data[2]; +static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; + static uint32_t board_keymap[] = { KEY(0, 0, KEY_1), KEY(1, 0, KEY_2), @@ -180,7 +188,9 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = { static inline void __init ldp_init_smsc911x(void) { - gpmc_smsc911x_init(smsc911x_cfg); + *gpmc_cur = gpmc_smsc911x_init(smsc911x_cfg); + if (*gpmc_cur) + gpmc_data.num_device++, gpmc_cur++; } /* LCD */ @@ -418,6 +428,8 @@ static struct regulator_consumer_supply dummy_supplies[] = { static void __init omap_ldp_init(void) { + struct omap_nand_platform_data *nand_data; + regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); ldp_init_smsc911x(); @@ -427,8 +439,16 @@ static void __init omap_ldp_init(void) omap_serial_init(); omap_sdrc_init(NULL, NULL); usb_musb_init(NULL); - board_nand_init(ldp_nand_partitions, ARRAY_SIZE(ldp_nand_partitions), - ZOOM_NAND_CS, 0, nand_default_timings); + + nand_data = board_nand_init(ldp_nand_partitions, + ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, + 0, nand_default_timings); + if (nand_data != NULL) { + *gpmc_cur++ = gpmc_nand_init(nand_data); + gpmc_data.num_device++; + } + + omap_init_gpmc(gpmc_data); omap_hsmmc_init(mmc); ldp_display_init(); -- 1.7.10 -- 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 29/39] ARM: OMAP2+: board n8x0: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-n8x0.c | 18 +++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index 94f6077..d3d866a 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -36,6 +36,7 @@ #include plat/onenand.h #include plat/mmc.h #include plat/serial.h +#include plat/gpmc.h #include mux.h @@ -45,6 +46,13 @@ #define TUSB6010_GPIO_ENABLE 0 #define TUSB6010_DMACHAN 0x3f +static struct gpmc_device_pdata *gpmc_device_data[2]; +static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; + #if defined(CONFIG_USB_MUSB_TUSB6010) || defined(CONFIG_USB_MUSB_TUSB6010_MODULE) /* * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and @@ -114,10 +122,12 @@ static void __init n8x0_usb_init(void) } tusb_set_power(0); - ret = tusb6010_setup_interface(tusb_data, TUSB6010_REFCLK_19, 2, + *gpmc_cur = tusb6010_setup_interface(tusb_data, TUSB6010_REFCLK_19, 2, TUSB6010_ASYNC_CS, TUSB6010_SYNC_CS, TUSB6010_GPIO_INT, TUSB6010_DMACHAN); - if (ret != 0) + if (*gpmc_cur) + gpmc_data.num_device++, gpmc_cur++; + else goto err; printk(announce); @@ -785,7 +795,9 @@ static void __init n8x0_init_machine(void) ARRAY_SIZE(n810_i2c_board_info_2)); board_serial_init(); omap_sdrc_init(NULL, NULL); - gpmc_onenand_init(board_onenand_data); + *gpmc_cur++ = gpmc_onenand_init(board_onenand_data); + gpmc_data.num_device++; + omap_init_gpmc(gpmc_data); n8x0_mmc_init(); n8x0_usb_init(); } -- 1.7.10 -- 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 30/39] ARM: OMAP2+: board omap3logic: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-omap3logic.c | 13 - 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c index 9b3c141..9867fc8 100644 --- a/arch/arm/mach-omap2/board-omap3logic.c +++ b/arch/arm/mach-omap2/board-omap3logic.c @@ -55,6 +55,12 @@ #define OMAP3_TORPEDO_MMC_GPIO_CD 127 #define OMAP3_TORPEDO_SMSC911X_GPIO_IRQ129 +static struct gpmc_device_pdata *gpmc_device_data[1]; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; + static struct regulator_consumer_supply omap3logic_vmmc1_supply[] = { REGULATOR_SUPPLY(vmmc, omap_hsmmc.0), }; @@ -180,7 +186,11 @@ static inline void __init board_smsc911x_init(void) return; } - gpmc_smsc911x_init(board_smsc911x_data); + *gpmc_device_data = gpmc_smsc911x_init(board_smsc911x_data); + if (*gpmc_device_data) + gpmc_data.num_device++; + else + pr_err(error: unable to initilaize gpmc smsc911x\n); } #ifdef CONFIG_OMAP_MUX @@ -204,6 +214,7 @@ static void __init omap3logic_init(void) omap_sdrc_init(NULL, NULL); board_mmc_init(); board_smsc911x_init(); + omap_init_gpmc(gpmc_data); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal(sdrc_cke0, OMAP_PIN_OUTPUT); -- 1.7.10 -- 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 31/39] ARM: OMAP2+: board omap3pandora: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-omap3pandora.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 33d995d..25b2de6 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -57,6 +57,12 @@ #define PANDORA_WIFI_NRESET_GPIO 23 #define OMAP3_PANDORA_TS_GPIO 94 +static struct gpmc_device_pdata *gpmc_device_data[1]; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; + static struct mtd_partition omap3pandora_nand_partitions[] = { { .name = xloader, @@ -607,8 +613,9 @@ static void __init omap3pandora_init(void) omap_ads7846_init(1, OMAP3_PANDORA_TS_GPIO, 0, NULL); usbhs_init(usbhs_bdata); usb_musb_init(NULL); - gpmc_nand_init(pandora_nand_data); - + *gpmc_device_data = gpmc_nand_init(pandora_nand_data); + gpmc_data.num_device++; + omap_init_gpmc(gpmc_data); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal(sdrc_cke0, OMAP_PIN_OUTPUT); omap_mux_init_signal(sdrc_cke1, OMAP_PIN_OUTPUT); -- 1.7.10 -- 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 32/39] ARM: OMAP2+: board omap3stalker: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-omap3stalker.c | 13 - 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c index 4dffc95..5e92d54 100644 --- a/arch/arm/mach-omap2/board-omap3stalker.c +++ b/arch/arm/mach-omap2/board-omap3stalker.c @@ -56,6 +56,12 @@ #include hsmmc.h #include common-board-devices.h +static struct gpmc_device_pdata *gpmc_device_data[1]; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; + #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) #include plat/gpmc-smsc911x.h @@ -74,7 +80,11 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = { static inline void __init omap3stalker_init_eth(void) { omap_mux_init_gpio(19, OMAP_PIN_INPUT_PULLUP); - gpmc_smsc911x_init(smsc911x_cfg); + *gpmc_device_data = gpmc_smsc911x_init(smsc911x_cfg); + if (*gpmc_device_data) + gpmc_data.num_device++; + else + pr_err(error: unable to initilaize gpmc smsc911x\n); } #else @@ -443,6 +453,7 @@ static void __init omap3_stalker_init(void) omap_mux_init_gpio(18, OMAP_PIN_INPUT_PULLUP); omap3stalker_init_eth(); + omap_init_gpmc(gpmc_data); omap3_stalker_display_init(); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal(sdr_cke0, OMAP_PIN_OUTPUT); -- 1.7.10 -- 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 33/39] ARM: OMAP2+: board omap4pcm049: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-omap4pcm049.c | 13 - 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/board-omap4pcm049.c b/arch/arm/mach-omap2/board-omap4pcm049.c index 81de7d5..b4ead86 100644 --- a/arch/arm/mach-omap2/board-omap4pcm049.c +++ b/arch/arm/mach-omap2/board-omap4pcm049.c @@ -130,6 +130,12 @@ static struct omap2_hsmmc_info mmc[] = { }, {} /* Terminator */ }; +static struct gpmc_device_pdata *gpmc_device_data[1]; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; + #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) static struct regulator_consumer_supply dummy_supplies[] = { REGULATOR_SUPPLY(vddvario, smsc911x.0), @@ -147,7 +153,11 @@ static inline void __init pcm049_init_smsc911x(void) { omap_mux_init_gpio(OMAP4_PCM049_ETH_GPIO_IRQ, OMAP_PIN_INPUT); regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); - gpmc_smsc911x_init(board_smsc911x_data); + *gpmc_device_data = gpmc_smsc911x_init(board_smsc911x_data); + if (*gpmc_device_data) + gpmc_data.num_device++; + else + pr_err(error: unable to initilaize gpmc smsc911x\n); } #else static inline void __init pcm049_init_smsc911x(void) { return; } @@ -562,6 +572,7 @@ static void __init pcm049_init(void) pm_power_off = pcm049_power_off; omap4_mux_init(board_mux, NULL, OMAP_PACKAGE_CBS); pcm049_init_smsc911x(); + omap_init_gpmc(gpmc_data); pcm049_i2c_init(); platform_add_devices(pcm049_devices, ARRAY_SIZE(pcm049_devices)); board_serial_init(); -- 1.7.10 -- 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 34/39] ARM: OMAP2+: board overo: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-overo.c | 29 ++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index e08479a..fa0197e 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -72,6 +72,13 @@ #define OVERO_SMSC911X2_CS 4 #define OVERO_SMSC911X2_GPIO 65 +static struct gpmc_device_pdata *gpmc_device_data[3]; +static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; + #if defined(CONFIG_TOUCHSCREEN_ADS7846) || \ defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) @@ -137,8 +144,16 @@ static struct omap_smsc911x_platform_data smsc911x2_cfg = { static void __init overo_init_smsc911x(void) { - gpmc_smsc911x_init(smsc911x_cfg); - gpmc_smsc911x_init(smsc911x2_cfg); + *gpmc_cur = gpmc_smsc911x_init(smsc911x_cfg); + if (*gpmc_cur) + gpmc_data.num_device++, gpmc_cur++; + else + pr_err(error: %s: smsc911x instance 1 setup\n, __func__); + *gpmc_cur = gpmc_smsc911x_init(smsc911x2_cfg); + if (*gpmc_cur) + gpmc_data.num_device++, gpmc_cur++; + else + pr_err(error: %s: smsc911x instance 1 setup\n, __func__); } #else @@ -509,6 +524,7 @@ static struct regulator_consumer_supply dummy_supplies[] = { static void __init overo_init(void) { int ret; + struct omap_nand_platform_data *nand_data; regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); @@ -518,12 +534,19 @@ static void __init overo_init(void) omap_serial_init(); omap_sdrc_init(mt46h32m32lf6_sdrc_params, mt46h32m32lf6_sdrc_params); - board_nand_init(overo_nand_partitions, + + nand_data = board_nand_init(overo_nand_partitions, ARRAY_SIZE(overo_nand_partitions), GPMC_CS_NUM, 0, NULL); + if (nand_data != NULL) { + *gpmc_cur++ = gpmc_nand_init(nand_data); + gpmc_data.num_device++; + } + usb_musb_init(NULL); usbhs_init(usbhs_bdata); overo_spi_init(); overo_init_smsc911x(); + omap_init_gpmc(gpmc_data); overo_display_init(); overo_init_led(); overo_init_keys(); -- 1.7.10 -- 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 35/39] ARM: OMAP2+: board rm680: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-rm680.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c index ae53d71..e28e606 100644 --- a/arch/arm/mach-omap2/board-rm680.c +++ b/arch/arm/mach-omap2/board-rm680.c @@ -33,6 +33,12 @@ #include sdram-nokia.h #include common-board-devices.h +static struct gpmc_device_pdata *gpmc_device_data[1]; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; + static struct regulator_consumer_supply rm680_vemmc_consumers[] = { REGULATOR_SUPPLY(vmmc, omap_hsmmc.1), }; @@ -119,7 +125,8 @@ static void __init rm680_peripherals_init(void) platform_add_devices(rm680_peripherals_devices, ARRAY_SIZE(rm680_peripherals_devices)); rm680_i2c_init(); - gpmc_onenand_init(board_onenand_data); + *gpmc_device_data = gpmc_onenand_init(board_onenand_data); + gpmc_data.num_device++; omap_hsmmc_init(mmc); } @@ -141,6 +148,7 @@ static void __init rm680_init(void) usb_musb_init(NULL); rm680_peripherals_init(); + omap_init_gpmc(gpmc_data); } MACHINE_START(NOKIA_RM680, Nokia RM-680 board) -- 1.7.10 -- 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 36/39] ARM: OMAP2+: board rx51: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-rx51-peripherals.c | 17 +++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index ae957c9..af7909e 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -73,6 +73,13 @@ enum { static struct wl12xx_platform_data wl1251_pdata; static struct tsc2005_platform_data tsc2005_pdata; +static struct gpmc_device_pdata *gpmc_device_data[2]; +static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; + #if defined(CONFIG_SENSORS_TSL2563) || defined(CONFIG_SENSORS_TSL2563_MODULE) static struct tsl2563_platform_data rx51_tsl2563_platform_data = { .cover_comp_gain = 16, @@ -1039,7 +1046,11 @@ static void __init board_smc91x_init(void) omap_mux_init_gpio(86, OMAP_PIN_OUTPUT); omap_mux_init_gpio(164, OMAP_PIN_OUTPUT); - gpmc_smc91x_init(board_smc91x_data); + *gpmc_cur = gpmc_smc91x_init(board_smc91x_data); + if (*gpmc_cur) + gpmc_data.num_device++, gpmc_cur++; + else + pr_err(error: gpmc smsc911x setup\n); } #else @@ -1136,8 +1147,10 @@ void __init rx51_peripherals_init(void) { rx51_i2c_init(); regulator_has_full_constraints(); - gpmc_onenand_init(board_onenand_data); + *gpmc_cur++ = gpmc_onenand_init(board_onenand_data); + gpmc_data.num_device++; board_smc91x_init(); + omap_init_gpmc(gpmc_data); rx51_add_gpio_keys(); rx51_init_wl1251(); rx51_init_tsc2005(); -- 1.7.10 -- 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 37/39] ARM: OMAP2+: board zoom-debugboard: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-zoom-debugboard.c | 47 +++ 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-omap2/board-zoom-debugboard.c b/arch/arm/mach-omap2/board-zoom-debugboard.c index f64f441..dae7df2 100644 --- a/arch/arm/mach-omap2/board-zoom-debugboard.c +++ b/arch/arm/mach-omap2/board-zoom-debugboard.c @@ -31,6 +31,13 @@ #define DEBUG_BASE 0x0800 #define ZOOM_ETHR_STARTDEBUG_BASE +static struct gpmc_device_pdata *gpmc_device_data[2]; +static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; + static struct omap_smsc911x_platform_data zoom_smsc911x_cfg = { .cs = ZOOM_SMSC911X_CS, .gpio_irq = ZOOM_SMSC911X_GPIO, @@ -40,7 +47,11 @@ static struct omap_smsc911x_platform_data zoom_smsc911x_cfg = { static inline void __init zoom_init_smsc911x(void) { - gpmc_smsc911x_init(zoom_smsc911x_cfg); + *gpmc_cur = gpmc_smsc911x_init(zoom_smsc911x_cfg); + if (*gpmc_cur) + gpmc_data.num_device++, gpmc_cur++; + else + pr_err(error: %s: gpmc smsc911x setup\n, __func__); } static struct plat_serial8250_port serial_platform_data[] = { @@ -56,18 +67,22 @@ static struct plat_serial8250_port serial_platform_data[] = { } }; -static struct platform_device zoom_debugboard_serial_device = { +static struct gpmc_cs_data zoom_debugboard_gpmc_cs_serial_data = { + .cs = ZOOM_QUADUART_CS, + .mem_size = SZ_1M, +}; + +static struct gpmc_device_pdata zoom_debugboard_gpmc_serial_data = { .name = serial8250, .id = PLAT8250_DEV_PLATFORM, - .dev= { - .platform_data = serial_platform_data, - }, + .pdata = serial_platform_data, + .pdata_size = sizeof(serial_platform_data), + .cs_data= zoom_debugboard_gpmc_cs_serial_data, + .num_cs = 1, }; static inline void __init zoom_init_quaduart(void) { - int quart_cs; - unsigned long cs_mem_base; int quart_gpio = 0; if (gpio_request_one(ZOOM_QUADUART_RST_GPIO, @@ -78,14 +93,6 @@ static inline void __init zoom_init_quaduart(void) return; } - quart_cs = ZOOM_QUADUART_CS; - - if (gpmc_cs_request(quart_cs, SZ_1M, cs_mem_base) 0) { - printk(KERN_ERR Failed to request GPMC mem - for Quad UART(TL16CP754C)\n); - return; - } - quart_gpio = ZOOM_QUADUART_GPIO; if (gpio_request_one(quart_gpio, GPIOF_IN, TL16CP754C GPIO) 0) @@ -93,6 +100,9 @@ static inline void __init zoom_init_quaduart(void) quart_gpio); serial_platform_data[0].irq = gpio_to_irq(102); + + *gpmc_cur++ = zoom_debugboard_gpmc_serial_data; + gpmc_data.num_device++; } static inline int omap_zoom_debugboard_detect(void) @@ -116,10 +126,6 @@ static inline int omap_zoom_debugboard_detect(void) return ret; } -static struct platform_device *zoom_devices[] __initdata = { - zoom_debugboard_serial_device, -}; - static struct regulator_consumer_supply dummy_supplies[] = { REGULATOR_SUPPLY(vddvario, smsc911x.0), REGULATOR_SUPPLY(vdd33a, smsc911x.0), @@ -133,5 +139,6 @@ int __init zoom_debugboard_init(void) regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); zoom_init_smsc911x(); zoom_init_quaduart(); - return platform_add_devices(zoom_devices, ARRAY_SIZE(zoom_devices)); + omap_init_gpmc(gpmc_data); + return 0; } -- 1.7.10 -- 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 38/39] OMAP3: igep0020: Add support for Micron NAND Flash storage memory
From: Javier Martinez Canillas jav...@dowhile0.org IGEP-based boards can have two different flash memories, a OneNAND or a NAND device. The boot configuration pins (sys_boot) are used to specify which memory is available. Also, this patch removes unnecesary code for registering the OneNAND. af...@ti.com: Update to use modified board_nand_init Signed-off-by: Javier Martinez Canillas jav...@dowhile0.org Signed-off-by: Afzal Mohammed af...@ti.com fixup: igep --- arch/arm/mach-omap2/board-igep0020.c | 75 ++ 1 file changed, 31 insertions(+), 44 deletions(-) diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index 930c0d3..6d171ca 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c @@ -24,6 +24,8 @@ #include linux/i2c/twl.h #include linux/mmc/host.h +#include linux/mtd/nand.h + #include asm/mach-types.h #include asm/mach/arch.h @@ -39,6 +41,8 @@ #include hsmmc.h #include sdram-numonyx-m65kam.h #include common-board-devices.h +#include board-flash.h +#include control.h #define IGEP2_SMSC911X_CS 5 #define IGEP2_SMSC911X_GPIO 176 @@ -60,6 +64,10 @@ #define IGEP3_GPIO_LED1_RED16 #define IGEP3_GPIO_USBH_NRESET 183 +#define IGEP_SYSBOOT_MASK 0x1f +#define IGEP_SYSBOOT_NAND 0x0f +#define IGEP_SYSBOOT_ONENAND0x10 + /* * IGEP2 Hardware Revision Table * @@ -110,8 +118,10 @@ static void __init igep2_get_revision(void) gpio_free(IGEP2_GPIO_LED1_RED); } -#if defined(CONFIG_MTD_ONENAND_OMAP2) || \ - defined(CONFIG_MTD_ONENAND_OMAP2_MODULE) +#if defined(CONFIG_MTD_ONENAND_OMAP2) || \ + defined(CONFIG_MTD_ONENAND_OMAP2_MODULE) || \ + defined(CONFIG_MTD_NAND_OMAP2) || \ + defined(CONFIG_MTD_NAND_OMAP2_MODULE) #define ONENAND_MAP 0x2000 @@ -123,7 +133,7 @@ static void __init igep2_get_revision(void) * So MTD regards it as 4KiB page size and 256KiB block size 64*(2*2048) */ -static struct mtd_partition igep_onenand_partitions[] = { +static struct mtd_partition igep_flash_partitions[] = { { .name = X-Loader, .offset = 0, @@ -151,50 +161,27 @@ static struct mtd_partition igep_onenand_partitions[] = { }, }; -static struct omap_onenand_platform_data igep_onenand_data = { - .parts = igep_onenand_partitions, - .nr_parts = ARRAY_SIZE(igep_onenand_partitions), - .dma_channel= -1, /* disable DMA in OMAP OneNAND driver */ -}; - -static struct platform_device igep_onenand_device = { - .name = omap2-onenand, - .id = -1, - .dev = { - .platform_data = igep_onenand_data, - }, -}; +static inline u32 igep_get_sysboot_value(void) +{ + return omap_ctrl_readl(OMAP343X_CONTROL_STATUS) IGEP_SYSBOOT_MASK; +} static void __init igep_flash_init(void) { - u8 cs = 0; - u8 onenandcs = GPMC_CS_NUM + 1; - - for (cs = 0; cs GPMC_CS_NUM; cs++) { - u32 ret; - ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); - - /* Check if NAND/oneNAND is configured */ - if ((ret 0xC00) == 0x800) - /* NAND found */ - pr_err(IGEP: Unsupported NAND found\n); - else { - ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); - if ((ret 0x3F) == (ONENAND_MAP 24)) - /* ONENAND found */ - onenandcs = cs; - } - } - - if (onenandcs GPMC_CS_NUM) { - pr_err(IGEP: Unable to find configuration in GPMC\n); - return; - } - - igep_onenand_data.cs = onenandcs; - - if (platform_device_register(igep_onenand_device) 0) - pr_err(IGEP: Unable to register OneNAND device\n); + u32 mux; + mux = igep_get_sysboot_value(); + + if (mux == IGEP_SYSBOOT_NAND) { + pr_info(IGEP: initializing NAND memory device\n); + board_nand_init(igep_flash_partitions, + ARRAY_SIZE(igep_flash_partitions), + 0, NAND_BUSWIDTH_16, NULL); + } else if (mux == IGEP_SYSBOOT_ONENAND) { + pr_info(IGEP: initializing OneNAND memory device\n); + board_onenand_init(igep_flash_partitions, + ARRAY_SIZE(igep_flash_partitions), 0); + } else + pr_err(IGEP: Flash: unsupported sysboot sequence found\n); } #else -- 1.7.10 -- 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 39/39] ARM: OMAP2+: board igep0020: gpmc driver adaptation
gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/board-igep0020.c | 32 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index 6d171ca..91de8ce 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c @@ -36,6 +36,7 @@ #include video/omapdss.h #include video/omap-panel-dvi.h #include plat/onenand.h +#include plat/nand.h #include mux.h #include hsmmc.h @@ -118,6 +119,13 @@ static void __init igep2_get_revision(void) gpio_free(IGEP2_GPIO_LED1_RED); } +static struct gpmc_device_pdata *gpmc_device_data[2]; +static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data; + +static struct gpmc_pdata gpmc_data = { + .device_pdata = gpmc_device_data, +}; + #if defined(CONFIG_MTD_ONENAND_OMAP2) || \ defined(CONFIG_MTD_ONENAND_OMAP2_MODULE) || \ defined(CONFIG_MTD_NAND_OMAP2) || \ @@ -172,14 +180,26 @@ static void __init igep_flash_init(void) mux = igep_get_sysboot_value(); if (mux == IGEP_SYSBOOT_NAND) { + struct omap_nand_platform_data *nand_data; + pr_info(IGEP: initializing NAND memory device\n); - board_nand_init(igep_flash_partitions, + nand_data = board_nand_init(igep_flash_partitions, ARRAY_SIZE(igep_flash_partitions), - 0, NAND_BUSWIDTH_16, NULL); + 0, NAND_BUSWIDTH_16, nand_default_timings); + if (nand_data != NULL) { + *gpmc_cur++ = gpmc_nand_init(nand_data); + gpmc_data.num_device++; + } } else if (mux == IGEP_SYSBOOT_ONENAND) { + struct omap_onenand_platform_data *onenand_data; + pr_info(IGEP: initializing OneNAND memory device\n); - board_onenand_init(igep_flash_partitions, + onenand_data = board_onenand_init(igep_flash_partitions, ARRAY_SIZE(igep_flash_partitions), 0); + if (onenand_data != NULL) { + *gpmc_cur++ = gpmc_onenand_init(onenand_data); + gpmc_data.num_device++; + } } else pr_err(IGEP: Flash: unsupported sysboot sequence found\n); } @@ -202,7 +222,11 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = { static inline void __init igep2_init_smsc911x(void) { - gpmc_smsc911x_init(smsc911x_cfg); + *gpmc_cur = gpmc_smsc911x_init(smsc911x_cfg); + if (*gpmc_cur) + gpmc_data.num_device++, gpmc_cur++; + else + pr_err(error: gpmc smsc911x setup\n); } #else -- 1.7.10 -- 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 v4 00/39] OMAP GPMC driver conversion
Hi, GPMC driver conversion patch series. Some peripherals has GPMC helper functions, these has been modified to cater to the needs of GPMC driver. All the boards using GPMC has been adapted to use the new GPMC driver. GPMC HWMOD entry for OMAP2/3 has been added. On OMAP3, kernel does spit omap_hwmod: gpmc: cannot be enabled for reset (3), but peripherals connected via GPMC are working. Really shaky about OMAP2 GPMC HWMOD entry. Would be helpful if someone can help me in resolving warning on OMAP3 verify whether OMAP2 entry is proper. The series adapts to HWMOD. Drivers, NAND OneNAND of OMAP has been modified to make use of GPMC changes cleaned up the now unnecessary exported symbol usages. This series has been made on top of, 5e136da Linux-omap rebuilt: Updated to -rc5, A patch by Javier Martinez Canillas jav...@dowhile0.org, OMAP3: igep0020: Add support for Micron NAND Flash storage memory, has also been incorporated into the series as this was necessary for igep0020 board. This has been tested on omap3 evm (SMSC911x) beagle board (NAND) I would need help to get these changes tested on other boards using GPMC. Expected problematic boards are those having OMAP2xxx SoCs, apollon board. In the case of apollon, in addition to it being OMAP2xxx, it was modified to use gpmc_smc91x_init instead of directly writing to configuration registers. Additional features that currently boards in mainline does not make use of like, waitpin interrupt handling, changes to leverage revision 6 IP differences has not been incorporated. GPMC driver now provides NAND driver with GPMC-NAND registers so that OMAP NAND driver can handle those by itself instead of using exported symbols. Acquiring CS for NAND has also been incorporated, it has been made as a separate patch as it is felt that this should probably go away, explained in the relevant patch. GPMC (General Purpose Memory Controller) in brief: GPMC is an unified memory controller dedicated to interfacing external memory devices like Asynchronous SRAM like memories and application specific integrated circuit devices. Asynchronous, synchronous, and page mode burst NOR flash devices NAND flash Pseudo-SRAM devices GPMC details can be referred in AM335X Technical Reference Manual @ http://www.ti.com/lit/pdf/spruh73 v4: Handle wait pin (except for interrupts), enhance configuration timing interface of GPMC to take care of all boards. Dynamic allocation of interrupt instead of static. Convert remaining peripherals to work with GPMC driver. Handle acquiring NAND CS#, adapt to HWMOD, update HWMOD OMAP2/3 entries, other minor commenst on v3. v3: Single device structure passed from platform for peripherals using multiple CS instead of using multiple device structure having a few redundant data, handle interrupts, GPMC NAND handling by GPMC NAND driver instead of GPMC driver v2: Avoid code movement that kept similar code together (for easy review) TODO: Cleanup Regards Afzal Afzal Mohammed (38): ARM: OMAP2+: gpmc: driver conversion ARM: OMAP2+: gpmc: Adapt to HWMOD ARM: OMAP2+: gpmc: register details for nand driver ARM: OMAP2+: gpmc: Acquire NAND CS value ARM: OMAP2+: nand: create platform data structure ARM: OMAP2+: onenand: return value in init function ARM: OMAP2+: gpmc-nand: Adapt to use gpmc driver ARM: OMAP2+: gpmc-onenand: Adapt to use gpmc driver ARM: OMAP2+: flash: Adapt to gpmc driver ARM: OMAP2+: gpmc-smsc911x: Adapt to use gpmc driver ARM: OMAP2+: gpmc-smc91x: Adapt to use gpmc driver ARM: OMAP2+: gpmc-tusb6010: Adapt to gpmc driver ARM: OMAP3: hwmod data: add gpmc ARM: OMAP2xxx: hwmod data: add gpmc mtd: nand: omap2: obtain memory from resource mtd: nand: omap2: use gpmc provided irqs mtd: nand: omap2: handle nand on gpmc mtd: onenand: omap: obtain memory from resource ARM: OMAP2+: board omap3evm: gpmc driver adaptation ARM: OMAP2+: board omap3beagle: gpmc driver adaptation ARM: OMAP2+: board apollon: gpmc driver adaptation ARM: OMAP2+: board h4: gpmc driver adaptation ARM: OMAP2+: board 3630sdp: gpmc driver adaptation ARM: OMAP2+: board 3430sdp: gpmc driver adaptation ARM: OMAP2+: board 2430sdp: gpmc driver adaptation ARM: OMAP2+: board cm-t3517: gpmc driver adaptation ARM: OMAP2+: board cm-t35: gpmc driver adaptation ARM: OMAP2+: board ldp: gpmc driver adaptation ARM: OMAP2+: board n8x0: gpmc driver adaptation ARM: OMAP2+: board omap3logic: gpmc driver adaptation ARM: OMAP2+: board omap3pandora: gpmc driver adaptation ARM: OMAP2+: board omap3stalker: gpmc driver adaptation ARM: OMAP2+: board omap4pcm049: gpmc driver adaptation ARM: OMAP2+: board overo: gpmc driver adaptation ARM: OMAP2+: board rm680: gpmc driver adaptation ARM: OMAP2+: board rx51: gpmc driver adaptation ARM: OMAP2+: board zoom-debugboard: gpmc driver adaptation ARM: OMAP2+: board igep0020: gpmc driver adaptation Javier Martinez Canillas (1): OMAP3: igep0020: Add support
[PATCH v4 02/39] ARM: OMAP2+: gpmc: Adapt to HWMOD
Create API for platforms to adapt gpmc to HWMOD Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 52 +++- arch/arm/plat-omap/include/plat/gpmc.h |1 + 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 12916f3..c8d07bb 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -33,6 +33,8 @@ #include plat/sdrc.h +#include plat/omap_device.h + /* GPMC register offsets */ #define GPMC_REVISION 0x00 #define GPMC_SYSCONFIG 0x10 @@ -276,6 +278,31 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns) return ticks * gpmc_get_fclk_period() / 1000; } +int __init omap_init_gpmc(struct gpmc_pdata *pdata) +{ + struct omap_hwmod *oh; + struct platform_device *pdev; + char *name = omap-gpmc; + char *oh_name = gpmc; + + pdata-clk_prd = gpmc_get_fclk_period(); + + oh = omap_hwmod_lookup(oh_name); + if (!oh) { + pr_err(Could not look up %s\n, oh_name); + return -ENODEV; + } + + pdev = omap_device_build(name, -1, oh, pdata, + sizeof(*pdata), NULL, 0, 0); + if (IS_ERR(pdev)) { + WARN(1, Can't build omap_device for %s:%s.\n, + name, oh-name); + return PTR_ERR(pdev); + } + + return 0; +} #ifdef DEBUG static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, int time, const char *name) @@ -843,24 +870,19 @@ static __devinit void gpmc_mem_init(void) static int __init gpmc_init(void) { - int ret = -EINVAL; - char *ck = NULL; - - if (cpu_is_omap24xx()) { - ck = core_l3_ck; - } else if (cpu_is_omap34xx()) { - ck = gpmc_fck; - } else if (cpu_is_omap44xx()) { - ck = gpmc_ck; - } + char *oh_name = gpmc; + struct omap_hwmod *oh; - if (WARN_ON(!ck)) - return ret; + oh = omap_hwmod_lookup(oh_name); + if (!oh) { + pr_err(Could not look up %s\n, oh_name); + return -ENODEV; + } - gpmc_l3_clk = clk_get(NULL, ck); + gpmc_l3_clk = clk_get(NULL, oh-main_clk); if (IS_ERR(gpmc_l3_clk)) { - printk(KERN_ERR Could not get GPMC clock %s\n, ck); - BUG(); + pr_err(error: clk_get on %s\n, oh-main_clk); + return -EINVAL; } clk_enable(gpmc_l3_clk); diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 2eedd99..c5cf020 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -217,6 +217,7 @@ struct gpmc_pdata { }; extern int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs); +extern int omap_init_gpmc(struct gpmc_pdata *pdata); extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns); extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps); -- 1.7.10 -- 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