~ubuntu-branches/ubuntu/utopic/linux-ti-omap/utopic

« back to all changes in this revision

Viewing changes to drivers/mtd/nand/ams-delta.c

  • Committer: Bazaar Package Importer
  • Author(s): Amit Kucheria, Amit Kucheria
  • Date: 2010-03-10 02:28:15 UTC
  • Revision ID: james.westby@ubuntu.com-20100310022815-7sd3gwvn5kenaq33
Tags: 2.6.33-500.1
[ Amit Kucheria ]

* Initial release of a 2.6.33-based OMAP kernel
* UBUNTU: [Upstream] Fix omap 1-wire driver compilation
* UBUNTU: ubuntu: AppArmor -- update to mainline 2010-03-04

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  drivers/mtd/nand/ams-delta.c
 
3
 *
 
4
 *  Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
 
5
 *
 
6
 *  Derived from drivers/mtd/toto.c
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or modify
 
9
 * it under the terms of the GNU General Public License version 2 as
 
10
 * published by the Free Software Foundation.
 
11
 *
 
12
 *  Overview:
 
13
 *   This is a device driver for the NAND flash device found on the
 
14
 *   Amstrad E3 (Delta).
 
15
 */
 
16
 
 
17
#include <linux/slab.h>
 
18
#include <linux/init.h>
 
19
#include <linux/module.h>
 
20
#include <linux/delay.h>
 
21
#include <linux/mtd/mtd.h>
 
22
#include <linux/mtd/nand.h>
 
23
#include <linux/mtd/partitions.h>
 
24
#include <asm/io.h>
 
25
#include <mach/hardware.h>
 
26
#include <asm/sizes.h>
 
27
#include <mach/gpio.h>
 
28
#include <plat/board-ams-delta.h>
 
29
 
 
30
/*
 
31
 * MTD structure for E3 (Delta)
 
32
 */
 
33
static struct mtd_info *ams_delta_mtd = NULL;
 
34
 
 
35
#define NAND_MASK (AMS_DELTA_LATCH2_NAND_NRE | AMS_DELTA_LATCH2_NAND_NWE | AMS_DELTA_LATCH2_NAND_CLE | AMS_DELTA_LATCH2_NAND_ALE | AMS_DELTA_LATCH2_NAND_NCE | AMS_DELTA_LATCH2_NAND_NWP)
 
36
 
 
37
/*
 
38
 * Define partitions for flash devices
 
39
 */
 
40
 
 
41
static struct mtd_partition partition_info[] = {
 
42
        { .name         = "Kernel",
 
43
          .offset       = 0,
 
44
          .size         = 3 * SZ_1M + SZ_512K },
 
45
        { .name         = "u-boot",
 
46
          .offset       = 3 * SZ_1M + SZ_512K,
 
47
          .size         = SZ_256K },
 
48
        { .name         = "u-boot params",
 
49
          .offset       = 3 * SZ_1M + SZ_512K + SZ_256K,
 
50
          .size         = SZ_256K },
 
51
        { .name         = "Amstrad LDR",
 
52
          .offset       = 4 * SZ_1M,
 
53
          .size         = SZ_256K },
 
54
        { .name         = "File system",
 
55
          .offset       = 4 * SZ_1M + 1 * SZ_256K,
 
56
          .size         = 27 * SZ_1M },
 
57
        { .name         = "PBL reserved",
 
58
          .offset       = 32 * SZ_1M - 3 * SZ_256K,
 
59
          .size         =  3 * SZ_256K },
 
60
};
 
61
 
 
62
static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
 
63
{
 
64
        struct nand_chip *this = mtd->priv;
 
65
 
 
66
        omap_writew(0, (OMAP1_MPUIO_BASE + OMAP_MPUIO_IO_CNTL));
 
67
        omap_writew(byte, this->IO_ADDR_W);
 
68
        ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE, 0);
 
69
        ndelay(40);
 
70
        ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE,
 
71
                               AMS_DELTA_LATCH2_NAND_NWE);
 
72
}
 
73
 
 
74
static u_char ams_delta_read_byte(struct mtd_info *mtd)
 
75
{
 
76
        u_char res;
 
77
        struct nand_chip *this = mtd->priv;
 
78
 
 
79
        ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE, 0);
 
80
        ndelay(40);
 
81
        omap_writew(~0, (OMAP1_MPUIO_BASE + OMAP_MPUIO_IO_CNTL));
 
82
        res = omap_readw(this->IO_ADDR_R);
 
83
        ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE,
 
84
                               AMS_DELTA_LATCH2_NAND_NRE);
 
85
 
 
86
        return res;
 
87
}
 
88
 
 
89
static void ams_delta_write_buf(struct mtd_info *mtd, const u_char *buf,
 
90
                                int len)
 
91
{
 
92
        int i;
 
93
 
 
94
        for (i=0; i<len; i++)
 
95
                ams_delta_write_byte(mtd, buf[i]);
 
96
}
 
97
 
 
98
static void ams_delta_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 
99
{
 
100
        int i;
 
101
 
 
102
        for (i=0; i<len; i++)
 
103
                buf[i] = ams_delta_read_byte(mtd);
 
104
}
 
105
 
 
106
static int ams_delta_verify_buf(struct mtd_info *mtd, const u_char *buf,
 
107
                                int len)
 
108
{
 
109
        int i;
 
110
 
 
111
        for (i=0; i<len; i++)
 
112
                if (buf[i] != ams_delta_read_byte(mtd))
 
113
                        return -EFAULT;
 
114
 
 
115
        return 0;
 
116
}
 
