Mercurial > flash_v2
diff packages/hal/powerpc/ppc40x/current/src/var_misc.c @ 1223:dbcfe4e0dbd2
New platform - TAMS MOAB - and generic changes to support it
| author | gthomas |
|---|---|
| date | Fri, 19 Sep 2003 17:11:18 +0000 |
| parents | d2c90368aeef |
| children |
line wrap: on
line diff
--- a/packages/hal/powerpc/ppc40x/current/src/var_misc.c +++ b/packages/hal/powerpc/ppc40x/current/src/var_misc.c @@ -9,6 +9,7 @@ // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2002, 2003 Gary Thomas // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -56,16 +57,35 @@ #define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS #include <cyg/hal/ppc_regs.h> #include <cyg/infra/cyg_type.h> - +#include <cyg/hal/hal_io.h> // I/O macros +#include <cyg/hal/hal_if.h> // Support (virtual vector) #include <cyg/hal/hal_mem.h> +#include <cyg/infra/diag.h> -void hal_ppc40x_clock_initialize(cyg_uint32 period); +#ifdef CYGPKG_IO_PCI +externC void hal_ppc405_pci_init(void); +#endif + +externC void hal_ppc40x_clock_initialize(cyg_uint32 period); +static void hal_ppc405_i2c_init(void); //-------------------------------------------------------------------------- void hal_variant_init(void) { + // Initialize I/O interfaces + hal_if_init(); + +#if defined(CYGHWR_HAL_POWERPC_PPC4XX_405) || defined(CYGHWR_HAL_POWERPC_PPC4XX_405GP) + // Initialize I2C controller + hal_ppc405_i2c_init(); +#endif + // Initialize real-time clock (for delays, etc, even if kernel doesn't use it) hal_ppc40x_clock_initialize(CYGNUM_HAL_RTC_PERIOD); + +#ifdef CYGPKG_IO_PCI + hal_ppc405_pci_init(); +#endif } @@ -96,26 +116,38 @@ cyg_hal_map_memory (int id, CYG_ADDRESS // There are 64 TLBs. max_tlbs = 64; - // Use the smallest "size" value which is big enough (round up) - for (sv = 0, lv = 0x400; sv < 8; sv++, lv <<= 2) { - if (lv >= size) break; - } + // May need to use more than one slot since the TLB can only + // map 16MB max. - // Note: the process ID comes from the PID register (always 0) - epn = (virt & M_EPN_EPNMASK) | M_EPN_EV | M_EPN_SIZE(sv); - rpn = (phys & M_RPN_RPNMASK) | M_RPN_EX | M_RPN_WR; + while (size > 0) { + // Use the smallest "size" value which is big enough (round up) + for (sv = 0, lv = 0x400; sv < 7; sv++, lv <<= 2) { + if (lv >= size) break; + } + + // Note: the process ID comes from the PID register (always 0) + epn = (virt & M_EPN_EPNMASK) | M_EPN_EV | M_EPN_SIZE(sv); + rpn = (phys & M_RPN_RPNMASK) | M_RPN_EX | M_RPN_WR; - if (flags & CYGARC_MEMDESC_CI) { - rpn |= M_RPN_I; - } + if (flags & CYGARC_MEMDESC_CI) { + rpn |= M_RPN_I; + } +#ifdef CYGSEM_HAL_DCACHE_STARTUP_MODE_WRITETHRU + // Only for cache-enabled regions + else { + rpn |= M_RPN_W; + } +#endif - if (flags & CYGARC_MEMDESC_GUARDED) - rpn |= M_RPN_G; + if (flags & CYGARC_MEMDESC_GUARDED) + rpn |= M_RPN_G; - CYGARC_TLBWE(id, epn, rpn); - id++; - - // Make caches default disabled when MMU is disabled. + CYGARC_TLBWE(id, epn, rpn); + id++; + size -= lv; + virt += lv; + phys += lv; + } return id; } @@ -193,23 +225,137 @@ hal_ppc40x_delay_us(int us) cyg_uint32 pit_val1, pit_val2; delay_period = (_period * us) / 10000; + delay_period = ((_period / 10000) * us); delay = 0; CYGARC_MFSPR(SPR_PIT, pit_val1); while (delay < delay_period) { // Wait for clock to "tick" while (true) { CYGARC_MFSPR(SPR_PIT, pit_val2); - if (pit_val2 != pit_val1) break; + if (pit_val1 != pit_val2) break; } - if (pit_val2 > pit_val1) { - diff = pit_val2 - pit_val1; + // The counter ticks down + if (pit_val2 < pit_val1) { + diff = pit_val1 - pit_val2; } else { - diff = (pit_val2 + _period) - pit_val1; + diff = (_period - pit_val2) + pit_val1; } delay += diff; pit_val1 = pit_val2; } } +#if defined(CYGHWR_HAL_POWERPC_PPC4XX_405) || defined(CYGHWR_HAL_POWERPC_PPC4XX_405GP) +//---------------------------------------------------------------------- +// I2C Support +static void +hal_ppc405_i2c_init(void) +{ + HAL_WRITE_UINT8(IIC0_CLKDIV, 6); // 66MHz + HAL_WRITE_UINT8(IIC0_STS, (IIC0_STS_SCMP|IIC0_STS_IRQA)); + HAL_WRITE_UINT8(IIC0_LMADR, 0); // Clear interface + HAL_WRITE_UINT8(IIC0_HMADR, 0); + HAL_WRITE_UINT8(IIC0_LSADR, 0); + HAL_WRITE_UINT8(IIC0_HSADR, 0); + HAL_WRITE_UINT8(IIC0_EXTSTS, (IIC0_EXTSTS_IRQP|IIC0_EXTSTS_IRQD)); + HAL_WRITE_UINT8(IIC0_MDCNTL, (IIC0_MDCNTL_FSDB|IIC0_MDCNTL_FMDB|IIC0_MDCNTL_EUBS)); +} + +externC bool +hal_ppc405_i2c_put_bytes(int addr, cyg_uint8 *val, int len) +{ + cyg_uint8 stat, extstat, xfrcnt, cmd, size; + int i, j; + + // The hardware can only move up to 4 bytes in a single operation + // This code breaks the request down into chunks of up to 4 bytes + // and checks the status after each chunk. + // Note: the actual device may impose additional size restrictions, + // e.g. some EEPROM devices may limit a single write to 32 bytes. + for (i = 0; i < len; i += size) { + HAL_WRITE_UINT8(IIC0_STS, (IIC0_STS_SCMP|IIC0_STS_IRQA)); + HAL_WRITE_UINT8(IIC0_EXTSTS, (IIC0_EXTSTS_IRQP|IIC0_EXTSTS_IRQD)); + HAL_WRITE_UINT8(IIC0_MDCNTL, (IIC0_MDCNTL_FSDB|IIC0_MDCNTL_FMDB)); + cmd = IIC0_CNTL_RW_WRITE|IIC0_CNTL_PT; + size = (len - i); + if (size > 4) { + size = 4; + cmd |= IIC0_CNTL_CHT; + } + cmd |= ((size-1)<<IIC0_CNTL_TCT_SHIFT); + for (j = 0; j < size; j++) { + HAL_WRITE_UINT8(IIC0_MDBUF, val[i+j]); + } + HAL_WRITE_UINT8(IIC0_LMADR, addr); + HAL_WRITE_UINT8(IIC0_CNTL, cmd); + while (true) { + CYGACC_CALL_IF_DELAY_US(10); // 10us + HAL_READ_UINT8(IIC0_STS, stat); + if ((stat & IIC0_STS_PT) == 0) { + if ((stat & IIC0_STS_ERR) != 0) { + // Some sort of error + HAL_READ_UINT8(IIC0_EXTSTS, extstat); + HAL_READ_UINT8(IIC0_XFRCNT, xfrcnt); + HAL_WRITE_UINT8(IIC0_EXTSTS, extstat); + HAL_WRITE_UINT8(IIC0_MDCNTL, (IIC0_MDCNTL_FSDB|IIC0_MDCNTL_FMDB)); + HAL_WRITE_UINT8(IIC0_STS, (IIC0_STS_SCMP|IIC0_STS_IRQA)); + diag_printf("%s addr: %x, len: %d, err: %x/%x, count: %d, cmd: %x\n", + __FUNCTION__, addr, len, stat, extstat, xfrcnt, cmd); + diag_printf("buf: "); + for (j = 0; j < size; j++) { + diag_printf("0x%02x ", val[i+j]); + } + diag_printf("\n"); + return false; + } + break; + } + } + } + return true; +} + +externC bool +hal_ppc405_i2c_get_bytes(int addr, cyg_uint8 *val, int len) +{ + cyg_uint8 stat, extstat, _val, cmd; + int i, j, size; + + for (i = 0; i < len; i += size) { + cmd = IIC0_CNTL_RW_READ|IIC0_CNTL_PT; + size = (len - i); + if (size > 4) { + size = 4; + cmd |= IIC0_CNTL_CHT; + } + cmd |= ((size-1)<<IIC0_CNTL_TCT_SHIFT); + HAL_WRITE_UINT8(IIC0_LMADR, addr); + HAL_WRITE_UINT8(IIC0_CNTL, cmd); + while (true) { + CYGACC_CALL_IF_DELAY_US(10); // 10us + HAL_READ_UINT8(IIC0_STS, stat); + if ((stat & IIC0_STS_PT) == 0) { + if ((stat & IIC0_STS_ERR) != 0) { + // Some sort of error + HAL_READ_UINT8(IIC0_EXTSTS, extstat); + HAL_WRITE_UINT8(IIC0_EXTSTS, extstat); + HAL_WRITE_UINT8(IIC0_MDCNTL, (IIC0_MDCNTL_FSDB|IIC0_MDCNTL_FMDB)); + HAL_WRITE_UINT8(IIC0_STS, (IIC0_STS_SCMP|IIC0_STS_IRQA)); + diag_printf("%s addr: %x, len: %d, err: %x/%x\n", + __FUNCTION__, addr, len, stat, extstat); + return false; + } + break; + } + } + for (j = 0; j < size; j++) { + HAL_READ_UINT8(IIC0_MDBUF, _val); + val[i+j] = _val; + } + } + return true; +} +#endif // 405 + //-------------------------------------------------------------------------- // End of var_misc.c
