diff options
author | Tony Lindgren <tony@atomide.com> | 2014-11-03 20:45:36 -0500 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2014-11-03 20:45:36 -0500 |
commit | 2dde3bccbf905548a17b8d440053f86454af54a9 (patch) | |
tree | e25ebd532def85307fc231710b6660c93565d55f | |
parent | 8f5951172b6dbda75a9cdf5990650e1cf8b1dd22 (diff) | |
parent | 8bf9be566ed5790003402eb1060184956788b410 (diff) |
Merge branch 'for-v3.19/gpmc-omap' of github.com:rogerq/linux into omap-for-v3.19/gpmc
Conflicts:
arch/arm/mach-omap2/gpmc.c
-rw-r--r-- | arch/arm/mach-omap2/gpmc.c | 87 |
1 files changed, 54 insertions, 33 deletions
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index a7554ac3f37c..73189fa9e1fc 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c | |||
@@ -85,6 +85,8 @@ | |||
85 | #define GPMC_ECC_CTRL_ECCREG8 0x008 | 85 | #define GPMC_ECC_CTRL_ECCREG8 0x008 |
86 | #define GPMC_ECC_CTRL_ECCREG9 0x009 | 86 | #define GPMC_ECC_CTRL_ECCREG9 0x009 |
87 | 87 | ||
88 | #define GPMC_CONFIG_LIMITEDADDRESS BIT(1) | ||
89 | |||
88 | #define GPMC_CONFIG2_CSEXTRADELAY BIT(7) | 90 | #define GPMC_CONFIG2_CSEXTRADELAY BIT(7) |
89 | #define GPMC_CONFIG3_ADVEXTRADELAY BIT(7) | 91 | #define GPMC_CONFIG3_ADVEXTRADELAY BIT(7) |
90 | #define GPMC_CONFIG4_OEEXTRADELAY BIT(7) | 92 | #define GPMC_CONFIG4_OEEXTRADELAY BIT(7) |
@@ -210,11 +212,6 @@ static unsigned long gpmc_get_fclk_period(void) | |||
210 | { | 212 | { |
211 | unsigned long rate = clk_get_rate(gpmc_l3_clk); | 213 | unsigned long rate = clk_get_rate(gpmc_l3_clk); |
212 | 214 | ||
213 | if (rate == 0) { | ||
214 | printk(KERN_WARNING "gpmc_l3_clk not enabled\n"); | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | rate /= 1000; | 215 | rate /= 1000; |
219 | rate = 1000000000 / rate; /* In picoseconds */ | 216 | rate = 1000000000 / rate; /* In picoseconds */ |
220 | 217 | ||
@@ -414,13 +411,8 @@ static inline void gpmc_cs_show_timings(int cs, const char *desc) | |||
414 | } | 411 | } |
415 | #endif | 412 | #endif |
416 | 413 | ||
417 | #ifdef DEBUG | ||
418 | static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, | 414 | static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, |
419 | int time, const char *name) | 415 | int time, const char *name) |
420 | #else | ||
421 | static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, | ||
422 | int time) | ||
423 | #endif | ||
424 | { | 416 | { |
425 | u32 l; | 417 | u32 l; |
426 | int ticks, mask, nr_bits; | 418 | int ticks, mask, nr_bits; |
@@ -430,15 +422,15 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, | |||
430 | else | 422 | else |
431 | ticks = gpmc_ns_to_ticks(time); | 423 | ticks = gpmc_ns_to_ticks(time); |
432 | nr_bits = end_bit - st_bit + 1; | 424 | nr_bits = end_bit - st_bit + 1; |
433 | if (ticks >= 1 << nr_bits) { | 425 | mask = (1 << nr_bits) - 1; |
434 | #ifdef DEBUG | 426 | |
435 | printk(KERN_INFO "GPMC CS%d: %-10s* %3d ns, %3d ticks >= %d\n", | 427 | if (ticks > mask) { |
436 | cs, name, time, ticks, 1 << nr_bits); | 428 | pr_err("%s: GPMC error! CS%d: %s: %d ns, %d ticks > %d\n", |
437 | #endif | 429 | __func__, cs, name, time, ticks, mask); |
430 | |||
438 | return -1; | 431 | return -1; |
439 | } | 432 | } |
440 | 433 | ||
441 | mask = (1 << nr_bits) - 1; | ||
442 | l = gpmc_cs_read_reg(cs, reg); | 434 | l = gpmc_cs_read_reg(cs, reg); |
443 | #ifdef DEBUG | 435 | #ifdef DEBUG |
444 | printk(KERN_INFO | 436 | printk(KERN_INFO |
@@ -453,16 +445,10 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, | |||
453 | return 0; | 445 | return 0; |
454 | } | 446 | } |
455 | 447 | ||
456 | #ifdef DEBUG | ||
457 | #define GPMC_SET_ONE(reg, st, end, field) \ | 448 | #define GPMC_SET_ONE(reg, st, end, field) \ |
458 | if (set_gpmc_timing_reg(cs, (reg), (st), (end), \ | 449 | if (set_gpmc_timing_reg(cs, (reg), (st), (end), \ |
459 | t->field, #field) < 0) \ | 450 | t->field, #field) < 0) \ |
460 | return -1 | 451 | return -1 |
461 | #else | ||
462 | #define GPMC_SET_ONE(reg, st, end, field) \ | ||
463 | if (set_gpmc_timing_reg(cs, (reg), (st), (end), t->field) < 0) \ | ||
464 | return -1 | ||
465 | #endif | ||
466 | 452 | ||
467 | int gpmc_calc_divider(unsigned int sync_clk) | 453 | int gpmc_calc_divider(unsigned int sync_clk) |
468 | { | 454 | { |
@@ -539,7 +525,7 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) | |||
539 | return 0; | 525 | return 0; |
540 | } | 526 | } |
541 | 527 | ||
542 | static int gpmc_cs_enable_mem(int cs, u32 base, u32 size) | 528 | static int gpmc_cs_set_memconf(int cs, u32 base, u32 size) |
543 | { | 529 | { |
544 | u32 l; | 530 | u32 l; |
545 | u32 mask; | 531 | u32 mask; |
@@ -563,6 +549,15 @@ static int gpmc_cs_enable_mem(int cs, u32 base, u32 size) | |||
563 | return 0; | 549 | return 0; |
564 | } | 550 | } |
565 | 551 | ||
552 | static void gpmc_cs_enable_mem(int cs) | ||
553 | { | ||
554 | u32 l; | ||
555 | |||
556 | l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); | ||
557 | l |= GPMC_CONFIG7_CSVALID; | ||
558 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l); | ||
559 | } | ||
560 | |||
566 | static void gpmc_cs_disable_mem(int cs) | 561 | static void gpmc_cs_disable_mem(int cs) |
567 | { | 562 | { |
568 | u32 l; | 563 | u32 l; |
@@ -693,18 +688,18 @@ static int gpmc_cs_remap(int cs, u32 base) | |||
693 | gpmc_cs_get_memconf(cs, &old_base, &size); | 688 | gpmc_cs_get_memconf(cs, &old_base, &size); |
694 | if (base == old_base) | 689 | if (base == old_base) |
695 | return 0; | 690 | return 0; |
696 | gpmc_cs_disable_mem(cs); | 691 | |
697 | ret = gpmc_cs_delete_mem(cs); | 692 | ret = gpmc_cs_delete_mem(cs); |
698 | if (ret < 0) | 693 | if (ret < 0) |
699 | return ret; | 694 | return ret; |
695 | |||
700 | ret = gpmc_cs_insert_mem(cs, base, size); | 696 | ret = gpmc_cs_insert_mem(cs, base, size); |
701 | if (ret < 0) | 697 | if (ret < 0) |
702 | return ret; | 698 | return ret; |
703 | ret = gpmc_cs_enable_mem(cs, base, size); | ||
704 | if (ret < 0) | ||
705 | return ret; | ||
706 | 699 | ||
707 | return 0; | 700 | ret = gpmc_cs_set_memconf(cs, base, size); |
701 | |||
702 | return ret; | ||
708 | } | 703 | } |
709 | 704 | ||
710 | int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) | 705 | int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) |
@@ -734,12 +729,17 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) | |||
734 | if (r < 0) | 729 | if (r < 0) |
735 | goto out; | 730 | goto out; |
736 | 731 | ||
737 | r = gpmc_cs_enable_mem(cs, res->start, resource_size(res)); | 732 | /* Disable CS while changing base address and size mask */ |
733 | gpmc_cs_disable_mem(cs); | ||
734 | |||
735 | r = gpmc_cs_set_memconf(cs, res->start, resource_size(res)); | ||
738 | if (r < 0) { | 736 | if (r < 0) { |
739 | release_resource(res); | 737 | release_resource(res); |
740 | goto out; | 738 | goto out; |
741 | } | 739 | } |
742 | 740 | ||
741 | /* Enable CS */ | ||
742 | gpmc_cs_enable_mem(cs); | ||
743 | *base = res->start; | 743 | *base = res->start; |
744 | gpmc_cs_set_reserved(cs, 1); | 744 | gpmc_cs_set_reserved(cs, 1); |
745 | out: | 745 | out: |
@@ -1667,6 +1667,7 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, | |||
1667 | unsigned long base; | 1667 | unsigned long base; |
1668 | const char *name; | 1668 | const char *name; |
1669 | int ret, cs; | 1669 | int ret, cs; |
1670 | u32 val; | ||
1670 | 1671 | ||
1671 | if (of_property_read_u32(child, "reg", &cs) < 0) { | 1672 | if (of_property_read_u32(child, "reg", &cs) < 0) { |
1672 | dev_err(&pdev->dev, "%s has no 'reg' property\n", | 1673 | dev_err(&pdev->dev, "%s has no 'reg' property\n", |
@@ -1712,6 +1713,9 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, | |||
1712 | goto no_timings; | 1713 | goto no_timings; |
1713 | } | 1714 | } |
1714 | 1715 | ||
1716 | /* CS must be disabled while making changes to gpmc configuration */ | ||
1717 | gpmc_cs_disable_mem(cs); | ||
1718 | |||
1715 | /* | 1719 | /* |
1716 | * FIXME: gpmc_cs_request() will map the CS to an arbitary | 1720 | * FIXME: gpmc_cs_request() will map the CS to an arbitary |
1717 | * location in the gpmc address space. When booting with | 1721 | * location in the gpmc address space. When booting with |
@@ -1735,7 +1739,20 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, | |||
1735 | if (ret < 0) | 1739 | if (ret < 0) |
1736 | goto err; | 1740 | goto err; |
1737 | 1741 | ||
1738 | gpmc_cs_set_timings(cs, &gpmc_t); | 1742 | ret = gpmc_cs_set_timings(cs, &gpmc_t); |
1743 | if (ret) { | ||
1744 | dev_err(&pdev->dev, "failed to set gpmc timings for: %s\n", | ||
1745 | child->name); | ||
1746 | goto err; | ||
1747 | } | ||
1748 | |||
1749 | /* Clear limited address i.e. enable A26-A11 */ | ||
1750 | val = gpmc_read_reg(GPMC_CONFIG); | ||
1751 | val &= ~GPMC_CONFIG_LIMITEDADDRESS; | ||
1752 | gpmc_write_reg(GPMC_CONFIG, val); | ||
1753 | |||
1754 | /* Enable CS region */ | ||
1755 | gpmc_cs_enable_mem(cs); | ||
1739 | 1756 | ||
1740 | no_timings: | 1757 | no_timings: |
1741 | if (of_platform_device_create(child, NULL, &pdev->dev)) | 1758 | if (of_platform_device_create(child, NULL, &pdev->dev)) |
@@ -1832,13 +1849,18 @@ static int gpmc_probe(struct platform_device *pdev) | |||
1832 | else | 1849 | else |
1833 | gpmc_irq = res->start; | 1850 | gpmc_irq = res->start; |
1834 | 1851 | ||
1835 | gpmc_l3_clk = clk_get(&pdev->dev, "fck"); | 1852 | gpmc_l3_clk = devm_clk_get(&pdev->dev, "fck"); |
1836 | if (IS_ERR(gpmc_l3_clk)) { | 1853 | if (IS_ERR(gpmc_l3_clk)) { |
1837 | dev_err(&pdev->dev, "error: clk_get\n"); | 1854 | dev_err(&pdev->dev, "Failed to get GPMC fck\n"); |
1838 | gpmc_irq = 0; | 1855 | gpmc_irq = 0; |
1839 | return PTR_ERR(gpmc_l3_clk); | 1856 | return PTR_ERR(gpmc_l3_clk); |
1840 | } | 1857 | } |
1841 | 1858 | ||
1859 | if (!clk_get_rate(gpmc_l3_clk)) { | ||
1860 | dev_err(&pdev->dev, "Invalid GPMC fck clock rate\n"); | ||
1861 | return -EINVAL; | ||
1862 | } | ||
1863 | |||
1842 | pm_runtime_enable(&pdev->dev); | 1864 | pm_runtime_enable(&pdev->dev); |
1843 | pm_runtime_get_sync(&pdev->dev); | 1865 | pm_runtime_get_sync(&pdev->dev); |
1844 | 1866 | ||
@@ -1878,7 +1900,6 @@ static int gpmc_probe(struct platform_device *pdev) | |||
1878 | rc = gpmc_probe_dt(pdev); | 1900 | rc = gpmc_probe_dt(pdev); |
1879 | if (rc < 0) { | 1901 | if (rc < 0) { |
1880 | pm_runtime_put_sync(&pdev->dev); | 1902 | pm_runtime_put_sync(&pdev->dev); |
1881 | clk_put(gpmc_l3_clk); | ||
1882 | dev_err(gpmc_dev, "failed to probe DT parameters\n"); | 1903 | dev_err(gpmc_dev, "failed to probe DT parameters\n"); |
1883 | return rc; | 1904 | return rc; |
1884 | } | 1905 | } |