1 //==========================================================================
5 // HAL misc board support code for ARM Industrial Module AIM 711
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.
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.
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
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.
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.
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.
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####
44 // Contributors: gthomas, jskov, r.cassebohm
45 // Michael Checky <Michael_Checky@ThermoKing.com>
46 // Grant Edwards <grante@visi.com>
48 // Purpose: HAL board support
49 // Description: Implementations of HAL board interfaces
51 //####DESCRIPTIONEND####
53 //========================================================================*/
55 #include <pkgconf/hal.h>
57 #include <cyg/infra/cyg_type.h> // base types
58 #include <cyg/infra/cyg_trac.h> // tracing macros
59 #include <cyg/infra/cyg_ass.h> // assertion macros
60 #include <cyg/infra/diag.h> // diag_printf()
62 #include <cyg/hal/hal_io.h> // IO macros
63 #include <cyg/hal/hal_arch.h> // Register state info
64 #include <cyg/hal/hal_diag.h>
65 #include <cyg/hal/hal_cache.h>
66 #include <cyg/hal/hal_intr.h> // necessary?
67 #include <cyg/hal/hal_if.h> // calling interface
68 #include <cyg/hal/hal_misc.h> // helper functions
69 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
70 #include <cyg/hal/drv_api.h> // HAL ISR support
73 #include <pkgconf/system.h>
76 #define MIN(_x_,_y_) ((_x_) < (_y_) ? (_x_) : (_y_))
79 #define MAX(_x_,_y_) ((_x_) > (_y_) ? (_x_) : (_y_))
82 //======================================================================
83 // Use Timer0 for kernel clock
85 static cyg_uint32 _period;
87 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
88 #if 0 // Not supported yet
89 static cyg_interrupt abort_interrupt;
90 static cyg_handle_t abort_interrupt_handle;
92 // This ISR is called only for the Abort button interrupt
94 ks32c_abort_isr(cyg_vector_t vector, cyg_addrword_t data, HAL_SavedRegisters *regs)
96 cyg_hal_user_break((CYG_ADDRWORD*)regs);
97 cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_EXT2);
98 return 0; // No need to run DSR
103 void hal_clock_initialize(cyg_uint32 period)
105 cyg_uint32 tmod, clkcon;
108 HAL_READ_UINT32(KS32C_TMOD, tmod);
109 tmod &= ~(KS32C_TMOD_TE0);
110 HAL_WRITE_UINT32(KS32C_TMOD, 0);
112 tmod &= ~(KS32C_TMOD_TMD0 | KS32C_TMOD_TCLR0);
113 tmod |= KS32C_TMOD_TE0;
116 HAL_READ_UINT32(KS32C_CLKCON, clkcon);
117 period = period/((clkcon & 0xffff) + 1);
118 HAL_WRITE_UINT32(KS32C_TDATA0, period);
121 HAL_WRITE_UINT32(KS32C_TMOD, tmod);
125 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
126 #if 0 // Not supported yet
127 cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_EXT2,
129 0, // Data item passed to interrupt handler
132 &abort_interrupt_handle,
134 cyg_drv_interrupt_attach(abort_interrupt_handle);
135 cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_EXT2);
140 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
145 void hal_clock_read(cyg_uint32 *pvalue)
149 HAL_READ_UINT32(KS32C_TCNT0, value);
150 *pvalue = _period - value;
154 hal_ks32c_i2c_init(void);
156 //======================================================================
157 // Interrupt controller stuff
159 void hal_hardware_init(void)
161 cyg_uint32 intmask, syscfg, val;
163 // Setup external IO timing
164 // Timing for Ext0 is for external 16550 UART, all other are default values
165 val = ( KS32C_EXTACON_INIT(1,1,3,0) << KS32C_EXTACON0_EXT0_shift ) \
166 | ( KS32C_EXTACON_INIT(1,1,3,1) << KS32C_EXTACON0_EXT1_shift );
167 HAL_WRITE_UINT32(KS32C_EXTACON0, val);
168 val = ( KS32C_EXTACON_INIT(1,1,3,1) << KS32C_EXTACON1_EXT2_shift ) \
169 | ( KS32C_EXTACON_INIT(1,1,3,1) << KS32C_EXTACON1_EXT3_shift );
170 HAL_WRITE_UINT32(KS32C_EXTACON1, val);
173 HAL_READ_UINT32(KS32C_IOPMOD, val);
174 val |= (AIM711_GPIO_DOUT0_DAK0|AIM711_GPIO_DOUT1_DAK1 \
175 |AIM711_GPIO_DOUT2_TO0|AIM711_GPIO_DOUT3_TO1 \
176 |AIM711_GPIO_POWERLED);
177 HAL_WRITE_UINT32(KS32C_IOPMOD, val);
180 AIM711_GPIO_SET(AIM711_GPIO_POWERLED);
182 // Enable XIRQ0 for external 16550 UART
183 HAL_READ_UINT32(KS32C_IOPCON, val);
184 val &= ~( KS32C_IOPCON_XIRQ_MASK << KS32C_IOPCON_XIRQ0_shift );
185 val |= ( KS32C_IOPCON_XIRQ_LEVEL|KS32C_IOPCON_XIRQ_AKTIV_HI| \
186 KS32C_IOPCON_XIRQ_ENABLE ) << KS32C_IOPCON_XIRQ0_shift ;
187 HAL_WRITE_UINT32(KS32C_IOPCON, val);
189 // Set up eCos/ROM interfaces
193 HAL_READ_UINT32(KS32C_SYSCFG, syscfg);
194 syscfg &= ~KS32C_SYSCFG_CM_MASK;
195 syscfg |= KS32C_SYSCFG_CM_0R_8C|KS32C_SYSCFG_WE;
196 HAL_WRITE_UINT32(KS32C_SYSCFG, syscfg);
197 HAL_UCACHE_INVALIDATE_ALL();
201 hal_ks32c_i2c_init();
203 // Clear global interrupt mask bit
204 HAL_READ_UINT32(KS32C_INTMSK, intmask);
205 intmask &= ~KS32C_INTMSK_GLOBAL;
206 HAL_WRITE_UINT32(KS32C_INTMSK, intmask);
209 // This routine is called to respond to a hardware interrupt (IRQ). It
210 // should interrogate the hardware and return the IRQ vector number.
212 int hal_IRQ_handler(void)
214 // Do hardware-level IRQ handling
215 cyg_uint32 irq_status;
216 HAL_READ_UINT32(KS32C_INTOFFSET_IRQ, irq_status);
217 irq_status = irq_status / 4;
218 if (CYGNUM_HAL_ISR_MAX >= irq_status)
220 // It's a bit bogus to test for FIQs after IRQs, but we use the
221 // latter more, so don't impose the overhead of checking for FIQs
222 HAL_READ_UINT32(KS32C_INTOFFSET_FIQ, irq_status);
223 irq_status = irq_status / 4;
224 if (CYGNUM_HAL_ISR_MAX >= irq_status)
226 return CYGNUM_HAL_INTERRUPT_NONE;
229 // -------------------------------------------------------------------------
234 void hal_interrupt_mask(int vector)
236 cyg_uint32 mask, old_mask;
237 HAL_READ_UINT32(KS32C_INTMSK, mask);
240 HAL_WRITE_UINT32(KS32C_INTMSK, mask);
243 void hal_interrupt_unmask(int vector)
245 cyg_uint32 mask, old_mask;
246 HAL_READ_UINT32(KS32C_INTMSK, mask);
248 mask &= ~(1<<vector);
249 HAL_WRITE_UINT32(KS32C_INTMSK, mask);
252 void hal_interrupt_acknowledge(int vector)
254 HAL_WRITE_UINT32(KS32C_INTPND, (1<<vector));
257 void hal_interrupt_configure(int vector, int level, int up)
261 void hal_interrupt_set_level(int vector, int level)
265 void hal_show_IRQ(int vector, int data, int handler)
269 // -------------------------------------------------------------------------
271 // Delay for some number of micro-seconds
273 void hal_delay_us(cyg_int32 usecs)
276 cyg_uint32 ticks = ((CYGNUM_HAL_RTC_PERIOD*CYGNUM_HAL_RTC_DENOMINATOR)/1000000) * usecs;
280 HAL_READ_UINT32(KS32C_TMOD, tmod);
281 tmod &= ~(KS32C_TMOD_TE1);
282 HAL_WRITE_UINT32(KS32C_TMOD, tmod);
284 tmod &= ~(KS32C_TMOD_TMD1 | KS32C_TMOD_TCLR1);
285 tmod |= KS32C_TMOD_TE1;
287 // Clear pending flag
288 HAL_WRITE_UINT32(KS32C_INTPND, (1 << CYGNUM_HAL_INTERRUPT_TIMER1));
291 HAL_WRITE_UINT32(KS32C_TDATA1, ticks);
294 HAL_WRITE_UINT32(KS32C_TMOD, tmod);
296 // Wait for timer to underflow. Can't test the timer completion
297 // bit without actually enabling the interrupt. So instead watch
299 ticks /= 2; // wait for this threshold
301 // Wait till timer counts below threshold
303 HAL_READ_UINT32(KS32C_TCNT1, count);
304 } while (count >= ticks);
305 // then wait for it to be reloaded
307 HAL_READ_UINT32(KS32C_TCNT1, count);
308 } while (count < ticks);
310 // Then disable timer 1 again
311 tmod &= ~KS32C_TMOD_TE1;
312 HAL_WRITE_UINT32(KS32C_TMOD, tmod);
315 // -------------------------------------------------------------------------
317 // To reset the AIM 711, set P3 to low, which is connected to the reset
323 CYG_INTERRUPT_STATE old;
325 CYGACC_CALL_IF_DELAY_US(100000);
328 HAL_READ_UINT32(KS32C_IOPMOD, value);
329 value |= AIM711_GPIO_RESET;
330 HAL_WRITE_UINT32(KS32C_IOPMOD, value);
333 AIM711_GPIO_CLR(AIM711_GPIO_RESET);
335 HAL_DISABLE_INTERRUPTS(old);
340 //----------------------------------------------------------------------
346 #include <cyg/hal/drv_api.h>
350 #define I2C_STATUS_SUCCESS (ENOERR)
351 #define I2C_STATUS_MUTEX (-EINTR)
352 #define I2C_STATUS_BUSY (-EBUSY)
353 #define I2C_STATUS_ADDR_NAK (-1000)
354 #define I2C_STATUS_DATA_NAK (-1001)
356 #define I2C_STATUS_SUCCESS (0)
357 #define I2C_STATUS_MUTEX (-1)
358 #define I2C_STATUS_BUSY (-1)
359 #define I2C_STATUS_ADDR_NAK (-1)
360 #define I2C_STATUS_DATA_NAK (-1)
363 static cyg_drv_mutex_t i2c_mutex;
365 // Initialize the I2C bus controller.
367 hal_ks32c_i2c_init(void)
369 cyg_uint32 prescale = KS32C_I2C_FREQ(100000);
371 // reset the bus controller
372 HAL_WRITE_UINT32(KS32C_I2CCON, KS32C_I2C_CON_RESET);
374 // set the bus frequency
375 HAL_WRITE_UINT32(KS32C_I2CPS, prescale);
377 cyg_drv_mutex_init(&i2c_mutex);
380 #define RETURN(_x_) \
382 diag_printf("%s: line %d error=%d\n",__FUNCTION__,__LINE__,(_x_)); \
386 // Transfer the I2C messages.
388 hal_ks32c_i2c_transfer(cyg_uint32 nmsg, hal_ks32c_i2c_msg_t* pmsgs)
392 // serialize access to the I2C bus
393 if (!cyg_drv_mutex_lock(&i2c_mutex))
395 RETURN(I2C_STATUS_MUTEX);
401 HAL_READ_UINT32(KS32C_I2CCON, i2ccon);
402 } while (i2ccon & KS32C_I2C_CON_BUSY);
404 // transfer the messages
405 for (; nmsg > 0; --nmsg, ++pmsgs)
407 // generate the start condition
408 HAL_WRITE_UINT32(KS32C_I2CCON, KS32C_I2C_CON_START);
410 // send the device address
411 HAL_WRITE_UINT32(KS32C_I2CBUF, pmsgs->devaddr);
414 HAL_READ_UINT32(KS32C_I2CCON, i2ccon);
415 } while ((i2ccon & KS32C_I2C_CON_BF) == 0);
417 // check if the slave ACK'ed the device address
418 if (i2ccon & KS32C_I2C_CON_LRB)
420 // generate the stop condition
421 HAL_WRITE_UINT32(KS32C_I2CCON, KS32C_I2C_CON_STOP);
422 cyg_drv_mutex_unlock(&i2c_mutex);
423 RETURN(I2C_STATUS_ADDR_NAK);
426 // read the message ?
427 if (pmsgs->devaddr & KS32C_I2C_RD)
429 cyg_uint8* pbuf = pmsgs->pbuf;
430 cyg_uint32 bufsize = pmsgs->bufsize;
433 // read more than one byte ?
437 HAL_WRITE_UINT32(KS32C_I2CCON, KS32C_I2C_CON_ACK);
439 while (bufsize-- > 0)
443 HAL_READ_UINT32(KS32C_I2CCON, i2ccon);
444 } while ((i2ccon & KS32C_I2C_CON_BF) == 0);
446 // read the data byte
447 HAL_READ_UINT32(KS32C_I2CBUF, i2cbuf);
453 HAL_WRITE_UINT32(KS32C_I2CCON, 0);
456 HAL_READ_UINT32(KS32C_I2CCON, i2ccon);
457 } while ((i2ccon & KS32C_I2C_CON_BF) == 0);
459 // read the data byte
460 HAL_READ_UINT32(KS32C_I2CBUF, i2cbuf);
469 for (i = 0; i < pmsgs->bufsize; ++i)
471 HAL_WRITE_UINT32(KS32C_I2CBUF, pmsgs->pbuf[i]);
474 HAL_READ_UINT32(KS32C_I2CCON, i2ccon);
475 } while ((i2ccon & KS32C_I2C_CON_BF) == 0);
477 // check if the slave ACK'ed the data byte
478 if (i2ccon & KS32C_I2C_CON_LRB)
480 // generate the stop condition
481 HAL_WRITE_UINT32(KS32C_I2CCON, KS32C_I2C_CON_STOP);
482 cyg_drv_mutex_unlock(&i2c_mutex);
483 RETURN(I2C_STATUS_DATA_NAK);
488 // generate a restart condition ?
491 HAL_WRITE_UINT32(KS32C_I2CCON, KS32C_I2C_CON_RESTART);
495 // generate the stop condition
496 HAL_WRITE_UINT32(KS32C_I2CCON, KS32C_I2C_CON_STOP);
498 cyg_drv_mutex_unlock(&i2c_mutex);
499 return I2C_STATUS_SUCCESS;
502 //----------------------------------------------------------------------
507 int hal_aim711_eeprom_write(cyg_uint8 *buf, int offset, int len)
509 cyg_uint8 addr_page[1 + AIM711_EEPROM_PAGESIZE];
510 cyg_uint8 const* pbufbyte = (cyg_uint8 const*)buf;
511 hal_ks32c_i2c_msg_t msg;
515 if (offset > AIM711_EEPROM_SIZE)
518 if (len > (AIM711_EEPROM_SIZE - offset))
519 len = (AIM711_EEPROM_SIZE - offset);
524 msg.devaddr = AIM711_EEPROM_ADDR | KS32C_I2C_WR;
525 msg.pbuf = addr_page;
532 // write at most a page at a time
533 nbytes = MIN(bufsize, AIM711_EEPROM_PAGESIZE);
535 // don't cross a page boundary
536 if (addr%AIM711_EEPROM_PAGESIZE)
538 nbytes = MIN(nbytes, AIM711_EEPROM_PAGESIZE - addr%AIM711_EEPROM_PAGESIZE);
541 // build the write message
543 memcpy(&addr_page[1], pbufbyte, nbytes);
544 msg.bufsize = nbytes + 1;
549 // transfer the message
550 status = hal_ks32c_i2c_transfer(1, &msg);
551 if (status != I2C_STATUS_SUCCESS)
557 CYGACC_CALL_IF_DELAY_US(10000);
563 int hal_aim711_eeprom_read(cyg_uint8 *buf, int offset, int len)
565 hal_ks32c_i2c_msg_t msgs[2];
569 if (offset > AIM711_EEPROM_SIZE)
572 if (len > (AIM711_EEPROM_SIZE - offset))
573 len = (AIM711_EEPROM_SIZE - offset);
577 // write message to set the address
578 msgs[0].devaddr = AIM711_EEPROM_ADDR | KS32C_I2C_WR;
579 msgs[0].pbuf = &toffset;
580 msgs[0].bufsize = sizeof(toffset);
583 msgs[1].devaddr = AIM711_EEPROM_ADDR | KS32C_I2C_RD;
585 msgs[1].bufsize = len;
587 // transfer the messages
588 status = hal_ks32c_i2c_transfer(2, msgs);
596 //-----------------------------------------------------------------------------