]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/devs/flash/arm/mxc/v2_0/src/mxc_ata.c
Initial revision
[karo-tx-redboot.git] / packages / devs / flash / arm / mxc / v2_0 / src / mxc_ata.c
1 //==========================================================================
2 //
3 //      mxc_ata.c
4 //
5 //      Flash programming to support ATA flash on Freescale MXC platforms
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):    Mahesh Mahadevan <mahesh.mahadevan@freescale.com>
44 // Contributors: Mahesh Mahadevan <mahesh.mahadevan@freescale.com>
45 // Date:         2008-11-18 Initial version
46 //
47 //==========================================================================
48 //
49
50 #include <cyg/hal/hal_cache.h>
51 #include <stdlib.h>
52 #include <cyg/io/mxc_ata.h>
53 #include <redboot.h>
54
55 static struct fsl_ata_time_regs {
56     unsigned char time_off, time_on, time_1, time_2w;
57     unsigned char time_2r, time_ax, time_pio_rdx, time_4;
58     unsigned char time_9, time_m, time_jn, time_d;
59     unsigned char time_k, time_ack, time_env, time_rpx;
60     unsigned char time_zah, time_mlix, time_dvh, time_dzfs;
61     unsigned char time_dvs, time_cvh, time_ss, time_cyc;
62 };
63 extern void mxc_ata_iomux_setup(void);
64
65 /*
66  * This structure contains the timing parameters for
67  * ATA bus timing in the 5 PIO modes.  The timings
68  * are in nanoseconds, and are converted to clock
69  * cycles before being stored in the ATA controller
70  * timing registers.
71  */
72 static struct {
73     short t0, t1, t2_8, t2_16, t2i, t4, t9, tA;
74 } pio_specs[] = {
75     [0] = {
76     .t0 = 600, .t1 = 70, .t2_8 = 290, .t2_16 = 165, .t2i = 40, .t4 =
77         30, .t9 = 20, .tA = 50,},
78     [1] = {
79     .t0 = 383, .t1 = 50, .t2_8 = 290, .t2_16 = 125, .t2i = 0, .t4 =
80         20, .t9 = 15, .tA = 50,},
81     [2] = {
82     .t0 = 240, .t1 = 30, .t2_8 = 290, .t2_16 = 100, .t2i = 0, .t4 =
83         15, .t9 = 10, .tA = 50,},
84     [3] = {
85     .t0 = 180, .t1 = 30, .t2_8 = 80, .t2_16 = 80, .t2i = 0, .t4 =
86         10, .t9 = 10, .tA = 50,},
87     [4] = {
88     .t0 = 120, .t1 = 25, .t2_8 = 70, .t2_16 = 70, .t2i = 0, .t4 =
89         10, .t9 = 10, .tA = 50,},
90     };
91
92 #define NR_PIO_SPECS (sizeof pio_specs / sizeof pio_specs[0])
93
94 static void update_timing_config(struct fsl_ata_time_regs *tp)
95 {
96     unsigned int  *lp = (unsigned int  *) tp;
97     unsigned int  *ctlp = (unsigned int  *) ATA_BASE_ADDR;
98     int i;
99
100     for (i = 0; i < 5; i++) {
101         writel(*lp, ctlp);
102         lp++;
103         ctlp++;
104     }
105 }
106
107 static void set_ata_bus_timing(unsigned char xfer_mode)
108 {
109     int speed = xfer_mode;
110     struct fsl_ata_time_regs tr = { 0 };
111     int T = 1 * 1000 * 1000 * 1000 / get_main_clock(IPG_CLK);
112
113     if (speed >= NR_PIO_SPECS)
114         return;
115     tr.time_off = 3;
116     tr.time_on = 3;
117
118     tr.time_1 = (pio_specs[speed].t1 + T) / T;
119     tr.time_2w = (pio_specs[speed].t2_8 + T) / T;
120
121     tr.time_2r = (pio_specs[speed].t2_8 + T) / T;
122     tr.time_ax = (pio_specs[speed].tA + T) / T + 2;
123     tr.time_pio_rdx = 1;
124     tr.time_4 = (pio_specs[speed].t4 + T) / T;
125
126     tr.time_9 = (pio_specs[speed].t9 + T) / T;
127
128     update_timing_config(&tr);
129 }
130
131 static unsigned char ata_sff_busy_wait(unsigned int bits, unsigned int max, unsigned int delay)
132 {
133     unsigned char status;
134     unsigned int iterations = 1;
135
136     if (max != 0)
137         iterations = max;
138
139     do {
140         hal_delay_us(delay);
141         status = readb(ATA_BASE_ADDR + FSL_ATA_DCDR);
142         if (max != 0)
143             iterations--;
144     } while (status != 0xff && (status & bits) && (iterations > 0));
145
146     if (iterations == 0) {
147         diag_printf("ata_sff_busy_wait timeout status = %x\n", status);
148         return 0xff;
149     }
150
151     return status;
152 }
153
154 static void ata_sff_exec_command(unsigned short cmd)
155 {
156     writeb(cmd, ATA_BASE_ADDR + FSL_ATA_DCDR);
157     readb(ATA_BASE_ADDR + FSL_ATA_DRIVE_CONTROL);
158     hal_delay_us(4);
159 }
160
161 static int ata_dev_set_feature(unsigned int feature)
162 {
163     unsigned char status;
164
165     writeb(feature, ATA_BASE_ADDR + FSL_ATA_DFTR);
166     //Issue Set feature command
167     ata_sff_exec_command(ATA_CMD_SET_FEATURES);
168     status = ata_sff_busy_wait(ATA_BUSY, 5000, 500);
169
170     if (status == 0xff)
171         return 1;
172     if (status & ATA_ERR) {
173         return 1;
174     }
175     return 0;
176 }
177
178 void ata_id_string(int *id, unsigned char *s,
179                                  unsigned int ofs, unsigned int len)
180 {
181     unsigned int c;
182
183     while (len > 0) {
184         c = id[ofs] >> 8;
185         *s = c;
186         s++;
187
188         c = id[ofs] & 0xff;
189         *s = c;
190         s++;
191
192         ofs++;
193         len -= 2;
194     }
195 }
196
197 /**
198  *  ata_id_c_string - Convert IDENTIFY DEVICE page into C string
199  *  @id: IDENTIFY DEVICE results we will examine
200  *  @s: string into which data is output
201  *  @ofs: offset into identify device page
202  *  @len: length of string to return. must be an odd number.
203  *
204  *  This function is identical to ata_id_string except that it
205  *  trims trailing spaces and terminates the resulting string with
206  *  null.  @len must be actual maximum length (even number) + 1.
207  *
208  *  LOCKING:
209  *  caller.
210  */
211 void ata_id_c_string(int *id)
212 {
213     unsigned char model_num[ATA_ID_PROD_LEN + 1];
214
215     ata_id_string(id, model_num, ATA_ID_PROD, ATA_ID_PROD_LEN);
216
217     model_num[ATA_ID_PROD_LEN] = '\0';
218
219     diag_printf("ATA Model number = %s\n", model_num);
220 }
221
222 static int read_dev_id(void)
223 {
224     int i, tried_spinup = 0;
225     int CIS[256], err_mask = 0;
226
227 retry:
228
229     //identify device command
230     ata_sff_exec_command(ATA_CMD_ID_ATA);
231     if (ata_sff_busy_wait(ATA_BUSY, 5000, 500) == 0xff)
232         return 1;
233     memset((void *)CIS, 0, sizeof(int) * 256);
234
235     for (i=0 ; i < 256; i++ ) {
236         CIS[i] = readw(ATA_BASE_ADDR + FSL_ATA_DRIVE_DATA);
237     }
238
239     if ((CIS[0] & (1 << 15)) == 0) {
240         if (!tried_spinup && (CIS[2] == 0x37c8 || CIS[2] == 0x738c)) {
241             tried_spinup = 1;
242             err_mask = ata_dev_set_feature(0x7);
243             if (err_mask && CIS[2] != 0x738c) {
244                 diag_printf("ATA SPINUP Failed \n");
245                 goto err_out;
246             }
247             if (CIS[2] == 0x37c8)
248                 goto retry;
249         }
250         ata_id_c_string(CIS);
251         return 0;
252     } else {
253         diag_printf("ATA IDENTIFY DEVICE command Failed \n");
254     }
255 err_out:
256     return 1;
257 }
258
259 static void write_sector_pio(unsigned int *addr, int num_of_sectors)
260 {
261     int i, j;
262
263     for (i = 0; i < num_of_sectors; i++) {
264         for (j= 0; j < ATA_SECTOR_SIZE; j = j + 4) {
265             /* Write 4 bytes in each iteration */
266             writew((*addr & 0xFFFF), ATA_BASE_ADDR + FSL_ATA_DRIVE_DATA) ;
267             writew(((*addr >> 16 ) & 0xFFFF), ATA_BASE_ADDR + FSL_ATA_DRIVE_DATA) ;
268             addr++;
269         }
270         ata_sff_busy_wait(ATA_BUSY, 5000, 50);
271     }
272     readb(ATA_BASE_ADDR + FSL_ATA_DRIVE_CONTROL);
273 }
274
275 static void read_sector_pio(unsigned int *addr, int num_of_sectors)
276 {
277     int i, j;
278     unsigned int data[2];
279
280     for (i = 0; i < num_of_sectors; i++) {
281         for (j = 0; j < ATA_SECTOR_SIZE; j = j + 4) {
282             /* Read 4 bytes in each iteration */
283             data[0] = readw(ATA_BASE_ADDR + FSL_ATA_DRIVE_DATA);
284             data[1] = readw(ATA_BASE_ADDR + FSL_ATA_DRIVE_DATA);
285             *addr = ((data[1] << 16) & 0xFFFF0000) | (data[0] & 0xFFFF);
286             addr++;
287         }
288         ata_sff_busy_wait(ATA_BUSY, 5000, 10);
289     }
290     readb(ATA_BASE_ADDR + FSL_ATA_DRIVE_CONTROL);
291 }
292
293 void ata_hwr_init(void)
294 {
295     mxc_ata_iomux_setup();
296
297     /* Deassert the reset bit to enable the interface */
298     writel(FSL_ATA_CTRL_ATA_RST_B, ATA_BASE_ADDR + FSL_ATA_CONTROL);
299     writel(FSL_ATA_CTRL_ATA_RST_B | FSL_ATA_CTRL_FIFO_RST_B, ATA_BASE_ADDR + FSL_ATA_CONTROL);
300     /* Set initial timing and mode */
301     set_ata_bus_timing(PIO_XFER_MODE_4);
302     writeb(20, ATA_BASE_ADDR+ FSL_ATA_FIFO_ALARM) ; /* set fifo alarm to 20 halfwords, midway */
303
304     /* software reset */
305     writeb(ATA_IEN, ATA_BASE_ADDR + FSL_ATA_DRIVE_CONTROL);
306     hal_delay_us(20);
307     writeb(ATA_IEN | ATA_SRST, ATA_BASE_ADDR + FSL_ATA_DRIVE_CONTROL);
308     hal_delay_us(20);
309     writeb(ATA_IEN, ATA_BASE_ADDR + FSL_ATA_DRIVE_CONTROL);
310
311     writeb(0, ATA_BASE_ADDR + FSL_ATA_DDHR);
312     if (ata_sff_busy_wait(ATA_BUSY | ATA_DRQ, 6000, 1000) == 0xff) {
313         diag_printf("Failed to initialize the ATA drive\n");
314         return;
315     }
316
317     /* Read the device ID */
318     if (read_dev_id())
319         diag_printf("Failed to initialize the ATA drive\n");
320 }
321
322 static void ata_read_buf(int argc, char *argv[]);
323 RedBoot_cmd("ata_read",
324             "Read Ata",
325             "-f <flash_addr> -b <mem_base> -l <image_length>",
326             ata_read_buf
327            );
328
329 static void ata_program_buf(int argc, char *argv[]);
330 RedBoot_cmd("ata_write",
331             "Write Ata",
332             "-f <flash_addr> -b <mem_base> -l <image_length>",
333             ata_program_buf
334            );
335
336 static void ata_read_buf(int argc, char *argv[])
337 {
338     unsigned int total_sectors, num_of_sectors;
339     unsigned char lba_addr[4];
340     CYG_ADDRESS addr, data;
341     unsigned long sect_addr;
342     unsigned long len;
343     unsigned char status;
344     bool mem_addr_set = false;
345     bool flash_addr_set = false;
346     bool length_set = false;
347     struct option_info opts[3];
348
349     init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
350               (void *)&data, (bool *)&mem_addr_set, "memory base address");
351     init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM,
352               (void *)&addr, (bool *)&flash_addr_set, "FLASH memory base address");
353     init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM,
354               (void *)&len, (bool *)&length_set, "image length [in FLASH]");
355
356     if (!scan_opts(argc, argv, 1, opts, 3, 0, 0, 0)) {
357         diag_printf("invalid arguments");
358         return;
359     }
360
361     if (!mem_addr_set || !flash_addr_set || !length_set) {
362         diag_printf("required parameter missing\n");
363         return;
364     }
365
366     if ((addr % ATA_SECTOR_SIZE) != 0) {
367         diag_printf("Need a sector-aligned (512 byte) address in ATA\n\n");
368         return;
369     }
370
371     total_sectors = (len / ATA_SECTOR_SIZE);
372     sect_addr = addr / ATA_SECTOR_SIZE;
373
374     do {
375         lba_addr[0] = sect_addr & 0xFF;
376         lba_addr[1] = (sect_addr >> 8) & 0xFF;
377         lba_addr[2] = (sect_addr >> 16) & 0xFF;
378         /* Enable the LBA bit */
379         lba_addr[3] = (1 << 6) | ((sect_addr >> 24) & 0xF);
380
381         if (total_sectors >= MAX_NUMBER_OF_SECTORS)
382             num_of_sectors = 0;
383         else
384             num_of_sectors = total_sectors;
385
386         ata_sff_busy_wait(ATA_BUSY | ATA_DRQ, 5000, 50);
387         writeb(num_of_sectors, ATA_BASE_ADDR + FSL_ATA_DSCR);
388         writeb(lba_addr[0], ATA_BASE_ADDR + FSL_ATA_DSNR);
389         writeb(lba_addr[1], ATA_BASE_ADDR + FSL_ATA_DCLR);
390         writeb(lba_addr[2], ATA_BASE_ADDR + FSL_ATA_DCHR);
391         writeb(lba_addr[3], ATA_BASE_ADDR + FSL_ATA_DDHR);
392
393         //Issue Read command
394         ata_sff_exec_command(ATA_CMD_READ);
395         status = ata_sff_busy_wait(ATA_BUSY, 5000, 50);
396         if (status & ATA_ERR) {
397             diag_printf("Error while issuing ATA Read command\n");
398             return;
399         }
400         if (num_of_sectors == 0) {
401             read_sector_pio((unsigned int *)data, MAX_NUMBER_OF_SECTORS);
402             total_sectors -= MAX_NUMBER_OF_SECTORS;
403             sect_addr += MAX_NUMBER_OF_SECTORS;
404             data += (MAX_NUMBER_OF_SECTORS * ATA_SECTOR_SIZE);
405         } else {
406             read_sector_pio((unsigned int *)data, num_of_sectors);
407             total_sectors -= num_of_sectors;
408             sect_addr += num_of_sectors;
409             data += (num_of_sectors * ATA_SECTOR_SIZE);
410         }
411     } while (total_sectors > 0);
412 }
413
414 static void ata_program_buf(int argc, char *argv[])
415 {
416     int total_sectors, num_of_sectors, lba_addr[4];
417     CYG_ADDRESS addr, data;
418     unsigned long len;
419     unsigned long sect_addr;
420     unsigned char status;
421     bool mem_addr_set = false;
422     bool flash_addr_set = false;
423     bool length_set = false;
424     struct option_info opts[3];
425
426     init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
427               (void *)&data, (bool *)&mem_addr_set, "memory base address");
428     init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM,
429               (void *)&addr, (bool *)&flash_addr_set, "FLASH memory base address");
430     init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM,
431               (void *)&len, (bool *)&length_set, "image length [in FLASH]");
432
433     if (!scan_opts(argc, argv, 1, opts, 3, 0, 0, 0)) {
434         diag_printf("invalid arguments");
435         return;
436     }
437
438     if (!mem_addr_set || !flash_addr_set || !length_set) {
439         diag_printf("required parameter missing\n");
440         return;
441     }
442
443     if ((addr % ATA_SECTOR_SIZE) != 0) {
444         diag_printf("Need a sector-aligned (512 byte) address in ATA\n\n");
445         return;
446     }
447
448     total_sectors = (len / ATA_SECTOR_SIZE);
449     sect_addr = addr / ATA_SECTOR_SIZE;
450
451     do {
452         lba_addr[0] = sect_addr & 0xFF;
453         lba_addr[1] = (sect_addr >> 8) & 0xFF;
454         lba_addr[2] = (sect_addr >> 16) & 0xFF;
455         /* Enable the LBA bit */
456         lba_addr[3] = (1 << 6) | ((sect_addr >> 24) & 0xF);
457
458         if (total_sectors >= MAX_NUMBER_OF_SECTORS)
459             num_of_sectors = 0;
460         else
461             num_of_sectors = total_sectors;
462
463         ata_sff_busy_wait(ATA_BUSY | ATA_DRQ, 5000, 50);
464         writeb(num_of_sectors, ATA_BASE_ADDR + FSL_ATA_DSCR);
465         writeb(lba_addr[0], ATA_BASE_ADDR + FSL_ATA_DSNR);
466         writeb(lba_addr[1], ATA_BASE_ADDR + FSL_ATA_DCLR);
467         writeb(lba_addr[2], ATA_BASE_ADDR + FSL_ATA_DCHR);
468         writeb(lba_addr[3], ATA_BASE_ADDR + FSL_ATA_DDHR);
469
470         //Issue Write command
471         ata_sff_exec_command(ATA_CMD_WRITE);
472         ata_sff_busy_wait(ATA_BUSY, 5000, 50);
473         if (status & ATA_ERR) {
474             diag_printf("Error while issuing ATA Write command\n");
475             return;
476         }
477         if (num_of_sectors == 0) {
478             write_sector_pio((unsigned int *)data, MAX_NUMBER_OF_SECTORS);
479             total_sectors -= MAX_NUMBER_OF_SECTORS;
480             sect_addr += MAX_NUMBER_OF_SECTORS;
481             data += (MAX_NUMBER_OF_SECTORS * ATA_SECTOR_SIZE);
482         } else {
483             write_sector_pio((unsigned int *)data, num_of_sectors);
484             total_sectors -= num_of_sectors;
485             sect_addr += num_of_sectors;
486             data += (num_of_sectors * ATA_SECTOR_SIZE);
487         }
488     } while (total_sectors > 0);
489 }
490