aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/s3c2410.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/s3c2410.c')
-rw-r--r--drivers/mtd/nand/s3c2410.c75
1 files changed, 45 insertions, 30 deletions
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 33d832dddfdd..4405468f196b 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -55,7 +55,7 @@ static int hardware_ecc = 0;
55#endif 55#endif
56 56
57#ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP 57#ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP
58static int clock_stop = 1; 58static const int clock_stop = 1;
59#else 59#else
60static const int clock_stop = 0; 60static const int clock_stop = 0;
61#endif 61#endif
@@ -96,6 +96,12 @@ enum s3c_cpu_type {
96 TYPE_S3C2440, 96 TYPE_S3C2440,
97}; 97};
98 98
99enum s3c_nand_clk_state {
100 CLOCK_DISABLE = 0,
101 CLOCK_ENABLE,
102 CLOCK_SUSPEND,
103};
104
99/* overview of the s3c2410 nand state */ 105/* overview of the s3c2410 nand state */
100 106
101/** 107/**
@@ -111,6 +117,7 @@ enum s3c_cpu_type {
111 * @mtd_count: The number of MTDs created from this controller. 117 * @mtd_count: The number of MTDs created from this controller.
112 * @save_sel: The contents of @sel_reg to be saved over suspend. 118 * @save_sel: The contents of @sel_reg to be saved over suspend.
113 * @clk_rate: The clock rate from @clk. 119 * @clk_rate: The clock rate from @clk.
120 * @clk_state: The current clock state.
114 * @cpu_type: The exact type of this controller. 121 * @cpu_type: The exact type of this controller.
115 */ 122 */
116struct s3c2410_nand_info { 123struct s3c2410_nand_info {
@@ -129,6 +136,7 @@ struct s3c2410_nand_info {
129 int mtd_count; 136 int mtd_count;
130 unsigned long save_sel; 137 unsigned long save_sel;
131 unsigned long clk_rate; 138 unsigned long clk_rate;
139 enum s3c_nand_clk_state clk_state;
132 140
133 enum s3c_cpu_type cpu_type; 141 enum s3c_cpu_type cpu_type;
134 142
@@ -159,11 +167,33 @@ static struct s3c2410_platform_nand *to_nand_plat(struct platform_device *dev)
159 return dev->dev.platform_data; 167 return dev->dev.platform_data;
160} 168}
161 169
162static inline int allow_clk_stop(struct s3c2410_nand_info *info) 170static inline int allow_clk_suspend(struct s3c2410_nand_info *info)
163{ 171{
164 return clock_stop; 172 return clock_stop;
165} 173}
166 174
175/**
176 * s3c2410_nand_clk_set_state - Enable, disable or suspend NAND clock.
177 * @info: The controller instance.
178 * @new_state: State to which clock should be set.
179 */
180static void s3c2410_nand_clk_set_state(struct s3c2410_nand_info *info,
181 enum s3c_nand_clk_state new_state)
182{
183 if (!allow_clk_suspend(info) && new_state == CLOCK_SUSPEND)
184 return;
185
186 if (info->clk_state == CLOCK_ENABLE) {
187 if (new_state != CLOCK_ENABLE)
188 clk_disable(info->clk);
189 } else {
190 if (new_state == CLOCK_ENABLE)
191 clk_enable(info->clk);
192 }
193
194 info->clk_state = new_state;
195}
196
167/* timing calculations */ 197/* timing calculations */
168 198
169#define NS_IN_KHZ 1000000 199#define NS_IN_KHZ 1000000
@@ -333,8 +363,8 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
333 nmtd = this->priv; 363 nmtd = this->priv;
334 info = nmtd->info; 364 info = nmtd->info;
335 365
336 if (chip != -1 && allow_clk_stop(info)) 366 if (chip != -1)
337 clk_enable(info->clk); 367 s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
338 368
339 cur = readl(info->sel_reg); 369 cur = readl(info->sel_reg);
340 370
@@ -356,8 +386,8 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
356 386
357 writel(cur, info->sel_reg); 387 writel(cur, info->sel_reg);
358 388
359 if (chip == -1 && allow_clk_stop(info)) 389 if (chip == -1)
360 clk_disable(info->clk); 390 s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
361} 391}
362 392
363/* s3c2410_nand_hwcontrol 393/* s3c2410_nand_hwcontrol
@@ -694,8 +724,7 @@ static int s3c24xx_nand_remove(struct platform_device *pdev)
694 /* free the common resources */ 724 /* free the common resources */
695 725
696 if (info->clk != NULL && !IS_ERR(info->clk)) { 726 if (info->clk != NULL && !IS_ERR(info->clk)) {
697 if (!allow_clk_stop(info)) 727 s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
698 clk_disable(info->clk);
699 clk_put(info->clk); 728 clk_put(info->clk);
700 } 729 }
701 730
@@ -715,7 +744,6 @@ static int s3c24xx_nand_remove(struct platform_device *pdev)
715 return 0; 744 return 0;
716} 745}
717 746
718#ifdef CONFIG_MTD_PARTITIONS
719const char *part_probes[] = { "cmdlinepart", NULL }; 747const char *part_probes[] = { "cmdlinepart", NULL };
720static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, 748static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
721 struct s3c2410_nand_mtd *mtd, 749 struct s3c2410_nand_mtd *mtd,
@@ -725,7 +753,7 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
725 int nr_part = 0; 753 int nr_part = 0;
726 754
727 if (set == NULL) 755 if (set == NULL)
728 return add_mtd_device(&mtd->mtd); 756 return mtd_device_register(&mtd->mtd, NULL, 0);
729 757
730 mtd->mtd.name = set->name; 758 mtd->mtd.name = set->name;
731 nr_part = parse_mtd_partitions(&mtd->mtd, part_probes, &part_info, 0); 759 nr_part = parse_mtd_partitions(&mtd->mtd, part_probes, &part_info, 0);
@@ -735,19 +763,8 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
735 part_info = set->partitions; 763 part_info = set->partitions;
736 } 764 }
737 765
738 if (nr_part > 0 && part_info) 766 return mtd_device_register(&mtd->mtd, part_info, nr_part);
739 return add_mtd_partitions(&mtd->mtd, part_info, nr_part);
740
741 return add_mtd_device(&mtd->mtd);
742}
743#else
744static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
745 struct s3c2410_nand_mtd *mtd,
746 struct s3c2410_nand_set *set)
747{
748 return add_mtd_device(&mtd->mtd);
749} 767}
750#endif
751 768
752/** 769/**
753 * s3c2410_nand_init_chip - initialise a single instance of an chip 770 * s3c2410_nand_init_chip - initialise a single instance of an chip
@@ -947,7 +964,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
947 goto exit_error; 964 goto exit_error;
948 } 965 }
949 966
950 clk_enable(info->clk); 967 s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
951 968
952 /* allocate and map the resource */ 969 /* allocate and map the resource */
953 970
@@ -1026,9 +1043,9 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
1026 goto exit_error; 1043 goto exit_error;
1027 } 1044 }
1028 1045
1029 if (allow_clk_stop(info)) { 1046 if (allow_clk_suspend(info)) {
1030 dev_info(&pdev->dev, "clock idle support enabled\n"); 1047 dev_info(&pdev->dev, "clock idle support enabled\n");
1031 clk_disable(info->clk); 1048 s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
1032 } 1049 }
1033 1050
1034 pr_debug("initialised ok\n"); 1051 pr_debug("initialised ok\n");
@@ -1059,8 +1076,7 @@ static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm)
1059 1076
1060 writel(info->save_sel | info->sel_bit, info->sel_reg); 1077 writel(info->save_sel | info->sel_bit, info->sel_reg);
1061 1078
1062 if (!allow_clk_stop(info)) 1079 s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
1063 clk_disable(info->clk);
1064 } 1080 }
1065 1081
1066 return 0; 1082 return 0;
@@ -1072,7 +1088,7 @@ static int s3c24xx_nand_resume(struct platform_device *dev)
1072 unsigned long sel; 1088 unsigned long sel;
1073 1089
1074 if (info) { 1090 if (info) {
1075 clk_enable(info->clk); 1091 s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
1076 s3c2410_nand_inithw(info); 1092 s3c2410_nand_inithw(info);
1077 1093
1078 /* Restore the state of the nFCE line. */ 1094 /* Restore the state of the nFCE line. */
@@ -1082,8 +1098,7 @@ static int s3c24xx_nand_resume(struct platform_device *dev)
1082 sel |= info->save_sel & info->sel_bit; 1098 sel |= info->save_sel & info->sel_bit;
1083 writel(sel, info->sel_reg); 1099 writel(sel, info->sel_reg);
1084 1100
1085 if (allow_clk_stop(info)) 1101 s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
1086 clk_disable(info->clk);
1087 } 1102 }
1088 1103
1089 return 0; 1104 return 0;