117
 
 
118
/*
 
119
 * Command control function
 
120
 *
 
121
 * ctrl:
 
122
 * NAND_NCE: bit 0 -> bit 2
 
123
 * NAND_CLE: bit 1 -> bit 7
 
124
 * NAND_ALE: bit 2 -> bit 6
 
125
 */
 
126
static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
 
127
                                unsigned int ctrl)
 
128
{
 
129
 
 
130
        if (ctrl & NAND_CTRL_CHANGE) {
 
131
                unsigned long bits;
 
132
 
 
133
                bits = (~ctrl & NAND_NCE) ? AMS_DELTA_LATCH2_NAND_NCE : 0;
 
134
                bits |= (ctrl & NAND_CLE) ? AMS_DELTA_LATCH2_NAND_CLE : 0;
 
135
                bits |= (ctrl & NAND_ALE) ? AMS_DELTA_LATCH2_NAND_ALE : 0;
 
136
 
 
137
                ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE |
 
138
                                AMS_DELTA_LATCH2_NAND_ALE |
 
139
                                AMS_DELTA_LATCH2_NAND_NCE, bits);
 
140
        }
 
141
 
 
142
        if (cmd != NAND_CMD_NONE)
 
143
                ams_delta_write_byte(mtd, cmd);
 
144
}
 
145
 
 
146
static int ams_delta_nand_ready(struct mtd_info *mtd)
 
147
{
 
148
        return gpio_get_value(AMS_DELTA_GPIO_PIN_NAND_RB);
 
149
}
 
150
 
 
151
/*
 
152
 * Main initialization routine
 
153
 */
 
154
static int __init ams_delta_init(void)
 
155
{
 
156
        struct nand_chip *this;
 
157
        int err = 0;
 
158
 
 
159
        /* Allocate memory for MTD device structure and private data */
 
160
        ams_delta_mtd = kmalloc(sizeof(struct mtd_info) +
 
161
                                sizeof(struct nand_chip), GFP_KERNEL);
 
162
        if (!ams_delta_mtd) {
 
163
                printk (KERN_WARNING "Unable to allocate E3 NAND MTD device structure.\n");
 
164
                err = -ENOMEM;
 
165
                goto out;
 
166
        }
 
167
 
 
168
        ams_delta_mtd->owner = THIS_MODULE;
 
169
 
 
170
        /* Get pointer to private data */
 
171
        this = (struct nand_chip *) (&ams_delta_mtd[1]);
 
172
 
 
173
        /* Initialize structures */
 
174
        memset(ams_delta_mtd, 0, sizeof(struct mtd_info));
 
175
        memset(this, 0, sizeof(struct nand_chip));
 
176
 
 
177
        /* Link the private data with the MTD structure */
 
178
        ams_delta_mtd->priv = this;
 
179
 
 
180
        /* Set address of NAND IO lines */
 
181
        this->IO_ADDR_R = (OMAP1_MPUIO_BASE + OMAP_MPUIO_INPUT_LATCH);
 
182
        this->IO_ADDR_W = (OMAP1_MPUIO_BASE + OMAP_MPUIO_OUTPUT);
 
183
        this->read_byte = ams_delta_read_byte;
 
184
        this->write_buf = ams_delta_write_buf;
 
185
        this->read_buf = ams_delta_read_buf;
 
186
        this->verify_buf = ams_delta_verify_buf;
 
187
        this->cmd_ctrl = ams_delta_hwcontrol;
 
188
        if (gpio_request(AMS_DELTA_GPIO_PIN_NAND_RB, "nand_rdy") == 0) {
 
189
                this->dev_ready = ams_delta_nand_ready;
 
190
        } else {
 
191
                this->dev_ready = NULL;
 
192
                printk(KERN_NOTICE "Couldn't request gpio for Delta NAND ready.\n");
 
193
        }
 
194
        /* 25 us command delay time */
 
195
        this->chip_delay = 30;
 
196
        this->ecc.mode = NAND_ECC_SOFT;
 
197
 
 
198
        /* Set chip enabled, but  */
 
199
        ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE |
 
200
                                          AMS_DELTA_LATCH2_NAND_NWE |
 
201
                                          AMS_DELTA_LATCH2_NAND_NCE |
 
202
                                          AMS_DELTA_LATCH2_NAND_NWP);
 
203
 
 
204
        /* Scan to find existance of the device */
 
205
        if (nand_scan(ams_delta_mtd, 1)) {
 
206
                err = -ENXIO;
 
207
                goto out_mtd;
 
208
        }
 
209
 
 
210
        /* Register the partitions */
 
211
        add_mtd_partitions(ams_delta_mtd, partition_info,
 
212
                           ARRAY_SIZE(partition_info));
 
213
 
 
214
        goto out;
 
215
 
 
216
 out_mtd:
 
217
        kfree(ams_delta_mtd);
 
218
 out:
 
219
        return err;
 
220
}
 
221
 
 
222
module_init(ams_delta_init);
 
223
 
 
224
/*
 
225
 * Clean up routine
 
226
 */
 
227
static void __exit ams_delta_cleanup(void)
 
228
{
 
229
        /* Release resources, unregister device */
 
230
        nand_release(ams_delta_mtd);
 
231
 
 
232
        /* Free the MTD device structure */
 
233
        kfree(ams_delta_mtd);
 
234
}
 
235
module_exit(ams_delta_cleanup);
 
236
 
 
237
MODULE_LICENSE("GPL");
 
238
MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
 
239
MODULE_DESCRIPTION("Glue layer for NAND flash on Amstrad E3 (Delta)");