2 * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
3 * Scott McNutt <smcnutt@psyent.com>
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 * Modified by Jai Dhar, FPS-Tech <contact@fps-tech.net>
25 * Modifications made to work with uClinux, linux 2.6.11 kernel
27 * TODO: - Add timeouts to while loops; kernel will stall if somethings
29 * - Possibly add verifying to writes?
39 /*-----------------------------------------------------------------------*/
40 /* Operation codes for serial configuration devices
42 #define EPCS_WRITE_ENA 0x06 /* Write enable */
43 #define EPCS_WRITE_DIS 0x04 /* Write disable */
44 #define EPCS_READ_STAT 0x05 /* Read status */
45 #define EPCS_READ_BYTES 0x03 /* Read bytes */
46 #define EPCS_READ_ID 0xab /* Read silicon id */
47 #define EPCS_WRITE_STAT 0x01 /* Write status */
48 #define EPCS_WRITE_BYTES 0x02 /* Write bytes */
49 #define EPCS_ERASE_BULK 0xc7 /* Erase entire device */
50 #define EPCS_ERASE_SECT 0xd8 /* Erase sector */
52 /* Device status register bits
54 #define EPCS_STATUS_WIP (1<<0) /* Write in progress */
55 #define EPCS_STATUS_WEL (1<<1) /* Write enable latch */
58 static nios_spi_t
*epcs
;
60 void epcs_print_regs(void)
62 printk(KERN_NOTICE
"Printing EPCS Registers\n");
63 printk(KERN_NOTICE
"rxdata: 0x%X, 0x%X\n",(u_int
) &epcs
->rxdata
,(u_int
) readl(&epcs
->rxdata
));
64 printk(KERN_NOTICE
"txdata: 0x%X, 0x%X\n",(u_int
) &epcs
->txdata
,(u_int
) readl(&epcs
->txdata
));
65 printk(KERN_NOTICE
"status: 0x%X, 0x%X\n",(u_int
) &epcs
->status
,(u_int
) readl(&epcs
->status
));
66 printk(KERN_NOTICE
"control: 0x%X, 0x%X\n",(u_int
) &epcs
->control
,(u_int
) readl(&epcs
->control
));
67 printk(KERN_NOTICE
"reserved: 0x%X, 0x%X\n",(u_int
) &epcs
->reserved
,(u_int
) readl(&epcs
->reserved
));
68 printk(KERN_NOTICE
"slaveselect: 0x%X, 0x%X\n",(u_int
) &epcs
->slaveselect
,(u_int
) readl(&epcs
->slaveselect
));
72 /***********************************************************************
74 ***********************************************************************/
75 static int epcs_cs (int assert)
82 printk(KERN_NOTICE
"epcs_cs: Asserting CS\n");
85 writel (NIOS_SPI_SSO
, &epcs
->control
);
89 printk(KERN_NOTICE
"epcs_cs: De-asserting CS\n");
92 /* Let all bits shift out */
93 while ((readl (&epcs
->status
) & NIOS_SPI_TMT
) == 0);
95 tmp
= readl (&epcs
->control
);
96 writel (0,&epcs
->control
);
105 static int epcs_tx (unsigned char c
)
109 status
= (u_int
)readl(&epcs
->status
);
112 printk(KERN_NOTICE
"epcs_tx: 0x%X, 0x%X, 0x%X\n",(u_int
) &epcs
->status
,status
,NIOS_SPI_TRDY
);
115 //start = get_timer (0);
116 while ((status
& NIOS_SPI_TRDY
) == 0)
118 status
= (u_int
)readl(&epcs
->status
);
121 /*if (get_timer (start) > EPCS_TIMEOUT)
123 writel (c
, &epcs
->txdata
);
127 static int epcs_rx (void)
131 status
= (u_int
)readl(&epcs
->status
);
134 printk(KERN_NOTICE
"epcs_rx: 0x%X, 0x%X, 0x%X\n",(u_int
) &epcs
->status
,status
,NIOS_SPI_RRDY
);
137 while ((status
& NIOS_SPI_RRDY
) == 0)
139 status
= (u_int
)readl(&epcs
->status
);
141 return (readl (&epcs
->rxdata
));
145 static unsigned char bitrev
[] = {
146 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e,
147 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f
152 static unsigned char epcs_bitrev (unsigned char c
)
157 val
|= bitrev
[c
& 0x0f]<<4;
161 static void epcs_rcv (unsigned char *dst
, int len
)
170 static void epcs_rrcv (unsigned char *dst
, int len
)
174 *dst
++ = epcs_bitrev (epcs_rx ());
179 static void epcs_snd (const unsigned char *src
, int len
)
188 static void epcs_rsnd (unsigned char *src
, int len
)
191 epcs_tx (epcs_bitrev (*src
++));
198 static void epcs_wr_enable (void)
201 epcs_tx (EPCS_WRITE_ENA
);
206 static unsigned char epcs_status_rd (void)
208 unsigned char status
;
211 epcs_tx (EPCS_READ_STAT
);
220 static void epcs_status_wr (unsigned char status
)
224 epcs_tx (EPCS_WRITE_STAT
);
233 /***********************************************************************
235 ***********************************************************************/
237 int epcs_reset (void)
239 /* When booting from an epcs controller, the epcs bootrom
240 * code may leave the slave select in an asserted state.
241 * This causes two problems: (1) The initial epcs access
242 * will fail -- not a big deal, and (2) a software reset
243 * will cause the bootrom code to hang since it does not
244 * ensure the select is negated prior to first access -- a
245 * big deal. Here we just negate chip select and everything
249 /* Assign base address */
250 epcs
= (nios_spi_t
*) ((na_epcs_controller
| 0x200) | 0x80000000);
251 /* Clear status and control registers */
254 writel(0,&epcs
->status
);
255 writel(0,&epcs
->control
);
256 writel(1,&epcs
->slaveselect
);
259 epcs_cs (0); /* Negate chip select */
265 u_char
epcs_dev_find (void)
267 unsigned char buf
[4];
271 printk(KERN_NOTICE
"epcs_dev_find()\n");
274 /* Read silicon id requires 3 "dummy bytes" before it's put
277 buf
[0] = EPCS_READ_ID
;
286 if (epcs_cs (0) == -1)
292 printk(KERN_NOTICE
"epcs_dev_find: Device ID: 0x%X\n",id
);
299 /* Find the info struct */
301 while (devinfo
[i
].name
) {
302 if (id
== devinfo
[i
].id
) {
313 /***********************************************************************
315 ***********************************************************************/
318 u_int
epcs_buf_erase (u_int off
, u_int len
, u_int sz
)
322 /* Erase the requested sectors. An address is required
323 * that lies within the requested sector -- we'll just
324 * use the first address in the sector.
328 /* Check if address is a sector */
329 printk(KERN_NOTICE
"epcs_erase(): off: 0x%X, len: 0x%X, sz: 0x%X\n",off
,len
,sz
);
332 if ((off
% sz
) || (len
% sz
))
334 printk(KERN_NOTICE
"epcs_erase: Address is not sector-aligned, halting!\n");
342 printk(KERN_NOTICE
"epcs_erase: Erasing 0x%X\n",off
);
345 buf
[0] = EPCS_ERASE_SECT
;
355 /* Wait for erase to complete */
356 while (epcs_status_rd() & EPCS_STATUS_WIP
);
366 int epcs_buf_read (u_char
*dst
, u_int off
, u_int cnt
)
371 buf
[0] = EPCS_READ_BYTES
;
378 //epcs_rrcv ((u_char *)addr, cnt);
388 int epcs_buf_write (const u_char
*addr
, u_int off
, u_int cnt
)
394 pgsz
= EPCS_PAGESIZE
;
397 printk(KERN_NOTICE
"epcs_buf_write(): 0x%X, 0x%X\n",cnt
,off
);
402 wrcnt
= pgsz
- (off
% pgsz
);
405 wrcnt
= (wrcnt
> cnt
) ? cnt
: wrcnt
;
407 buf
[0] = EPCS_WRITE_BYTES
;
413 printk(KERN_NOTICE
"epcs_buf_write: wrcnt: 0x%X, offset: 0x%X\n",wrcnt
,off
);
419 //epcs_rsnd ((unsigned char *)addr, wrcnt);
420 epcs_snd (addr
, wrcnt
);
423 /* Wait for write to complete */
424 while (epcs_status_rd() & EPCS_STATUS_WIP
);
437 int epcs_verify (ulong addr
, ulong off
, ulong cnt
, ulong
*err
)
440 unsigned char buf
[256];
441 unsigned char *start
,*end
;
444 start
= end
= (unsigned char *)addr
;
446 rdcnt
= (cnt
>sizeof(buf
)) ? sizeof(buf
) : cnt
;
447 epcs_read ((ulong
)buf
, off
, rdcnt
);
448 for (i
=0; i
<rdcnt
; i
++) {
449 if (*end
!= buf
[i
]) {
461 static int epcs_sect_erased (int sect
, unsigned *offset
,
462 struct epcs_devinfo_t
*dev
)
464 unsigned char buf
[128];
469 sectsz
= (1 << dev
->sz_sect
);
474 epcs_read ((ulong
)buf
, off
, sizeof(buf
));
475 for (i
=0; i
< sizeof(buf
); i
++) {
476 if (buf
[i
] != 0xff) {