~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/mtd/nand/s3c2410.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
55
55
#endif
56
56
 
57
57
#ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP
58
 
static int clock_stop = 1;
 
58
static const int clock_stop = 1;
59
59
#else
60
60
static const int clock_stop = 0;
61
61
#endif
96
96
        TYPE_S3C2440,
97
97
};
98
98
 
 
99
enum s3c_nand_clk_state {
 
100
        CLOCK_DISABLE   = 0,
 
101
        CLOCK_ENABLE,
 
102
        CLOCK_SUSPEND,
 
103
};
 
104
 
99
105
/* overview of the s3c2410 nand state */
100
106
 
101
107
/**
111
117
 * @mtd_count: The number of MTDs created from this controller.
112
118
 * @save_sel: The contents of @sel_reg to be saved over suspend.
113
119
 * @clk_rate: The clock rate from @clk.
 
120
 * @clk_state: The current clock state.
114
121
 * @cpu_type: The exact type of this controller.
115
122
 */
116
123
struct s3c2410_nand_info {
129
136
        int                             mtd_count;
130
137
        unsigned long                   save_sel;
131
138
        unsigned long                   clk_rate;
 
139
        enum s3c_nand_clk_state         clk_state;
132
140
 
133
141
        enum s3c_cpu_type               cpu_type;
134
142
 
159
167
        return dev->dev.platform_data;
160
168
}
161
169
 
162
 
static inline int allow_clk_stop(struct s3c2410_nand_info *info)
 
170
static inline int allow_clk_suspend(struct s3c2410_nand_info *info)
163
171
{
164
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
 */
 
180
static 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
197
/* timing calculations */
168
198
 
169
199
#define NS_IN_KHZ 1000000
333
363
        nmtd = this->priv;
334
364
        info = nmtd->info;
335
365
 
336
 
        if (chip != -1 && allow_clk_stop(info))
337
 
                clk_enable(info->clk);
 
366
        if (chip != -1)
 
367
                s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
338
368
 
339
369
        cur = readl(info->sel_reg);
340
370
 
356
386
 
357
387
        writel(cur, info->sel_reg);
358
388
 
359
 
        if (chip == -1 && allow_clk_stop(info))
360
 
                clk_disable(info->clk);
 
389
        if (chip == -1)
 
390
                s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
361
391
}
362
392
 
363
393
/* s3c2410_nand_hwcontrol
694
724
        /* free the common resources */
695
725
 
696
726
        if (info->clk != NULL && !IS_ERR(info->clk)) {
697
 
                if (!allow_clk_stop(info))
698
 
                        clk_disable(info->clk);
 
727
                s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
699
728
                clk_put(info->clk);
700
729
        }
701
730
 
715
744
        return 0;
716
745
}
717
746
 
718
 
#ifdef CONFIG_MTD_PARTITIONS
719
747
const char *part_probes[] = { "cmdlinepart", NULL };
720
748
static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
721
749
                                      struct s3c2410_nand_mtd *mtd,
725
753
        int nr_part = 0;
726
754
 
727
755
        if (set == NULL)
728
 
                return add_mtd_device(&mtd->mtd);
 
756
                return mtd_device_register(&mtd->mtd, NULL, 0);
729
757
 
730
758
        mtd->mtd.name = set->name;
731
759
        nr_part = parse_mtd_partitions(&mtd->mtd, part_probes, &part_info, 0);
735
763
                part_info = set->partitions;
736
764
        }
737
765
 
738
 
        if (nr_part > 0 && part_info)
739
 
                return add_mtd_partitions(&mtd->mtd, part_info, nr_part);
740
 
 
741
 
        return add_mtd_device(&mtd->mtd);
742
 
}
743
 
#else
744
 
static 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
 
}
750
 
#endif
 
766
        return mtd_device_register(&mtd->mtd, part_info, nr_part);
 
767
}
751
768
 
752
769
/**
753
770
 * s3c2410_nand_init_chip - initialise a single instance of an chip
947
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
969
        /* allocate and map the resource */
953
970
 
1026
1043
                goto exit_error;
1027
1044
        }
1028
1045
 
1029
 
        if (allow_clk_stop(info)) {
 
1046
        if (allow_clk_suspend(info)) {
1030
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
1051
        pr_debug("initialised ok\n");
1059
1076
 
1060
1077
                writel(info->save_sel | info->sel_bit, info->sel_reg);
1061
1078
 
1062
 
                if (!allow_clk_stop(info))
1063
 
                        clk_disable(info->clk);
 
1079
                s3c2410_nand_clk_set_state(info, CLOCK_DISABLE);
1064
1080
        }
1065
1081
 
1066
1082
        return 0;
1072
1088
        unsigned long sel;
1073
1089
 
1074
1090
        if (info) {
1075
 
                clk_enable(info->clk);
 
1091
                s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
1076
1092
                s3c2410_nand_inithw(info);
1077
1093
 
1078
1094
                /* Restore the state of the nFCE line. */
1082
1098
                sel |= info->save_sel & info->sel_bit;
1083
1099
                writel(sel, info->sel_reg);
1084
1100
 
1085
 
                if (allow_clk_stop(info))
1086
 
                        clk_disable(info->clk);
 
1101
                s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
1087
1102
        }
1088
1103
 
1089
1104
        return 0;