Modifications for 1.1.6:
======================================================================
+* Patch by Dave Ellis, 13 Apr 2002:
+ - fix debug print in common/soft_i2c.c
+ - fix missing initialization of idata on 8xx
+ - fix eeprom command for EEPROMS with 2 byte addresses
+
+* Added M41T11 RTC driver
+ Patch by Andrew May, 2 Apr 2002
+
+* Changed MAC handling for Redundand Ethernet Interfaces; see README
+
+* Add DiskOnChip Support for PM826
+
* Fix I2C driver for PM826, CPU86, and TQM8260
* Add configuration options for PM826 and CPU86 boards to boot either
sbc8260 MPC8260
gw8260 MPC8260
+Dave Ellis <DGE@sixnetio.com>
+
+ SXNI855T MPC8xx
+
-------------------------------------------------------------------------
Unknown / orphaned boards:
NX823 MPC8xx
RPXClassic MPC8xx
RPXlite MPC8xx
- SXNI855T MPC8xx
CRAYL1 PPC4xx
ERIC PPC4xx
only effect after the next boot (yes, that's just like Windoze :-).
+Note for Redundand Ethernet Interfaces:
+=======================================
+
+Some boards come with redundand ethernet interfaces; PPCBoot supports
+such configurations and is capable of automatic selection of a
+"working" interface when needed. MAC assignemnt works as follows:
+
+Network interfaces are numbered eth0, eth1, eth2, ... Corresponding
+MAC addresses can be stored in the environment as "ethaddr" (=>eth0),
+"eth1addr" (=>eth1), "eth2addr", ...
+
+If the network interface stores some valid MAC address (for instance
+in SROM), this is used as default address if there is NO correspon-
+ding setting in the environment; if the corresponding environment
+variable is set, this overrides the settings in the card; that means:
+
+o If the SROM has a valid MAC address, and there is no address in the
+ environment, the SROM's address is used.
+
+o If there is no valid address in the SROM, and a definition in the
+ environment exists, then the value from the environment variable is
+ used.
+
+o If both the SROM and the environment contain a MAC address, and
+ both addresses are the same, this MAC address is used.
+
+o If both the SROM and the environment contain a MAC address, and the
+ addresses differ, the value from the environment is used and a
+ warning is printed.
+
+o If neither SROM nor the environment contain a MAC address, an error
+ is raised.
+
+
Image Formats:
==============
/* Static FLASH Bank configuration here (only one bank) */
size_b0 = flash_int_get_size ((ulong *) CFG_FLASH_BASE, &flash_info[0]);
- if (flash_info[0].flash_id == FLASH_UNKNOWN || size_b0 == 0) {
- printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
- size_b0, size_b0 >> 20);
- }
-
size_b1 = flash_amd_get_size ((uchar *) CFG_BOOTROM_BASE, &flash_info[1]);
- printf("(Bank#1 - %ld MB", size_b0 >> 20);
+ if (size_b0 > 0 || size_b1 > 0) {
- if (size_b1 > 0)
- printf(", Bank#2 - %ld kB", size_b1 >> 10);
+ printf("(");
- printf(")");
+ if (size_b0 > 0)
+ printf("Bank#1 - %ld MB", size_b0 >> 20);
+ if (size_b1 > 0)
+ printf("%sBank#2 - %ld kB",
+ (size_b0 > 0) ? ", " : "",
+ size_b1 >> 10);
+
+ printf(") ");
+ }
+ else {
+ printf ("## No FLASH found.\n");
+ return 0;
+ }
/* protect monitor and environment sectors
*/
/* protect monitor and environment sectors
*/
-#ifndef CONFIG_BOOT_BOOTROM
- /* If PPCBoot is booted from ROM the CFG_MONITOR_BASE > CFG_FLASH0_BASE
- * but we shouldn't protect it.
- */
-
#ifndef CONFIG_BOOT_ROM
/* If PPCBoot is booted from ROM the CFG_MONITOR_BASE > CFG_FLASH0_BASE
* but we shouldn't protect it.
*/
-#if CFG_MONITOR_BASE >= CFG_FLASH0_BASE
+# if CFG_MONITOR_BASE >= CFG_FLASH0_BASE
flash_protect (FLAG_PROTECT_SET,
CFG_MONITOR_BASE,
CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1, &flash_info[0]
);
-#endif
-#endif
-#endif
+# endif
+#endif /* CONFIG_BOOT_ROM */
#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR)
# ifndef CFG_ENV_SIZE
printf ("\n ");
printf (" %08lX%s",
info->start[i],
- info->protect[i] ? " (RO)" : " "
+ info->protect[i] ? " (RO)" : " "
);
}
printf ("\n");
#endif
return (psize);
}
+
+#if (CONFIG_COMMANDS & CFG_CMD_DOC)
+extern void doc_probe (ulong physadr);
+void doc_init (void)
+{
+ doc_probe (CFG_DOC_BASE);
+}
+#endif
#ifdef CFG_FLASH_PROTECTION
/*-----------------------------------------------------------------------
- * FIXME - pass in sector index instead of sector address, would simplify
- * this code a bit. w7o would need changing also.
*/
int flash_real_protect (flash_info_t * info, long sector, int prot)
{
- int rcode;
- int sectindex = 0;
- FPWV *addr = (FPWV *) sector;
+ int rcode = 0; /* assume success */
+ FPWV *addr; /* address of sector */
FPW value;
- int i;
-
- rcode = 1; /* assume fails */
- for (i = 0; rcode != 0 && i < info->sector_count; i++) {
- if (info->start[i] == sector) {
- sectindex = i;
- rcode = 0; /* success so far */
- }
- }
- if (rcode)
- return (rcode);
+ addr = (FPWV *) (info->start[sector]);
switch (info->flash_id & FLASH_TYPEMASK) {
case FLASH_28F800C3B:
*/
value = addr[2] & (FPW) 0x00010001;
if (value == 0)
- info->protect[sectindex] = 0;
+ info->protect[sector] = 0;
else if (value == (FPW) 0x00010001)
- info->protect[sectindex] = 1;
+ info->protect[sector] = 1;
else {
/* error, mixed protected and unprotected */
rcode = 1;
- info->protect[sectindex] = 1;
+ info->protect[sector] = 1;
}
- if (info->protect[sectindex] != prot)
+ if (info->protect[sector] != prot)
rcode = 1; /* failed to protect/unprotect as requested */
/* reload all protection bits from hardware for now */
case FLASH_AM640U:
default:
/* no hardware protect that we support */
- info->protect[sectindex] = prot;
+ info->protect[sector] = prot;
break;
}
/*-----------------------------------------------------------------------
*
- * for CONFIG_I2C_X defined (16-bit EEPROM address) offset is
+ * for CFG_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is
* 0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM.
*
- * for CONFIG_I2C_X not defined (8-bit EEPROM page address) offset is
+ * for CFG_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is
* 0x00000nxx for EEPROM address selectors and page number at n.
*/
#if (CONFIG_COMMANDS & CFG_CMD_EEPROM) || defined(CFG_ENV_IS_IN_EEPROM)
+#if !defined(CFG_I2C_EEPROM_ADDR_LEN) || CFG_I2C_EEPROM_ADDR_LEN < 1 || CFG_I2C_EEPROM_ADDR_LEN > 2
+#error CFG_I2C_EEPROM_ADDR_LEN must be 1 or 2
+#endif
+
int eeprom_read (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt)
{
unsigned end = offset + cnt;
*/
while (offset < end) {
unsigned alen, len, maxlen;
-#if !defined(CONFIG_I2C_X) && !defined(CONFIG_SPI_X)
+#if CFG_I2C_EEPROM_ADDR_LEN == 1 && !defined(CONFIG_SPI_X)
uchar addr[2];
blk_off = offset & 0xFF; /* block offset */
addr[1] = offset >> 8; /* upper address octet */
addr[2] = blk_off; /* lower address octet */
alen = 3;
-#endif /* CONFIG_I2C_X, CONFIG_SPI_X */
+#endif /* CFG_I2C_EEPROM_ADDR_LEN, CONFIG_SPI_X */
addr[0] |= dev_addr; /* insert device address */
/*-----------------------------------------------------------------------
*
- * for CONFIG_I2C_X defined (16-bit EEPROM address) offset is
+ * for CFG_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is
* 0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM.
*
- * for CONFIG_I2C_X not defined (8-bit EEPROM page address) offset is
+ * for CFG_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is
* 0x00000nxx for EEPROM address selectors and page number at n.
*/
while (offset < end) {
unsigned alen, len, maxlen;
-#if !defined(CONFIG_I2C_X) && !defined(CONFIG_SPI_X)
+#if CFG_I2C_EEPROM_ADDR_LEN == 1 && !defined(CONFIG_SPI_X)
uchar addr[2];
blk_off = offset & 0xFF; /* block offset */
addr[1] = offset >> 8; /* upper address octet */
addr[2] = blk_off; /* lower address octet */
alen = 3;
-#endif /* CONFIG_I2C_X, CONFIG_SPI_X */
+#endif /* CFG_I2C_EEPROM_ADDR_LEN, CONFIG_SPI_X */
addr[0] |= dev_addr; /* insert device address */
(CFG_CMD_ENV|CFG_CMD_FLASH))
int do_saveenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
- int rcode = 0;
-
puts (NVRAM_SAVESTR);
- if (!saveenv())
- rcode = 1;
- return rcode;
+ return (saveenv() ? 1 : 0);
}
#endif
#ifdef DEBUG_I2C
-#define PRINTD(fmt,args...) printf (fmt ,##args)
+#define PRINTD(fmt,args...) do { \
+ init_data_t *idata = (init_data_t *)(CFG_INIT_RAM_ADDR + CFG_INIT_DATA_OFFSET); \
+ if (idata->have_console) \
+ printf (fmt ,##args); \
+ } while (0)
#else
#define PRINTD(fmt,args...)
#endif
__asm__ ("eieio");
} while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+ /* clear memory for idata */
+ memset((init_data_t *)(CFG_INIT_RAM_ADDR + CFG_INIT_DATA_OFFSET), 0, CFG_INIT_DATA_SIZE);
+
#ifdef CONFIG_MBX
/*
* on the MBX, things are a little bit different:
u_char vl_dp; /* Data polarity */
u_char vl_bpix; /* Bits per pixel, 0 = 1, 1 = 2, 2 = 4, 3 = 8 */
u_char vl_lbw; /* LCD Bus width, 0 = 4, 1 = 8 */
- u_char vl_splt; /* Split display, 0 = dual, 1 = single */
+ u_char vl_splt; /* Split display, 0 = single-scan, 1 = dual-scan */
u_char vl_clor; /* Color, 0 = mono, 1 = color */
u_char vl_tft; /* 0 = passive, 1 = TFT */
memset(pa, 0xff, SETUP_FRAME_LEN);
for (i = 0; i < ETH_ALEN; i++) {
- *(pa + (i & 1)) = bis->bi_enetaddr[i];
+ *(pa + (i & 1)) = dev->enetaddr[i];
if (i & 0x01) {
pa += 4;
}
}
if ((j == 0) || (j == 0x2fffd)) {
+ memset (dev->enetaddr, 0, ETH_ALEN);
+#ifdef DEBUG
printf("Warning: can't read HW address from SROM.\n");
+#endif
goto Done;
}
-#ifdef DEBUG
- for (i = 0; i < ETH_ALEN; i++) {
- if (dev->enetaddr[i] != bis->bi_enetaddr[i]) {
- printf("Warning: HW addresses don't match:\n");
- printf("Address in SROM is "
- "%02X:%02X:%02X:%02X:%02X:%02X\n",
- dev->enetaddr[0], dev->enetaddr[1],
- dev->enetaddr[2], dev->enetaddr[3],
- dev->enetaddr[4], dev->enetaddr[5]);
- printf("Address used by ppcboot is "
- "%02X:%02X:%02X:%02X:%02X:%02X\n",
- bis->bi_enetaddr[0], bis->bi_enetaddr[1],
- bis->bi_enetaddr[2], bis->bi_enetaddr[3],
- bis->bi_enetaddr[4], bis->bi_enetaddr[5]);
-
- goto Done;
- }
- }
-#endif
-
return;
Done:
}
}
+ if (sum != 0xBABA) {
+ memset (dev->enetaddr, 0, ETH_ALEN);
#ifdef DEBUG
- if (sum != 0xBABA)
printf("%s: Invalid EEPROM checksum %#4.4x, "
"check settings before activating this device!\n",
dev->name, sum);
-
- for (i=0;i<ETH_ALEN;i++)
- {
- if (dev->enetaddr[i] != bis->bi_enetaddr[i])
- {
- printf("Warning: HW address don't match:\n");
- printf("Address in SROM is "
- "%02X:%02X:%02X:%02X:%02X:%02X\n",
- dev->enetaddr[0], dev->enetaddr[1],
- dev->enetaddr[2], dev->enetaddr[3],
- dev->enetaddr[4], dev->enetaddr[5]);
- printf("Address used by ppcboot is "
- "%02X:%02X:%02X:%02X:%02X:%02X\n",
- bis->bi_enetaddr[0], bis->bi_enetaddr[1],
- bis->bi_enetaddr[2], bis->bi_enetaddr[3],
- bis->bi_enetaddr[4], bis->bi_enetaddr[5]);
- goto Done;
- }
- }
-
-Done:
#endif
- return;
+ }
}
#endif
else iop->pdat &= ~0x00010000
#define I2C_SCL(bit) if(bit) iop->pdat |= 0x00020000; \
else iop->pdat &= ~0x00020000
-#define I2C_DELAY udelay(10) /* 1/4 I2C clock duration */
+#define I2C_DELAY udelay(5) /* 1/4 I2C clock duration */
#define CONFIG_RTC_PCF8563
#define CFG_I2C_RTC_ADDR 0x51
#if 0 /* Does not appear to be used?! If it is used, needs to be fixed */
#define CONFIG_SOFT_I2C /* Software I2C support enabled */
#endif
+#define CFG_I2C_EEPROM_ADDR_LEN 1 /* Bytes of address */
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include <cmd_confdefs.h>
# define CFG_I2C_SPEED 50000
# define CFG_I2C_SLAVE 0xFE
# define CFG_I2C_EEPROM_ADDR 0x50
+# define CFG_I2C_EEPROM_ADDR_LEN 1 /* Bytes of address */
/*
* Software (bit-bang) I2C driver configuration
*/
#define CONFIG_CLOCKS_IN_MHZ 1 /* clocks passsed to Linux in MHz */
-#if 0
-#define CONFIG_BOOTDELAY -1 /* autoboot disabled */
-#else
#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */
-#endif
#define CONFIG_PREBOOT "echo;echo Type \"run flash_nfs\" to mount root filesystem over NFS;echo"
else iop->pdat &= ~0x00010000
#define I2C_SCL(bit) if(bit) iop->pdat |= 0x00020000; \
else iop->pdat &= ~0x00020000
-#define I2C_DELAY udelay(10) /* 1/4 I2C clock duration */
+#define I2C_DELAY udelay(5) /* 1/4 I2C clock duration */
#define CONFIG_RTC_PCF8563
#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAULT|CONFIG_BOOTP_BOOTFILESIZE)
-#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_EEPROM | CFG_CMD_DATE)
+#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_EEPROM | CFG_CMD_DATE | CFG_CMD_DOC)
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include <cmd_confdefs.h>
+/*
+ * Disk-On-Chip configuration
+ */
+
+#define CFG_DOC_SHORT_TIMEOUT
+#define CFG_MAX_DOC_DEVICE 1 /* Max number of DOC devices */
+
+#define CFG_DOC_SUPPORT_2000
+#define CFG_DOC_SUPPORT_MILLENNIUM
+
/*
* Miscellaneous configurable options
*/
#define CFG_BOOTROM_SIZE 0x00080000
#define CFG_FLASH0_BASE 0x40000000
#define CFG_FLASH0_SIZE 0x02000000
+#define CFG_DOC_BASE 0x60000000
+#define CFG_DOC_SIZE 0x00100000
/* Flash bank size (for preliminary settings)
#if defined(CONFIG_BOOT_ROM)
/*
- * Bank 0 - BOOTROM
+ * Bank 0 - Boot ROM (8 bit wide)
*/
#define CFG_BR0_PRELIM ((CFG_BOOTROM_BASE & BRx_BA_MSK)|\
BRx_PS_8 |\
ORxG_EHTR |\
ORxG_TRLX)
+/*
+ * Bank 1 - Flash (64 bit wide)
+ */
#define CFG_BR1_PRELIM ((CFG_FLASH_BASE & BRx_BA_MSK) |\
BRx_PS_64 |\
BRx_MS_GPCM_P |\
#else /* ! CONFIG_BOOT_ROM */
/*
- * Bank 0 - FLASH
+ * Bank 0 - Flash (64 bit wide)
*/
#define CFG_BR0_PRELIM ((CFG_FLASH_BASE & BRx_BA_MSK) |\
BRx_PS_64 |\
ORxG_SCY_3_CLK |\
ORxG_EHTR |\
ORxG_TRLX)
+
+/*
+ * Bank 1 - Disk-On-Chip
+ */
+#define CFG_BR1_PRELIM ((CFG_DOC_BASE & BRx_BA_MSK) |\
+ BRx_PS_8 |\
+ BRx_MS_GPCM_P |\
+ BRx_V)
+
+#define CFG_OR1_PRELIM (P2SZ_TO_AM(CFG_DOC_SIZE) |\
+ ORxG_CSNT |\
+ ORxG_ACS_DIV1 |\
+ ORxG_SCY_3_CLK |\
+ ORxG_EHTR |\
+ ORxG_TRLX)
+
#endif /* CONFIG_BOOT_ROM */
/* Bank 2 - SDRAM
#define CFG_I2C_EEPROM_ADDR 0x57 /* EEPROM IS24C02 */
+#define CFG_I2C_EEPROM_ADDR_LEN 1 /* Bytes of address */
#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
#define CFG_FLASH_BANKS { FLASH_BASE0_PRELIM , FLASH_BASE1_PRELIM }
#endif /* CONFIG_SOFT_I2C */
#define CFG_I2C_EEPROM_ADDR 0x57 /* EEPROM IS24C02 */
+#define CFG_I2C_EEPROM_ADDR_LEN 1 /* Bytes of address */
#define CFG_EEPROM_PAGE_WRITE_BITS 3
#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10 /* and takes up to 10 msec */
else iop->pdat &= ~0x00020000
#define I2C_SCL(bit) if(bit) iop->pdat |= 0x00010000; \
else iop->pdat &= ~0x00010000
-#define I2C_DELAY udelay(20) /* 1/4 I2C clock duration */
+#define I2C_DELAY udelay(5) /* 1/4 I2C clock duration */
#else
else iop->pdat &= ~0x00010000
#define I2C_SCL(bit) if(bit) iop->pdat |= 0x00020000; \
else iop->pdat &= ~0x00020000
-#define I2C_DELAY udelay(20) /* 1/4 I2C clock duration */
+#define I2C_DELAY udelay(5) /* 1/4 I2C clock duration */
#endif
#define CFG_I2C_EEPROM_ADDR 0x50
#define CFG_I2C_SLAVE 0x7F
#define CFG_I2C_EEPROM_ADDR 0x50 /* EEPROM ATMEL 24C04N */
+#define CFG_I2C_EEPROM_ADDR_LEN 1 /* Bytes of address */
#define CFG_EEPROM_PAGE_WRITE_ENABLE
#define CFG_EEPROM_PAGE_WRITE_BITS 3
#define CFG_I2C_MULTI_EEPROMS
extern int eth_initialize(bd_t *bis); /* Initialize network subsystem */
extern int eth_register(struct eth_device* dev);/* Register network device */
extern void eth_try_another(void); /* Change the device */
-extern char *eth_get_enetaddr(void); /* get the current device MAC */
+extern char *eth_get_enetaddr(void); /* get the current device MAC */
#endif
extern int eth_init(bd_t *bis); /* Initialize the device */
int eth_initialize(bd_t *bis)
{
- int eth_number = 0;
+ unsigned char enetvar[32], env_enetaddr[6];
+ int i, eth_number = 0;
+ char *tmp, *end;
eth_devices = NULL;
eth_current = NULL;
struct eth_device *dev = eth_devices;
do {
- if (eth_number++)
+ if (eth_number)
printf(", ");
+
printf("%s", dev->name);
+
+ sprintf(enetvar, eth_number ? "eth%daddr" : "ethaddr", eth_number);
+ tmp = getenv (enetvar);
+
+ for (i=0; i<6; i++)
+ {
+ env_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
+ if (tmp)
+ tmp = (*end) ? end+1 : end;
+ }
+
+ if (memcmp(env_enetaddr, "\0\0\0\0\0\0", 6))
+ {
+ if (memcmp(dev->enetaddr, "\0\0\0\0\0\0", 6) &&
+ memcmp(dev->enetaddr, env_enetaddr, 6))
+ {
+ printf("\nWarning: %s HW address don't match:\n", dev->name);
+ printf("Address in SROM is "
+ "%02X:%02X:%02X:%02X:%02X:%02X\n",
+ dev->enetaddr[0], dev->enetaddr[1],
+ dev->enetaddr[2], dev->enetaddr[3],
+ dev->enetaddr[4], dev->enetaddr[5]);
+ printf("Address in environment is "
+ "%02X:%02X:%02X:%02X:%02X:%02X\n",
+ env_enetaddr[0], env_enetaddr[1],
+ env_enetaddr[2], env_enetaddr[3],
+ env_enetaddr[4], env_enetaddr[5]);
+ }
+
+ memcpy(dev->enetaddr, env_enetaddr, 6);
+ }
+
+ eth_number++;
dev = dev->next;
} while(dev != eth_devices);
LIB = librtc.a
OBJS = date.o ds1302.o ds174x.o ds1306.o ds1556.o \
- m48t35ax.o mc146818.o mk48t59.o mpc8xx.o pcf8563.o
+ m41t11.o m48t35ax.o mc146818.o mk48t59.o \
+ mpc8xx.o pcf8563.o
all: $(LIB)
--- /dev/null
+/*
+ * (C) Copyright 2002
+ * Andrew May, Viasat Inc, amay@viasat.com
+ *
+ * This program 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 Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * M41T11 Serial Access Timekeeper(R) SRAM
+ * can you believe a trademark on that?
+ */
+
+#include <ppcboot.h>
+#include <command.h>
+#include <rtc.h>
+#include <i2c.h>
+
+/*
+ I Don't have an example config file but this
+ is what should be done.
+
+#define CONFIG_RTC_M41T11 1
+#define CFG_I2C_RTC_ADDR 0x68
+#if 0
+#define CFG_M41T11_EXT_CENTURY_DATA
+#else
+#define CFG_M41T11_BASE_YEAR 2000
+#endif
+*/
+
+#if defined(CONFIG_RTC_M41T11) && defined(CFG_I2C_RTC_ADDR) && (CONFIG_COMMANDS & CFG_CMD_DATE)
+
+#define DEBUG 1
+
+static unsigned bcd2bin (uchar n)
+{
+ return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
+}
+
+static unsigned char bin2bcd (unsigned int n)
+{
+ return (((n / 10) << 4) | (n % 10));
+}
+
+
+/* ------------------------------------------------------------------------- */
+/*
+ these are simple defines for the chip local to here so they aren't too
+ verbose
+ DAY/DATE aren't nice but that is how they are on the data sheet
+*/
+#define RTC_SEC_ADDR 0x0
+#define RTC_MIN_ADDR 0x1
+#define RTC_HOUR_ADDR 0x2
+#define RTC_DAY_ADDR 0x3
+#define RTC_DATE_ADDR 0x4
+#define RTC_MONTH_ADDR 0x5
+#define RTC_YEARS_ADDR 0x6
+
+#define RTC_REG_CNT 7
+
+#define RTC_CONTROL_ADDR 0x7
+
+
+#ifndef CFG_M41T11_EXT_CENTURY_DATA
+
+#define REG_CNT (RTC_REG_CNT+1)
+
+/*
+ you only get 00-99 for the year we will asume you
+ want from the year 2000 if you don't set the config
+*/
+#ifndef CFG_M41T11_BASE_YEAR
+#define CFG_M41T11_BASE_YEAR 2000
+#endif
+
+#else
+/* we will store extra year info in byte 9*/
+#define M41T11_YEAR_DATA 0x8
+#define M41T11_YEAR_SIZE 1
+#define REG_CNT (RTC_REG_CNT+1+M41T11_YEAR_SIZE)
+#endif
+
+#define M41T11_STORAGE_SZ (64-REG_CNT)
+
+void rtc_get (struct rtc_time *tmp)
+{
+ uchar data[RTC_REG_CNT];
+
+ i2c_read(CFG_I2C_RTC_ADDR, RTC_SEC_ADDR, 1, data, RTC_REG_CNT);
+
+ if( data[RTC_SEC_ADDR] & 0x80 ){
+ printf( "m41t11 RTC Clock stopped!!!\n" );
+ }
+ tmp->tm_sec = bcd2bin (data[RTC_SEC_ADDR] & 0x7F);
+ tmp->tm_min = bcd2bin (data[RTC_MIN_ADDR] & 0x7F);
+ tmp->tm_hour = bcd2bin (data[RTC_HOUR_ADDR] & 0x3F);
+ tmp->tm_mday = bcd2bin (data[RTC_DATE_ADDR] & 0x3F);
+ tmp->tm_mon = bcd2bin (data[RTC_MONTH_ADDR]& 0x1F);
+#ifndef CFG_M41T11_EXT_CENTURY_DATA
+ tmp->tm_year = CFG_M41T11_BASE_YEAR
+ + bcd2bin(data[RTC_YEARS_ADDR])
+ + ((data[RTC_HOUR_ADDR]&0x40) ? 100 : 0);
+#else
+ {
+ unsigned char cent;
+ i2c_read(CFG_I2C_RTC_ADDR, M41T11_YEAR_DATA, 1, ¢, M41T11_YEAR_SIZE);
+ if( !(data[RTC_HOUR_ADDR] & 0x80) ){
+ printf( "m41t11 RTC: cann't keep track of years without CEB set\n" );
+ }
+ if( (cent & 0x1) != ((data[RTC_HOUR_ADDR]&0x40)>>7) ){
+ /*century flip store off new year*/
+ cent += 1;
+ i2c_write(CFG_I2C_RTC_ADDR, M41T11_YEAR_DATA, 1, ¢, M41T11_YEAR_SIZE);
+ }
+ tmp->tm_year =((int)cent*100)+bcd2bin(data[RTC_YEARS_ADDR]);
+ }
+#endif
+ tmp->tm_wday = bcd2bin (data[RTC_DAY_ADDR] & 0x07);
+ tmp->tm_yday = 0;
+ tmp->tm_isdst= 0;
+
+ debug ( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
+ tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+ tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+}
+
+void rtc_set (struct rtc_time *tmp)
+{
+ uchar data[RTC_REG_CNT];
+
+ debug ( "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
+ tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+ tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+
+ data[RTC_SEC_ADDR] = bin2bcd(tmp->tm_sec) & 0x7F;/*just in case*/
+ data[RTC_MIN_ADDR] = bin2bcd(tmp->tm_min);
+ data[RTC_HOUR_ADDR] = bin2bcd(tmp->tm_hour) & 0x3F;/*handle cent stuff later*/
+ data[RTC_DATE_ADDR] = bin2bcd(tmp->tm_mday) & 0x3F;
+ data[RTC_MONTH_ADDR] = bin2bcd(tmp->tm_mon);
+ data[RTC_DAY_ADDR] = bin2bcd(tmp->tm_wday) & 0x07;
+
+ data[RTC_HOUR_ADDR] |= 0x80;/*we will always use CEB*/
+
+ data[RTC_YEARS_ADDR] = bin2bcd(tmp->tm_year%100);/*same thing either way*/
+#ifndef CFG_M41T11_EXT_CENTURY_DATA
+ if( ((tmp->tm_year - CFG_M41T11_BASE_YEAR) > 200) ||
+ (tmp->tm_year < CFG_M41T11_BASE_YEAR) ){
+ printf( "m41t11 RTC setting year out of range!!need recompile\n" );
+ }
+ data[RTC_HOUR_ADDR] |= (tmp->tm_year - CFG_M41T11_BASE_YEAR) > 100 ? 0x40 : 0;
+#else
+ {
+ unsigned char cent;
+ cent = tmp->tm_year ? tmp->tm_year / 100 : 0;
+ data[RTC_HOUR_ADDR] |= (cent & 0x1) ? 0x40 : 0;
+ i2c_write(CFG_I2C_RTC_ADDR, M41T11_YEAR_DATA, 1, ¢, M41T11_YEAR_SIZE);
+ }
+#endif
+ i2c_write(CFG_I2C_RTC_ADDR, RTC_SEC_ADDR, 1, data, RTC_REG_CNT);
+}
+
+void rtc_reset (void)
+{
+ unsigned char val;
+ /* clear all control & status registers */
+ i2c_read(CFG_I2C_RTC_ADDR, RTC_SEC_ADDR, 1, &val, 1);
+ val = val & 0x7F;/*make sure we are running*/
+ i2c_write(CFG_I2C_RTC_ADDR, RTC_SEC_ADDR, 1, &val, RTC_REG_CNT);
+
+ i2c_read(CFG_I2C_RTC_ADDR, RTC_CONTROL_ADDR, 1, &val, 1);
+ val = val & 0x3F;/*turn off freq test keep calibration*/
+ i2c_write(CFG_I2C_RTC_ADDR, RTC_CONTROL_ADDR, 1, &val, 1);
+}
+
+int rtc_store(int addr, unsigned char* data, int size)
+{
+ /*don't let things wrap onto the time on a write*/
+ if( (addr+size) >= M41T11_STORAGE_SZ )
+ return 1;
+ return i2c_write( CFG_I2C_RTC_ADDR, REG_CNT+addr, 1, data, size );
+}
+
+int rtc_recall(int addr, unsigned char* data, int size)
+{
+ return i2c_read( CFG_I2C_RTC_ADDR, REG_CNT+addr, 1, data, size );
+}
+
+#endif /* CONFIG_RTC_M41T11 && CFG_I2C_RTC_ADDR && CFG_CMD_DATE */