summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rwxr-xr-xdrivers/Makefile73
-rw-r--r--drivers/bios_emulator/besys.c2
-rw-r--r--drivers/bios_emulator/biosemu.c6
-rw-r--r--drivers/block/Makefile50
-rw-r--r--drivers/block/ahci.c (renamed from drivers/ahci.c)0
-rw-r--r--drivers/block/ata_piix.c (renamed from drivers/ata_piix.c)0
-rw-r--r--drivers/block/sil680.c (renamed from drivers/sil680.c)0
-rw-r--r--drivers/block/sym53c8xx.c (renamed from drivers/sym53c8xx.c)0
-rw-r--r--drivers/block/systemace.c (renamed from drivers/systemace.c)0
-rw-r--r--drivers/hwmon/Makefile57
-rw-r--r--drivers/hwmon/adm1021.c174
-rw-r--r--drivers/hwmon/ds1621.c190
-rw-r--r--drivers/hwmon/ds1722.c (renamed from drivers/ds1722.c)0
-rw-r--r--drivers/hwmon/ds1775.c156
-rw-r--r--drivers/hwmon/lm73.c181
-rw-r--r--drivers/hwmon/lm75.c185
-rw-r--r--drivers/hwmon/lm81.c148
-rw-r--r--drivers/i2c/Makefile49
-rw-r--r--drivers/i2c/fsl_i2c.c (renamed from drivers/fsl_i2c.c)0
-rw-r--r--drivers/i2c/omap1510_i2c.c (renamed from drivers/omap1510_i2c.c)0
-rw-r--r--drivers/i2c/omap24xx_i2c.c (renamed from drivers/omap24xx_i2c.c)0
-rw-r--r--drivers/i2c/tsi108_i2c.c (renamed from drivers/tsi108_i2c.c)2
-rw-r--r--drivers/input/Makefile48
-rw-r--r--drivers/input/i8042.c (renamed from drivers/i8042.c)0
-rw-r--r--drivers/input/keyboard.c (renamed from drivers/keyboard.c)0
-rw-r--r--drivers/input/pc_keyb.c (renamed from drivers/pc_keyb.c)0
-rw-r--r--drivers/input/ps2mult.c (renamed from drivers/ps2mult.c)0
-rw-r--r--drivers/input/ps2ser.c (renamed from drivers/ps2ser.c)0
-rw-r--r--drivers/misc/Makefile (renamed from drivers/nand/Makefile)9
-rw-r--r--drivers/misc/ali512x.c (renamed from drivers/ali512x.c)0
-rw-r--r--drivers/misc/ns87308.c (renamed from drivers/ns87308.c)0
-rw-r--r--drivers/misc/status_led.c (renamed from drivers/status_led.c)0
-rw-r--r--drivers/mtd/Makefile50
-rw-r--r--drivers/mtd/at45.c (renamed from drivers/at45.c)0
-rw-r--r--drivers/mtd/cfi_flash.c (renamed from drivers/cfi_flash.c)1957
-rw-r--r--drivers/mtd/dataflash.c (renamed from drivers/dataflash.c)0
-rw-r--r--drivers/mtd/jedec_flash.c311
-rw-r--r--drivers/mtd/mw_eeprom.c (renamed from drivers/mw_eeprom.c)0
-rw-r--r--drivers/mtd/nand/Makefile51
-rw-r--r--drivers/mtd/nand/diskonchip.c (renamed from drivers/nand/diskonchip.c)0
-rw-r--r--drivers/mtd/nand/nand.c (renamed from drivers/nand/nand.c)0
-rw-r--r--drivers/mtd/nand/nand_base.c (renamed from drivers/nand/nand_base.c)0
-rw-r--r--drivers/mtd/nand/nand_bbt.c (renamed from drivers/nand/nand_bbt.c)0
-rw-r--r--drivers/mtd/nand/nand_ecc.c (renamed from drivers/nand/nand_ecc.c)0
-rw-r--r--drivers/mtd/nand/nand_ids.c (renamed from drivers/nand/nand_ids.c)0
-rw-r--r--drivers/mtd/nand/nand_util.c (renamed from drivers/nand/nand_util.c)0
-rw-r--r--drivers/mtd/nand_legacy/Makefile (renamed from drivers/nand_legacy/Makefile)0
-rw-r--r--drivers/mtd/nand_legacy/nand_legacy.c (renamed from drivers/nand_legacy/nand_legacy.c)0
-rw-r--r--drivers/mtd/onenand/Makefile (renamed from drivers/onenand/Makefile)0
-rw-r--r--drivers/mtd/onenand/onenand_base.c (renamed from drivers/onenand/onenand_base.c)0
-rw-r--r--drivers/mtd/onenand/onenand_bbt.c (renamed from drivers/onenand/onenand_bbt.c)0
-rw-r--r--drivers/net/3c589.c (renamed from drivers/3c589.c)0
-rw-r--r--drivers/net/3c589.h (renamed from drivers/3c589.h)0
-rw-r--r--drivers/net/5701rls.c (renamed from drivers/5701rls.c)0
-rw-r--r--drivers/net/5701rls.h (renamed from drivers/5701rls.h)0
-rw-r--r--drivers/net/8390.h (renamed from drivers/8390.h)0
-rw-r--r--drivers/net/Makefile33
-rw-r--r--drivers/net/bcm570x.c (renamed from drivers/bcm570x.c)0
-rw-r--r--drivers/net/bcm570x_autoneg.c (renamed from drivers/bcm570x_autoneg.c)0
-rw-r--r--drivers/net/bcm570x_autoneg.h (renamed from drivers/bcm570x_autoneg.h)0
-rw-r--r--drivers/net/bcm570x_bits.h (renamed from drivers/bcm570x_bits.h)0
-rw-r--r--drivers/net/bcm570x_debug.h (renamed from drivers/bcm570x_debug.h)0
-rw-r--r--drivers/net/bcm570x_lm.h (renamed from drivers/bcm570x_lm.h)0
-rw-r--r--drivers/net/bcm570x_mm.h (renamed from drivers/bcm570x_mm.h)0
-rw-r--r--drivers/net/bcm570x_queue.h (renamed from drivers/bcm570x_queue.h)0
-rw-r--r--drivers/net/cs8900.c (renamed from drivers/cs8900.c)0
-rw-r--r--drivers/net/cs8900.h (renamed from drivers/cs8900.h)0
-rw-r--r--drivers/net/dc2114x.c (renamed from drivers/dc2114x.c)0
-rw-r--r--drivers/net/dm9000x.c (renamed from drivers/dm9000x.c)0
-rw-r--r--drivers/net/dm9000x.h (renamed from drivers/dm9000x.h)0
-rw-r--r--drivers/net/e1000.c (renamed from drivers/e1000.c)0
-rw-r--r--drivers/net/e1000.h (renamed from drivers/e1000.h)0
-rw-r--r--drivers/net/eepro100.c (renamed from drivers/eepro100.c)0
-rw-r--r--drivers/net/enc28j60.c (renamed from drivers/enc28j60.c)0
-rw-r--r--drivers/net/inca-ip_sw.c (renamed from drivers/inca-ip_sw.c)0
-rw-r--r--drivers/net/ks8695eth.c (renamed from drivers/ks8695eth.c)0
-rw-r--r--drivers/net/lan91c96.c (renamed from drivers/lan91c96.c)0
-rw-r--r--drivers/net/lan91c96.h (renamed from drivers/lan91c96.h)0
-rw-r--r--drivers/net/macb.c (renamed from drivers/macb.c)0
-rw-r--r--drivers/net/macb.h (renamed from drivers/macb.h)0
-rw-r--r--drivers/net/natsemi.c (renamed from drivers/natsemi.c)0
-rw-r--r--drivers/net/ne2000.c (renamed from drivers/ne2000.c)21
-rw-r--r--drivers/net/ne2000.h (renamed from drivers/ne2000.h)0
-rw-r--r--drivers/net/netarm_eth.c (renamed from drivers/netarm_eth.c)0
-rw-r--r--drivers/net/netarm_eth.h (renamed from drivers/netarm_eth.h)0
-rw-r--r--drivers/net/netconsole.c (renamed from drivers/netconsole.c)0
-rw-r--r--drivers/net/nicext.h (renamed from drivers/nicext.h)0
-rw-r--r--drivers/net/ns7520_eth.c (renamed from drivers/ns7520_eth.c)0
-rw-r--r--drivers/net/ns8382x.c (renamed from drivers/ns8382x.c)0
-rw-r--r--drivers/net/ns9750_eth.c (renamed from drivers/ns9750_eth.c)0
-rw-r--r--drivers/net/pcnet.c (renamed from drivers/pcnet.c)0
-rw-r--r--drivers/net/plb2800_eth.c (renamed from drivers/plb2800_eth.c)0
-rw-r--r--drivers/net/rtl8019.c (renamed from drivers/rtl8019.c)0
-rw-r--r--drivers/net/rtl8019.h (renamed from drivers/rtl8019.h)0
-rw-r--r--drivers/net/rtl8139.c (renamed from drivers/rtl8139.c)0
-rw-r--r--drivers/net/rtl8169.c (renamed from drivers/rtl8169.c)0
-rw-r--r--drivers/net/s3c4510b_eth.c (renamed from drivers/s3c4510b_eth.c)2
-rw-r--r--drivers/net/s3c4510b_eth.h (renamed from drivers/s3c4510b_eth.h)0
-rw-r--r--drivers/net/sk98lin/Makefile (renamed from drivers/sk98lin/Makefile)26
-rw-r--r--drivers/net/sk98lin/h/lm80.h (renamed from drivers/sk98lin/h/lm80.h)0
-rw-r--r--drivers/net/sk98lin/h/skaddr.h (renamed from drivers/sk98lin/h/skaddr.h)0
-rw-r--r--drivers/net/sk98lin/h/skcsum.h (renamed from drivers/sk98lin/h/skcsum.h)0
-rw-r--r--drivers/net/sk98lin/h/skdebug.h (renamed from drivers/sk98lin/h/skdebug.h)0
-rw-r--r--drivers/net/sk98lin/h/skdrv1st.h (renamed from drivers/sk98lin/h/skdrv1st.h)0
-rw-r--r--drivers/net/sk98lin/h/skdrv2nd.h (renamed from drivers/sk98lin/h/skdrv2nd.h)0
-rw-r--r--drivers/net/sk98lin/h/skerror.h (renamed from drivers/sk98lin/h/skerror.h)0
-rw-r--r--drivers/net/sk98lin/h/skgedrv.h (renamed from drivers/sk98lin/h/skgedrv.h)0
-rw-r--r--drivers/net/sk98lin/h/skgehw.h (renamed from drivers/sk98lin/h/skgehw.h)0
-rw-r--r--drivers/net/sk98lin/h/skgehwt.h (renamed from drivers/sk98lin/h/skgehwt.h)0
-rw-r--r--drivers/net/sk98lin/h/skgei2c.h (renamed from drivers/sk98lin/h/skgei2c.h)0
-rw-r--r--drivers/net/sk98lin/h/skgeinit.h (renamed from drivers/sk98lin/h/skgeinit.h)0
-rw-r--r--drivers/net/sk98lin/h/skgepnm2.h (renamed from drivers/sk98lin/h/skgepnm2.h)0
-rw-r--r--drivers/net/sk98lin/h/skgepnmi.h (renamed from drivers/sk98lin/h/skgepnmi.h)0
-rw-r--r--drivers/net/sk98lin/h/skgesirq.h (renamed from drivers/sk98lin/h/skgesirq.h)0
-rw-r--r--drivers/net/sk98lin/h/ski2c.h (renamed from drivers/sk98lin/h/ski2c.h)0
-rw-r--r--drivers/net/sk98lin/h/skqueue.h (renamed from drivers/sk98lin/h/skqueue.h)0
-rw-r--r--drivers/net/sk98lin/h/skrlmt.h (renamed from drivers/sk98lin/h/skrlmt.h)0
-rw-r--r--drivers/net/sk98lin/h/sktimer.h (renamed from drivers/sk98lin/h/sktimer.h)0
-rw-r--r--drivers/net/sk98lin/h/sktypes.h (renamed from drivers/sk98lin/h/sktypes.h)0
-rw-r--r--drivers/net/sk98lin/h/skversion.h (renamed from drivers/sk98lin/h/skversion.h)0
-rw-r--r--drivers/net/sk98lin/h/skvpd.h (renamed from drivers/sk98lin/h/skvpd.h)0
-rw-r--r--drivers/net/sk98lin/h/xmac_ii.h (renamed from drivers/sk98lin/h/xmac_ii.h)0
-rw-r--r--drivers/net/sk98lin/skaddr.c (renamed from drivers/sk98lin/skaddr.c)0
-rw-r--r--drivers/net/sk98lin/skcsum.c (renamed from drivers/sk98lin/skcsum.c)0
-rw-r--r--drivers/net/sk98lin/skge.c (renamed from drivers/sk98lin/skge.c)0
-rw-r--r--drivers/net/sk98lin/skgehwt.c (renamed from drivers/sk98lin/skgehwt.c)0
-rw-r--r--drivers/net/sk98lin/skgeinit.c (renamed from drivers/sk98lin/skgeinit.c)0
-rw-r--r--drivers/net/sk98lin/skgemib.c (renamed from drivers/sk98lin/skgemib.c)0
-rw-r--r--drivers/net/sk98lin/skgepnmi.c (renamed from drivers/sk98lin/skgepnmi.c)0
-rw-r--r--drivers/net/sk98lin/skgesirq.c (renamed from drivers/sk98lin/skgesirq.c)0
-rw-r--r--drivers/net/sk98lin/ski2c.c (renamed from drivers/sk98lin/ski2c.c)0
-rw-r--r--drivers/net/sk98lin/sklm80.c (renamed from drivers/sk98lin/sklm80.c)0
-rw-r--r--drivers/net/sk98lin/skproc.c (renamed from drivers/sk98lin/skproc.c)0
-rw-r--r--drivers/net/sk98lin/skqueue.c (renamed from drivers/sk98lin/skqueue.c)0
-rw-r--r--drivers/net/sk98lin/skrlmt.c (renamed from drivers/sk98lin/skrlmt.c)0
-rw-r--r--drivers/net/sk98lin/sktimer.c (renamed from drivers/sk98lin/sktimer.c)0
-rw-r--r--drivers/net/sk98lin/skvpd.c (renamed from drivers/sk98lin/skvpd.c)0
-rw-r--r--drivers/net/sk98lin/skxmac2.c (renamed from drivers/sk98lin/skxmac2.c)0
-rw-r--r--drivers/net/sk98lin/u-boot_compat.h (renamed from drivers/sk98lin/u-boot_compat.h)0
-rw-r--r--drivers/net/sk98lin/uboot_drv.c (renamed from drivers/sk98lin/uboot_drv.c)0
-rw-r--r--drivers/net/sk98lin/uboot_skb.c (renamed from drivers/sk98lin/uboot_skb.c)0
-rw-r--r--drivers/net/smc91111.c (renamed from drivers/smc91111.c)0
-rw-r--r--drivers/net/smc91111.h (renamed from drivers/smc91111.h)0
-rw-r--r--drivers/net/tigon3.c (renamed from drivers/tigon3.c)0
-rw-r--r--drivers/net/tigon3.h (renamed from drivers/tigon3.h)0
-rw-r--r--drivers/net/tsec.c (renamed from drivers/tsec.c)14
-rw-r--r--drivers/net/tsec.h (renamed from drivers/tsec.h)0
-rw-r--r--drivers/net/tsi108_eth.c (renamed from drivers/tsi108_eth.c)0
-rw-r--r--drivers/net/uli526x.c996
-rw-r--r--drivers/pci/Makefile51
-rw-r--r--drivers/pci/fsl_pci_init.c (renamed from drivers/fsl_pci_init.c)23
-rw-r--r--drivers/pci/pci.c (renamed from drivers/pci.c)0
-rw-r--r--drivers/pci/pci_auto.c (renamed from drivers/pci_auto.c)0
-rw-r--r--drivers/pci/pci_indirect.c (renamed from drivers/pci_indirect.c)0
-rw-r--r--drivers/pci/tsi108_pci.c (renamed from drivers/tsi108_pci.c)3
-rw-r--r--drivers/pci/w83c553f.c (renamed from drivers/w83c553f.c)0
-rw-r--r--drivers/pcmcia/Makefile51
-rw-r--r--drivers/pcmcia/i82365.c (renamed from drivers/i82365.c)0
-rw-r--r--drivers/pcmcia/marubun_pcmcia.c113
-rw-r--r--drivers/pcmcia/mpc8xx_pcmcia.c (renamed from drivers/mpc8xx_pcmcia.c)0
-rw-r--r--drivers/pcmcia/pxa_pcmcia.c (renamed from drivers/pxa_pcmcia.c)0
-rw-r--r--drivers/pcmcia/rpx_pcmcia.c (renamed from drivers/rpx_pcmcia.c)0
-rw-r--r--drivers/pcmcia/ti_pci1410a.c (renamed from drivers/ti_pci1410a.c)0
-rw-r--r--drivers/pcmcia/tqm8xx_pcmcia.c (renamed from drivers/tqm8xx_pcmcia.c)0
-rw-r--r--drivers/qe/uec.c23
-rw-r--r--drivers/rtc/Makefile73
-rw-r--r--drivers/rtc/bf5xx_rtc.c143
-rw-r--r--drivers/rtc/date.c156
-rw-r--r--drivers/rtc/ds12887.c238
-rw-r--r--drivers/rtc/ds1302.c327
-rw-r--r--drivers/rtc/ds1306.c438
-rw-r--r--drivers/rtc/ds1307.c204
-rw-r--r--drivers/rtc/ds1337.c191
-rw-r--r--drivers/rtc/ds1374.c253
-rw-r--r--drivers/rtc/ds1556.c206
-rw-r--r--drivers/rtc/ds164x.c200
-rw-r--r--drivers/rtc/ds174x.c202
-rw-r--r--drivers/rtc/ds3231.c193
-rw-r--r--drivers/rtc/m41t11.c202
-rw-r--r--drivers/rtc/m41t60.c261
-rw-r--r--drivers/rtc/m48t35ax.c166
-rw-r--r--drivers/rtc/max6900.c131
-rw-r--r--drivers/rtc/mc146818.c178
-rw-r--r--drivers/rtc/mcfrtc.c121
-rw-r--r--drivers/rtc/mk48t59.c237
-rw-r--r--drivers/rtc/mpc5xxx.c140
-rw-r--r--drivers/rtc/mpc8xx.c73
-rw-r--r--drivers/rtc/pcf8563.c144
-rw-r--r--drivers/rtc/rs5c372.c302
-rw-r--r--drivers/rtc/rx8025.c227
-rw-r--r--drivers/rtc/s3c24x0_rtc.c178
-rw-r--r--drivers/rtc/x1205.c178
-rw-r--r--drivers/serial/Makefile16
-rw-r--r--drivers/serial/atmel_usart.c (renamed from drivers/atmel_usart.c)0
-rw-r--r--drivers/serial/atmel_usart.h (renamed from drivers/atmel_usart.h)0
-rw-r--r--drivers/serial/ns16550.c (renamed from drivers/ns16550.c)0
-rw-r--r--drivers/serial/ns9750_serial.c (renamed from drivers/ns9750_serial.c)0
-rw-r--r--drivers/serial/s3c4510b_uart.c (renamed from drivers/s3c4510b_uart.c)0
-rw-r--r--drivers/serial/s3c4510b_uart.h (renamed from drivers/s3c4510b_uart.h)0
-rw-r--r--drivers/serial/serial.c (renamed from drivers/serial.c)0
-rw-r--r--drivers/serial/serial_max3100.c (renamed from drivers/serial_max3100.c)0
-rw-r--r--drivers/serial/serial_pl010.c (renamed from drivers/serial_pl010.c)0
-rw-r--r--drivers/serial/serial_pl011.c (renamed from drivers/serial_pl011.c)0
-rw-r--r--drivers/serial/serial_pl011.h (renamed from drivers/serial_pl011.h)0
-rw-r--r--drivers/serial/serial_sh.c177
-rw-r--r--drivers/serial/serial_xuartlite.c (renamed from drivers/serial_xuartlite.c)0
-rw-r--r--drivers/serial/usbtty.c (renamed from drivers/usbtty.c)0
-rw-r--r--drivers/serial/usbtty.h (renamed from drivers/usbtty.h)0
-rw-r--r--drivers/usb/Makefile52
-rw-r--r--drivers/usb/isp116x-hcd.c (renamed from drivers/isp116x-hcd.c)0
-rw-r--r--drivers/usb/isp116x.h (renamed from drivers/isp116x.h)0
-rw-r--r--drivers/usb/sl811.h (renamed from drivers/sl811.h)0
-rw-r--r--drivers/usb/sl811_usb.c (renamed from drivers/sl811_usb.c)2
-rw-r--r--drivers/usb/usb_ohci.c (renamed from drivers/usb_ohci.c)4
-rw-r--r--drivers/usb/usb_ohci.h (renamed from drivers/usb_ohci.h)0
-rw-r--r--drivers/usb/usbdcore.c (renamed from drivers/usbdcore.c)0
-rw-r--r--drivers/usb/usbdcore_ep0.c (renamed from drivers/usbdcore_ep0.c)0
-rw-r--r--drivers/usb/usbdcore_mpc8xx.c (renamed from drivers/usbdcore_mpc8xx.c)0
-rw-r--r--drivers/usb/usbdcore_omap1510.c (renamed from drivers/usbdcore_omap1510.c)0
-rw-r--r--drivers/video/Makefile53
-rw-r--r--drivers/video/ati_ids.h (renamed from drivers/ati_ids.h)0
-rw-r--r--drivers/video/ati_radeon_fb.c (renamed from drivers/ati_radeon_fb.c)8
-rw-r--r--drivers/video/ati_radeon_fb.h (renamed from drivers/ati_radeon_fb.h)0
-rw-r--r--drivers/video/cfb_console.c (renamed from drivers/cfb_console.c)0
-rw-r--r--drivers/video/ct69000.c (renamed from drivers/ct69000.c)0
-rw-r--r--drivers/video/sed13806.c (renamed from drivers/sed13806.c)0
-rw-r--r--drivers/video/sed156x.c (renamed from drivers/sed156x.c)0
-rw-r--r--drivers/video/sm501.c (renamed from drivers/sm501.c)0
-rw-r--r--drivers/video/smiLynxEM.c (renamed from drivers/smiLynxEM.c)0
-rw-r--r--drivers/video/videomodes.c (renamed from drivers/videomodes.c)0
-rw-r--r--drivers/video/videomodes.h (renamed from drivers/videomodes.h)0
231 files changed, 9835 insertions, 894 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
deleted file mode 100755
index 00978d8..0000000
--- a/drivers/Makefile
+++ /dev/null
@@ -1,73 +0,0 @@
-#
-# (C) Copyright 2000-2007
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# See file CREDITS for list of people who contributed to this
-# project.
-#
-# 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
-#
-
-include $(TOPDIR)/config.mk
-
-# CFLAGS += -DET_DEBUG -DDEBUG
-
-LIB = $(obj)libdrivers.a
-
-COBJS = 3c589.o 5701rls.o ali512x.o at45.o ata_piix.o \
- ati_radeon_fb.o atmel_usart.o \
- bcm570x.o bcm570x_autoneg.o cfb_console.o cfi_flash.o \
- cs8900.o ct69000.o dataflash.o dc2114x.o dm9000x.o \
- ds1722.o e1000.o eepro100.o enc28j60.o \
- fsl_i2c.o fsl_pci_init.o \
- i8042.o inca-ip_sw.o isp116x-hcd.o \
- keyboard.o ks8695eth.o \
- lan91c96.o macb.o mpc8xx_pcmcia.o mw_eeprom.o \
- natsemi.o ne2000.o netarm_eth.o netconsole.o \
- ns16550.o ns8382x.o ns87308.o ns7520_eth.o omap1510_i2c.o \
- omap24xx_i2c.o pc_keyb.o \
- pci.o pci_auto.o pci_indirect.o \
- pcnet.o plb2800_eth.o ps2ser.o ps2mult.o pxa_pcmcia.o \
- rpx_pcmcia.o rtl8019.o rtl8139.o rtl8169.o \
- s3c4510b_eth.o s3c4510b_uart.o \
- sed13806.o sed156x.o \
- serial.o serial_max3100.o \
- serial_pl010.o serial_pl011.o serial_xuartlite.o \
- sil680.o sl811_usb.o sm501.o smc91111.o smiLynxEM.o \
- status_led.o sym53c8xx.o systemace.o ahci.o \
- ti_pci1410a.o tigon3.o tqm8xx_pcmcia.o tsec.o \
- tsi108_eth.o tsi108_i2c.o tsi108_pci.o \
- usb_ohci.o \
- usbdcore.o usbdcore_ep0.o usbdcore_mpc8xx.o usbdcore_omap1510.o \
- usbtty.o \
- videomodes.o w83c553f.o
-
-SRCS := $(COBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS))
-
-all: $(LIB)
-
-$(LIB): $(obj).depend $(OBJS)
- $(AR) $(ARFLAGS) $@ $(OBJS)
-
-#########################################################################
-
-# defines $(obj).depend target
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
diff --git a/drivers/bios_emulator/besys.c b/drivers/bios_emulator/besys.c
index 8f1d8b2..cb1b0c1 100644
--- a/drivers/bios_emulator/besys.c
+++ b/drivers/bios_emulator/besys.c
@@ -96,7 +96,7 @@ static u8 *BE_memaddr(u32 addr)
else if (addr >= 0xFFFF5 && addr < 0xFFFFE) {
/* Return a faked BIOS date string for non-x86 machines */
DB(printf("BE_memaddr - Returning BIOS date\n");)
- return BE_biosDate + addr - 0xFFFF5;
+ return (u8 *)(BE_biosDate + addr - 0xFFFF5);
} else if (addr == 0xFFFFE) {
/* Return system model identifier for non-x86 machines */
DB(printf("BE_memaddr - Returning model\n");)
diff --git a/drivers/bios_emulator/biosemu.c b/drivers/bios_emulator/biosemu.c
index ccfc872..75ceb45 100644
--- a/drivers/bios_emulator/biosemu.c
+++ b/drivers/bios_emulator/biosemu.c
@@ -96,7 +96,7 @@ int X86API BE_init(u32 debugFlags, int memSize, BE_VGAInfo * info, int shared)
return 0;
}
- M.mem_base = (unsigned long)malloc(memSize);
+ M.mem_base = malloc(memSize);
if (M.mem_base == NULL){
printf("Biosemu:Out of memory!");
@@ -106,7 +106,7 @@ int X86API BE_init(u32 debugFlags, int memSize, BE_VGAInfo * info, int shared)
_BE_env.emulateVGA = 0;
_BE_env.busmem_base = (unsigned long)malloc(128 * 1024);
- if (_BE_env.busmem_base == NULL){
+ if ((void *)_BE_env.busmem_base == NULL){
printf("Biosemu:Out of memory!");
return 0;
}
@@ -230,7 +230,7 @@ Cleans up and exits the emulator.
void X86API BE_exit(void)
{
free(M.mem_base);
- free(_BE_env.busmem_base);
+ free((void *)_BE_env.busmem_base);
}
/****************************************************************************
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
new file mode 100644
index 0000000..e069969
--- /dev/null
+++ b/drivers/block/Makefile
@@ -0,0 +1,50 @@
+#
+# (C) Copyright 2000-2007
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB := $(obj)libblock.a
+
+COBJS-y += ahci.o
+COBJS-y += ata_piix.o
+COBJS-y += sil680.o
+COBJS-y += sym53c8xx.o
+COBJS-y += systemace.o
+
+COBJS := $(COBJS-y)
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/ahci.c b/drivers/block/ahci.c
index 3d82c62..3d82c62 100644
--- a/drivers/ahci.c
+++ b/drivers/block/ahci.c
diff --git a/drivers/ata_piix.c b/drivers/block/ata_piix.c
index 42456d7..42456d7 100644
--- a/drivers/ata_piix.c
+++ b/drivers/block/ata_piix.c
diff --git a/drivers/sil680.c b/drivers/block/sil680.c
index a6143df..a6143df 100644
--- a/drivers/sil680.c
+++ b/drivers/block/sil680.c
diff --git a/drivers/sym53c8xx.c b/drivers/block/sym53c8xx.c
index 29eeccd..29eeccd 100644
--- a/drivers/sym53c8xx.c
+++ b/drivers/block/sym53c8xx.c
diff --git a/drivers/systemace.c b/drivers/block/systemace.c
index 7d82c27..7d82c27 100644
--- a/drivers/systemace.c
+++ b/drivers/block/systemace.c
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
new file mode 100644
index 0000000..32e3f44
--- /dev/null
+++ b/drivers/hwmon/Makefile
@@ -0,0 +1,57 @@
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2001
+# Erik Theisen, Wave 7 Optics, etheisen@mindspring.com.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+#CFLAGS += -DDEBUG
+
+LIB = $(obj)libhwmon.a
+
+COBJS-y += adm1021.o
+COBJS-y += ds1621.o
+COBJS-y += ds1722.o
+COBJS-y += ds1775.o
+COBJS-y += lm73.o
+COBJS-y += lm75.o
+COBJS-y += lm81.o
+
+COBJS := $(COBJS-y)
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
new file mode 100644
index 0000000..9f65cfb
--- /dev/null
+++ b/drivers/hwmon/adm1021.c
@@ -0,0 +1,174 @@
+/*
+ * (C) Copyright 2003
+ * Murray Jensen, CSIRO-MIT, Murray.Jensen@csiro.au
+ *
+ * based on dtt/lm75.c which is ...
+ *
+ * (C) Copyright 2001
+ * Bill Hunter, Wave 7 Optics, williamhunter@mediaone.net
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Analog Devices's ADM1021
+ * "Low Cost Microprocessor System Temperature Monitor"
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_DTT_ADM1021
+
+#include <i2c.h>
+#include <dtt.h>
+
+typedef
+ struct {
+ uint i2c_addr:7; /* 7bit i2c chip address */
+ uint conv_rate:3; /* conversion rate */
+ uint enable_alert:1; /* enable alert output pin */
+ uint enable_local:1; /* enable internal temp sensor */
+ uint max_local:8; /* internal temp maximum */
+ uint min_local:8; /* internal temp minimum */
+ uint enable_remote:1; /* enable remote temp sensor */
+ uint max_remote:8; /* remote temp maximum */
+ uint min_remote:8; /* remote temp minimum */
+ }
+dtt_cfg_t;
+
+dtt_cfg_t dttcfg[] = CFG_DTT_ADM1021;
+
+int
+dtt_read (int sensor, int reg)
+{
+ dtt_cfg_t *dcp = &dttcfg[sensor >> 1];
+ uchar data;
+
+ if (i2c_read(dcp->i2c_addr, reg, 1, &data, 1) != 0)
+ return -1;
+
+ return (int)data;
+} /* dtt_read() */
+
+int
+dtt_write (int sensor, int reg, int val)
+{
+ dtt_cfg_t *dcp = &dttcfg[sensor >> 1];
+ uchar data;
+
+ data = (uchar)(val & 0xff);
+
+ if (i2c_write(dcp->i2c_addr, reg, 1, &data, 1) != 0)
+ return 1;
+
+ return 0;
+} /* dtt_write() */
+
+static int
+_dtt_init (int sensor)
+{
+ dtt_cfg_t *dcp = &dttcfg[sensor >> 1];
+ int reg, val;
+
+ if (((sensor & 1) == 0 ? dcp->enable_local : dcp->enable_remote) == 0)
+ return 1; /* sensor is disabled (or rather ignored) */
+
+ /*
+ * Setup High Limit register
+ */
+ if ((sensor & 1) == 0) {
+ reg = DTT_WRITE_LOC_HIGHLIM;
+ val = dcp->max_local;
+ }
+ else {
+ reg = DTT_WRITE_REM_HIGHLIM;
+ val = dcp->max_remote;
+ }
+ if (dtt_write (sensor, reg, val) != 0)
+ return 1;
+
+ /*
+ * Setup Low Limit register
+ */
+ if ((sensor & 1) == 0) {
+ reg = DTT_WRITE_LOC_LOWLIM;
+ val = dcp->min_local;
+ }
+ else {
+ reg = DTT_WRITE_REM_LOWLIM;
+ val = dcp->min_remote;
+ }
+ if (dtt_write (sensor, reg, val) != 0)
+ return 1;
+
+ /* shouldn't hurt if the rest gets done twice */
+
+ /*
+ * Setup Conversion Rate register
+ */
+ if (dtt_write (sensor, DTT_WRITE_CONVRATE, dcp->conv_rate) != 0)
+ return 1;
+
+ /*
+ * Setup configuraton register
+ */
+ val = 0; /* running */
+ if (dcp->enable_alert == 0)
+ val |= DTT_CONFIG_ALERT_MASKED; /* mask ALERT pin */
+ if (dtt_write (sensor, DTT_WRITE_CONFIG, val) != 0)
+ return 1;
+
+ return 0;
+} /* _dtt_init() */
+
+int
+dtt_init (void)
+{
+ int i;
+ unsigned char sensors[] = CONFIG_DTT_SENSORS;
+ const char *const header = "DTT: ";
+
+ /* switch to correct I2C bus */
+ I2C_SET_BUS(CFG_DTT_BUS_NUM);
+
+ for (i = 0; i < sizeof(sensors); i++) {
+ if (_dtt_init(sensors[i]) != 0)
+ printf ("%s%d FAILED INIT\n", header, i+1);
+ else
+ printf ("%s%d is %i C\n", header, i+1,
+ dtt_get_temp(sensors[i]));
+ }
+
+ return (0);
+} /* dtt_init() */
+
+int
+dtt_get_temp (int sensor)
+{
+ signed char val;
+
+ if ((sensor & 1) == 0)
+ val = dtt_read(sensor, DTT_READ_LOC_VALUE);
+ else
+ val = dtt_read(sensor, DTT_READ_REM_VALUE);
+
+ return (int) val;
+} /* dtt_get_temp() */
+
+#endif /* CONFIG_DTT_ADM1021 */
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
new file mode 100644
index 0000000..4948181
--- /dev/null
+++ b/drivers/hwmon/ds1621.c
@@ -0,0 +1,190 @@
+/*
+ * (C) Copyright 2001
+ * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Dallas Semiconductor's DS1621 Digital Thermometer and Thermostat.
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_DTT_DS1621
+#if !defined(CFG_EEPROM_PAGE_WRITE_ENABLE) || \
+ (CFG_EEPROM_PAGE_WRITE_BITS < 1)
+# error "CFG_EEPROM_PAGE_WRITE_ENABLE must be defined and CFG_EEPROM_PAGE_WRITE_BITS must be greater than 1 to use CONFIG_DTT_DS1621"
+#endif
+#include <i2c.h>
+#include <dtt.h>
+
+/*
+ * Device code
+ */
+#define DTT_I2C_DEV_CODE 0x48 /* Dallas Semi's DS1621 */
+
+int dtt_read(int sensor, int reg)
+{
+ int dlen;
+ uchar data[2];
+
+ /*
+ * Calculate sensor address and command.
+ *
+ */
+ sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* Calculate addr of ds1621*/
+
+ /*
+ * Prepare to handle 2 byte result.
+ */
+ if ((reg == DTT_READ_TEMP) ||
+ (reg == DTT_TEMP_HIGH) || (reg == DTT_TEMP_LOW))
+ dlen = 2;
+ else
+ dlen = 1;
+
+ /*
+ * Now try to read the register.
+ */
+ if (i2c_read(sensor, reg, 1, data, dlen) != 0)
+ return 1;
+
+ /*
+ * Handle 2 byte result.
+ */
+ if (dlen == 2)
+ return ((int)((short)data[1] + (((short)data[0]) << 8)));
+
+ return (int)data[0];
+} /* dtt_read() */
+
+
+int dtt_write(int sensor, int reg, int val)
+{
+ int dlen;
+ uchar data[2];
+
+ /*
+ * Calculate sensor address and register.
+ *
+ */
+ sensor = DTT_I2C_DEV_CODE + (sensor & 0x07);
+
+ /*
+ * Handle various data sizes.
+ */
+ if ((reg == DTT_READ_TEMP) ||
+ (reg == DTT_TEMP_HIGH) || (reg == DTT_TEMP_LOW)) {
+ dlen = 2;
+ data[0] = (char)((val >> 8) & 0xff); /* MSB first */
+ data[1] = (char)(val & 0xff);
+ }
+ else if ((reg == DTT_WRITE_START_CONV) || (reg == DTT_WRITE_STOP_CONV)) {
+ dlen = 0;
+ data[0] = (char)0;
+ data[1] = (char)0;
+ }
+ else {
+ dlen = 1;
+ data[0] = (char)(val & 0xff);
+ }
+
+ /*
+ * Write value to device.
+ */
+ if (i2c_write(sensor, reg, 1, data, dlen) != 0)
+ return 1;
+
+ return 0;
+} /* dtt_write() */
+
+
+static int _dtt_init(int sensor)
+{
+ int val;
+
+ /*
+ * Setup High Temp.
+ */
+ val = ((CFG_DTT_MAX_TEMP * 2) << 7) & 0xff80;
+ if (dtt_write(sensor, DTT_TEMP_HIGH, val) != 0)
+ return 1;
+ udelay(50000); /* Max 50ms */
+
+ /*
+ * Setup Low Temp - hysteresis.
+ */
+ val = (((CFG_DTT_MAX_TEMP - CFG_DTT_HYSTERESIS) * 2) << 7) & 0xff80;
+ if (dtt_write(sensor, DTT_TEMP_LOW, val) != 0)
+ return 1;
+ udelay(50000); /* Max 50ms */
+
+ /*
+ * Setup configuraton register
+ *
+ * Clear THF & TLF, Reserved = 1, Polarity = Active Low, One Shot = YES
+ *
+ * We run in polled mode, since there isn't any way to know if this
+ * lousy device is ready to provide temperature readings on power up.
+ */
+ val = 0x9;
+ if (dtt_write(sensor, DTT_CONFIG, val) != 0)
+ return 1;
+ udelay(50000); /* Max 50ms */
+
+ return 0;
+} /* _dtt_init() */
+
+
+int dtt_init (void)
+{
+ int i;
+ unsigned char sensors[] = CONFIG_DTT_SENSORS;
+
+ for (i = 0; i < sizeof(sensors); i++) {
+ if (_dtt_init(sensors[i]) != 0)
+ printf("DTT%d: FAILED\n", i+1);
+ else
+ printf("DTT%d: %i C\n", i+1, dtt_get_temp(sensors[i]));
+ }
+
+ return (0);
+} /* dtt_init() */
+
+
+int dtt_get_temp(int sensor)
+{
+ int i;
+
+ /*
+ * Start a conversion, may take up to 1 second.
+ */
+ dtt_write(sensor, DTT_WRITE_START_CONV, 0);
+ for (i = 0; i <= 10; i++) {
+ udelay(100000);
+ if (dtt_read(sensor, DTT_CONFIG) & 0x80)
+ break;
+ }
+
+ return (dtt_read(sensor, DTT_READ_TEMP) / 256);
+} /* dtt_get_temp() */
+
+
+#endif /* CONFIG_DTT_DS1621 */
diff --git a/drivers/ds1722.c b/drivers/hwmon/ds1722.c
index c19ee01..c19ee01 100644
--- a/drivers/ds1722.c
+++ b/drivers/hwmon/ds1722.c
diff --git a/drivers/hwmon/ds1775.c b/drivers/hwmon/ds1775.c
new file mode 100644
index 0000000..0fbb0b4
--- /dev/null
+++ b/drivers/hwmon/ds1775.c
@@ -0,0 +1,156 @@
+/*
+ * 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
+ */
+
+/*
+ * Dallas Semiconductor's DS1775 Digital Thermometer and Thermostat
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_DTT_DS1775
+#include <i2c.h>
+#include <dtt.h>
+
+#define DTT_I2C_DEV_CODE CFG_I2C_DTT_ADDR /* Dallas Semi's DS1775 device code */
+
+int dtt_read(int sensor, int reg)
+{
+ int dlen;
+ uchar data[2];
+
+ /*
+ * Calculate sensor address and command
+ */
+ sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* Calculate addr of ds1775 */
+
+ /*
+ * Prepare to handle 2 byte result
+ */
+ if ((reg == DTT_READ_TEMP) ||
+ (reg == DTT_TEMP_OS) || (reg == DTT_TEMP_HYST))
+ dlen = 2;
+ else
+ dlen = 1;
+
+ /*
+ * Now try to read the register
+ */
+ if (i2c_read(sensor, reg, 1, data, dlen) != 0)
+ return 1;
+
+ /*
+ * Handle 2 byte result
+ */
+ if (dlen == 2)
+ return ((int)((short)data[1] + (((short)data[0]) << 8)));
+
+ return (int) data[0];
+}
+
+
+int dtt_write(int sensor, int reg, int val)
+{
+ int dlen;
+ uchar data[2];
+
+ /*
+ * Calculate sensor address and register
+ */
+ sensor = DTT_I2C_DEV_CODE + (sensor & 0x07);
+
+ /*
+ * Handle various data sizes
+ */
+ if ((reg == DTT_READ_TEMP) ||
+ (reg == DTT_TEMP_OS) || (reg == DTT_TEMP_HYST)) {
+ dlen = 2;
+ data[0] = (char)((val >> 8) & 0xff); /* MSB first */
+ data[1] = (char)(val & 0xff);
+ } else {
+ dlen = 1;
+ data[0] = (char)(val & 0xff);
+ }
+
+ /*
+ * Write value to device
+ */
+ if (i2c_write(sensor, reg, 1, data, dlen) != 0)
+ return 1;
+
+ return 0;
+}
+
+
+static int _dtt_init(int sensor)
+{
+ int val;
+
+ /*
+ * Setup High Temp
+ */
+ val = ((CFG_DTT_MAX_TEMP * 2) << 7) & 0xff80;
+ if (dtt_write(sensor, DTT_TEMP_OS, val) != 0)
+ return 1;
+ udelay(50000); /* Max 50ms */
+
+ /*
+ * Setup Low Temp - hysteresis
+ */
+ val = (((CFG_DTT_MAX_TEMP - CFG_DTT_HYSTERESIS) * 2) << 7) & 0xff80;
+ if (dtt_write(sensor, DTT_TEMP_HYST, val) != 0)
+ return 1;
+ udelay(50000); /* Max 50ms */
+
+ /*
+ * Setup configuraton register
+ *
+ * Fault Tolerance limits 4, Thermometer resolution bits is 9,
+ * Polarity = Active Low,continuous conversion mode, Thermostat
+ * mode is interrupt mode
+ */
+ val = 0xa;
+ if (dtt_write(sensor, DTT_CONFIG, val) != 0)
+ return 1;
+ udelay(50000); /* Max 50ms */
+
+ return 0;
+}
+
+
+int dtt_init (void)
+{
+ int i;
+ unsigned char sensors[] = CONFIG_DTT_SENSORS;
+
+ for (i = 0; i < sizeof(sensors); i++) {
+ if (_dtt_init(sensors[i]) != 0)
+ printf("DTT%d: FAILED\n", i+1);
+ else
+ printf("DTT%d: %i C\n", i+1, dtt_get_temp(sensors[i]));
+ }
+
+ return (0);
+}
+
+
+int dtt_get_temp(int sensor)
+{
+ return (dtt_read(sensor, DTT_READ_TEMP) / 256);
+}
+
+
+#endif /* CONFIG_DTT_DS1775 */
diff --git a/drivers/hwmon/lm73.c b/drivers/hwmon/lm73.c
new file mode 100644
index 0000000..f9ae012
--- /dev/null
+++ b/drivers/hwmon/lm73.c
@@ -0,0 +1,181 @@
+/*
+ * (C) Copyright 2007
+ * Larry Johnson, lrj@acm.org
+ *
+ * based on dtt/lm75.c which is ...
+ *
+ * (C) Copyright 2001
+ * Bill Hunter, Wave 7 Optics, williamhunter@mediaone.net
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * National Semiconductor LM73 Temperature Sensor
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_DTT_LM73
+#if !defined(CFG_EEPROM_PAGE_WRITE_ENABLE) || \
+ (CFG_EEPROM_PAGE_WRITE_BITS < 1)
+# error "CFG_EEPROM_PAGE_WRITE_ENABLE must be defined and CFG_EEPROM_PAGE_WRITE_BITS must be greater than 1 to use CONFIG_DTT_LM73"
+#endif
+
+#include <i2c.h>
+#include <dtt.h>
+
+/*
+ * Device code
+ */
+#define DTT_I2C_DEV_CODE 0x48 /* National Semi's LM73 device */
+
+int dtt_read(int sensor, int reg)
+{
+ int dlen;
+ uchar data[2];
+
+ /*
+ * Validate 'reg' param and get register size.
+ */
+ switch (reg) {
+ case DTT_CONFIG:
+ case DTT_CONTROL:
+ dlen = 1;
+ break;
+ case DTT_READ_TEMP:
+ case DTT_TEMP_HIGH:
+ case DTT_TEMP_LOW:
+ case DTT_ID:
+ dlen = 2;
+ break;
+ default:
+ return -1;
+ }
+ /*
+ * Calculate sensor address and register.
+ */
+ sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* calculate LM73 addr */
+ /*
+ * Now try to read the register.
+ */
+ if (i2c_read(sensor, reg, 1, data, dlen) != 0)
+ return -1;
+ /*
+ * Handle 2 byte result.
+ */
+ if (2 == dlen)
+ return ((int)((short)data[1] + (((short)data[0]) << 8)));
+
+ return (int)data[0];
+} /* dtt_read() */
+
+int dtt_write(int sensor, int reg, int val)
+{
+ int dlen;
+ uchar data[2];
+
+ /*
+ * Validate 'reg' param and handle register size
+ */
+ switch (reg) {
+ case DTT_CONFIG:
+ case DTT_CONTROL:
+ dlen = 1;
+ data[0] = (char)(val & 0xff);
+ break;
+ case DTT_TEMP_HIGH:
+ case DTT_TEMP_LOW:
+ dlen = 2;
+ data[0] = (char)((val >> 8) & 0xff); /* MSB first */
+ data[1] = (char)(val & 0xff);
+ break;
+ default:
+ return -1;
+ }
+ /*
+ * Calculate sensor address and register.
+ */
+ sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* calculate LM73 addr */
+ /*
+ * Write value to register.
+ */
+ return i2c_write(sensor, reg, 1, data, dlen) != 0;
+} /* dtt_write() */
+
+static int _dtt_init(int sensor)
+{
+ int val;
+
+ /*
+ * Validate the Identification register
+ */
+ if (0x0190 != dtt_read(sensor, DTT_ID))
+ return 1;
+ /*
+ * Setup THIGH (upper-limit) and TLOW (lower-limit) registers
+ */
+ val = CFG_DTT_MAX_TEMP << 7;
+ if (dtt_write(sensor, DTT_TEMP_HIGH, val))
+ return 1;
+
+ val = CFG_DTT_MIN_TEMP << 7;
+ if (dtt_write(sensor, DTT_TEMP_LOW, val))
+ return 1;
+ /*
+ * Setup configuraton register
+ */
+ /* config = alert active low, disabled, and reset */
+ val = 0x64;
+ if (dtt_write(sensor, DTT_CONFIG, val))
+ return 1;
+ /*
+ * Setup control/status register
+ */
+ /* control = temp resolution 0.25C */
+ val = 0x00;
+ if (dtt_write(sensor, DTT_CONTROL, val))
+ return 1;
+
+ dtt_read(sensor, DTT_CONTROL); /* clear temperature flags */
+ return 0;
+} /* _dtt_init() */
+
+int dtt_init(void)
+{
+ int i;
+ unsigned char sensors[] = CONFIG_DTT_SENSORS;
+ const char *const header = "DTT: ";
+
+ for (i = 0; i < sizeof(sensors); i++) {
+ if (_dtt_init(sensors[i]) != 0)
+ printf("%s%d FAILED INIT\n", header, i + 1);
+ else
+ printf("%s%d is %i C\n", header, i + 1,
+ dtt_get_temp(sensors[i]));
+ }
+ return 0;
+} /* dtt_init() */
+
+int dtt_get_temp(int sensor)
+{
+ return (dtt_read(sensor, DTT_READ_TEMP) + 0x0040) >> 7;
+} /* dtt_get_temp() */
+
+#endif /* CONFIG_DTT_LM73 */
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
new file mode 100644
index 0000000..63f3b75
--- /dev/null
+++ b/drivers/hwmon/lm75.c
@@ -0,0 +1,185 @@
+/*
+ * (C) Copyright 2001
+ * Bill Hunter, Wave 7 Optics, williamhunter@mediaone.net
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * On Semiconductor's LM75 Temperature Sensor
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_DTT_LM75
+#if !defined(CFG_EEPROM_PAGE_WRITE_ENABLE) || \
+ (CFG_EEPROM_PAGE_WRITE_BITS < 1)
+# error "CFG_EEPROM_PAGE_WRITE_ENABLE must be defined and CFG_EEPROM_PAGE_WRITE_BITS must be greater than 1 to use CONFIG_DTT_LM75"
+#endif
+
+#include <i2c.h>
+#include <dtt.h>
+
+
+/*
+ * Device code
+ */
+#define DTT_I2C_DEV_CODE 0x48 /* ON Semi's LM75 device */
+
+int dtt_read(int sensor, int reg)
+{
+ int dlen;
+ uchar data[2];
+
+ /*
+ * Validate 'reg' param
+ */
+ if((reg < 0) || (reg > 3))
+ return -1;
+
+ /*
+ * Calculate sensor address and register.
+ */
+ sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* calculate address of lm75 */
+
+ /*
+ * Prepare to handle 2 byte result.
+ */
+ if ((reg == DTT_READ_TEMP) ||
+ (reg == DTT_TEMP_HYST) ||
+ (reg == DTT_TEMP_SET))
+ dlen = 2;
+ else
+ dlen = 1;
+
+ /*
+ * Now try to read the register.
+ */
+ if (i2c_read(sensor, reg, 1, data, dlen) != 0)
+ return -1;
+
+ /*
+ * Handle 2 byte result.
+ */
+ if (dlen == 2)
+ return ((int)((short)data[1] + (((short)data[0]) << 8)));
+
+
+ return (int)data[0];
+} /* dtt_read() */
+
+
+int dtt_write(int sensor, int reg, int val)
+{
+ int dlen;
+ uchar data[2];
+
+ /*
+ * Validate 'reg' param
+ */
+ if ((reg < 0) || (reg > 3))
+ return 1;
+
+ /*
+ * Calculate sensor address and register.
+ */
+ sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* calculate address of lm75 */
+
+ /*
+ * Handle 2 byte values.
+ */
+ if ((reg == DTT_READ_TEMP) ||
+ (reg == DTT_TEMP_HYST) ||
+ (reg == DTT_TEMP_SET)) {
+ dlen = 2;
+ data[0] = (char)((val >> 8) & 0xff); /* MSB first */
+ data[1] = (char)(val & 0xff);
+ } else {
+ dlen = 1;
+ data[0] = (char)(val & 0xff);
+ }
+
+ /*
+ * Write value to register.
+ */
+ if (i2c_write(sensor, reg, 1, data, dlen) != 0)
+ return 1;
+
+ return 0;
+} /* dtt_write() */
+
+
+static int _dtt_init(int sensor)
+{
+ int val;
+
+ /*
+ * Setup TSET ( trip point ) register
+ */
+ val = ((CFG_DTT_MAX_TEMP * 2) << 7) & 0xff80; /* trip */
+ if (dtt_write(sensor, DTT_TEMP_SET, val) != 0)
+ return 1;
+
+ /*
+ * Setup THYST ( untrip point ) register - Hysteresis
+ */
+ val = (((CFG_DTT_MAX_TEMP - CFG_DTT_HYSTERESIS) * 2) << 7) & 0xff80;
+ if (dtt_write(sensor, DTT_TEMP_HYST, val) != 0)
+ return 1;
+
+ /*
+ * Setup configuraton register
+ */
+#ifdef CONFIG_DTT_AD7414
+ /* config = alert active low and disabled */
+ val = 0x60;
+#else
+ /* config = 6 sample integration, int mode, active low, and enable */
+ val = 0x18;
+#endif
+ if (dtt_write(sensor, DTT_CONFIG, val) != 0)
+ return 1;
+
+ return 0;
+} /* _dtt_init() */
+
+
+int dtt_init (void)
+{
+ int i;
+ unsigned char sensors[] = CONFIG_DTT_SENSORS;
+ const char *const header = "DTT: ";
+
+ for (i = 0; i < sizeof(sensors); i++) {
+ if (_dtt_init(sensors[i]) != 0)
+ printf("%s%d FAILED INIT\n", header, i+1);
+ else
+ printf("%s%d is %i C\n", header, i+1,
+ dtt_get_temp(sensors[i]));
+ }
+
+ return (0);
+} /* dtt_init() */
+
+int dtt_get_temp(int sensor)
+{
+ return (dtt_read(sensor, DTT_READ_TEMP) / 256);
+} /* dtt_get_temp() */
+
+#endif /* CONFIG_DTT_LM75 */
diff --git a/drivers/hwmon/lm81.c b/drivers/hwmon/lm81.c
new file mode 100644
index 0000000..03bc53d
--- /dev/null
+++ b/drivers/hwmon/lm81.c
@@ -0,0 +1,148 @@
+/*
+ * (C) Copyright 2006
+ * Heiko Schocher, DENX Software Enginnering <hs@denx.de>
+ *
+ * based on dtt/lm75.c which is ...
+ *
+ * (C) Copyright 2001
+ * Bill Hunter, Wave 7 Optics, williamhunter@mediaone.net
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * On Semiconductor's LM81 Temperature Sensor
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_DTT_LM81
+#if !defined(CFG_EEPROM_PAGE_WRITE_ENABLE) || \
+ (CFG_EEPROM_PAGE_WRITE_BITS < 1)
+# error "CFG_EEPROM_PAGE_WRITE_ENABLE must be defined and CFG_EEPROM_PAGE_WRITE_BITS must be greater than 1 to use CONFIG_DTT_LM81"
+#endif
+
+#include <i2c.h>
+#include <dtt.h>
+
+/*
+ * Device code
+ */
+#define DTT_I2C_DEV_CODE 0x2c /* ON Semi's LM81 device */
+
+int dtt_read(int sensor, int reg)
+{
+ int dlen = 1;
+ uchar data[2];
+
+ /*
+ * Calculate sensor address and register.
+ */
+ sensor = DTT_I2C_DEV_CODE + (sensor & 0x03); /* calculate address of lm81 */
+
+ /*
+ * Now try to read the register.
+ */
+ if (i2c_read(sensor, reg, 1, data, dlen) != 0)
+ return -1;
+
+ return (int)data[0];
+} /* dtt_read() */
+
+
+int dtt_write(int sensor, int reg, int val)
+{
+ uchar data;
+
+ /*
+ * Calculate sensor address and register.
+ */
+ sensor = DTT_I2C_DEV_CODE + (sensor & 0x03); /* calculate address of lm81 */
+
+ data = (char)(val & 0xff);
+
+ /*
+ * Write value to register.
+ */
+ if (i2c_write(sensor, reg, 1, &data, 1) != 0)
+ return 1;
+
+ return 0;
+} /* dtt_write() */
+
+#define DTT_MANU 0x3e
+#define DTT_REV 0x3f
+#define DTT_CONFIG 0x40
+#define DTT_ADR 0x48
+
+static int _dtt_init(int sensor)
+{
+ int man;
+ int adr;
+ int rev;
+
+ if (dtt_write (sensor, DTT_CONFIG, 0x01) < 0)
+ return 1;
+ /* The LM81 needs 400ms to get the correct values ... */
+ udelay (400000);
+ man = dtt_read (sensor, DTT_MANU);
+ if (man != 0x01)
+ return 1;
+ adr = dtt_read (sensor, DTT_ADR);
+ if (adr < 0)
+ return 1;
+ rev = dtt_read (sensor, DTT_REV);
+ if (adr < 0)
+ return 1;
+
+ printf ("DTT: Found LM81@%x Rev: %d\n", adr, rev);
+ return 0;
+} /* _dtt_init() */
+
+
+int dtt_init (void)
+{
+ int i;
+ unsigned char sensors[] = CONFIG_DTT_SENSORS;
+ const char *const header = "DTT: ";
+
+ for (i = 0; i < sizeof(sensors); i++) {
+ if (_dtt_init(sensors[i]) != 0)
+ printf("%s%d FAILED INIT\n", header, i+1);
+ else
+ printf("%s%d is %i C\n", header, i+1,
+ dtt_get_temp(sensors[i]));
+ }
+
+ return (0);
+} /* dtt_init() */
+
+#define TEMP_FROM_REG(temp) \
+ ((temp)<256?((((temp)&0x1fe) >> 1) * 10) + ((temp) & 1) * 5: \
+ ((((temp)&0x1fe) >> 1) -255) * 10 - ((temp) & 1) * 5) \
+
+int dtt_get_temp(int sensor)
+{
+ int val = dtt_read (sensor, DTT_READ_TEMP);
+ int tmpcnf = dtt_read (sensor, DTT_CONFIG_TEMP);
+
+ return (TEMP_FROM_REG((val << 1) + ((tmpcnf & 0x80) >> 7))) / 10;
+} /* dtt_get_temp() */
+
+#endif /* CONFIG_DTT_LM81 */
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
new file mode 100644
index 0000000..29d6c03
--- /dev/null
+++ b/drivers/i2c/Makefile
@@ -0,0 +1,49 @@
+#
+# (C) Copyright 2000-2007
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB := $(obj)libi2c.a
+
+COBJS-y += fsl_i2c.o
+COBJS-y += omap1510_i2c.o
+COBJS-y += omap24xx_i2c.o
+COBJS-y += tsi108_i2c.o
+
+COBJS := $(COBJS-y)
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/fsl_i2c.c b/drivers/i2c/fsl_i2c.c
index 22485ea..22485ea 100644
--- a/drivers/fsl_i2c.c
+++ b/drivers/i2c/fsl_i2c.c
diff --git a/drivers/omap1510_i2c.c b/drivers/i2c/omap1510_i2c.c
index 04400fb..04400fb 100644
--- a/drivers/omap1510_i2c.c
+++ b/drivers/i2c/omap1510_i2c.c
diff --git a/drivers/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index 7dab786..7dab786 100644
--- a/drivers/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
diff --git a/drivers/tsi108_i2c.c b/drivers/i2c/tsi108_i2c.c
index 3a3b75c..d6736b0 100644
--- a/drivers/tsi108_i2c.c
+++ b/drivers/i2c/tsi108_i2c.c
@@ -276,7 +276,7 @@ int i2c_probe (uchar chip)
* The Tsi108 HW doesn't support sending just the chip address
* and checkong for an <ACK> back.
*/
- return i2c_read (chip, 0, 1, (char *)&tmp, 1);
+ return i2c_read (chip, 0, 1, (uchar *)&tmp, 1);
}
#endif
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
new file mode 100644
index 0000000..df22cf9
--- /dev/null
+++ b/drivers/input/Makefile
@@ -0,0 +1,48 @@
+#
+# (C) Copyright 2000-2007
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB := $(obj)libinput.a
+
+COBJS-y += i8042.o
+COBJS-y += keyboard.o
+COBJS-y += pc_keyb.o ps2ser.o ps2mult.o
+
+COBJS := $(COBJS-y)
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/i8042.c b/drivers/input/i8042.c
index 22c2a4e..22c2a4e 100644
--- a/drivers/i8042.c
+++ b/drivers/input/i8042.c
diff --git a/drivers/keyboard.c b/drivers/input/keyboard.c
index 9975202..9975202 100644
--- a/drivers/keyboard.c
+++ b/drivers/input/keyboard.c
diff --git a/drivers/pc_keyb.c b/drivers/input/pc_keyb.c
index 81d3e98..81d3e98 100644
--- a/drivers/pc_keyb.c
+++ b/drivers/input/pc_keyb.c
diff --git a/drivers/ps2mult.c b/drivers/input/ps2mult.c
index 9515a0f..9515a0f 100644
--- a/drivers/ps2mult.c
+++ b/drivers/input/ps2mult.c
diff --git a/drivers/ps2ser.c b/drivers/input/ps2ser.c
index 4e304f7..4e304f7 100644
--- a/drivers/ps2ser.c
+++ b/drivers/input/ps2ser.c
diff --git a/drivers/nand/Makefile b/drivers/misc/Makefile
index fb0185b..78cec21 100644
--- a/drivers/nand/Makefile
+++ b/drivers/misc/Makefile
@@ -1,5 +1,5 @@
#
-# (C) Copyright 2006
+# (C) Copyright 2000-2007
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# See file CREDITS for list of people who contributed to this
@@ -23,10 +23,13 @@
include $(TOPDIR)/config.mk
-LIB := $(obj)libnand.a
+LIB := $(obj)libmisc.a
-COBJS := nand.o nand_base.o nand_ids.o nand_ecc.o nand_bbt.o nand_util.o
+COBJS-y += ali512x.o
+COBJS-y += ns87308.o
+COBJS-y += status_led.o
+COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
diff --git a/drivers/ali512x.c b/drivers/misc/ali512x.c
index 7b7edc0..7b7edc0 100644
--- a/drivers/ali512x.c
+++ b/drivers/misc/ali512x.c
diff --git a/drivers/ns87308.c b/drivers/misc/ns87308.c
index cf4d359..cf4d359 100644
--- a/drivers/ns87308.c
+++ b/drivers/misc/ns87308.c
diff --git a/drivers/status_led.c b/drivers/misc/status_led.c
index ddb6c22..ddb6c22 100644
--- a/drivers/status_led.c
+++ b/drivers/misc/status_led.c
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
new file mode 100644
index 0000000..952e919
--- /dev/null
+++ b/drivers/mtd/Makefile
@@ -0,0 +1,50 @@
+#
+# (C) Copyright 2000-2007
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB := $(obj)libmtd.a
+
+COBJS-y += at45.o
+COBJS-y += cfi_flash.o
+COBJS-y += dataflash.o
+COBJS-y += mw_eeprom.o
+COBJS-$(CONFIG_FLASH_CFI_LEGACY) += jedec_flash.o
+
+COBJS := $(COBJS-y)
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/at45.c b/drivers/mtd/at45.c
index dac987a..dac987a 100644
--- a/drivers/at45.c
+++ b/drivers/mtd/at45.c
diff --git a/drivers/cfi_flash.c b/drivers/mtd/cfi_flash.c
index 5579a1e..4f61e36 100644
--- a/drivers/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -42,9 +42,12 @@
#ifdef CFG_FLASH_CFI_DRIVER
/*
- * This file implements a Common Flash Interface (CFI) driver for U-Boot.
- * The width of the port and the width of the chips are determined at initialization.
- * These widths are used to calculate the address for access CFI data structures.
+ * This file implements a Common Flash Interface (CFI) driver for
+ * U-Boot.
+ *
+ * The width of the port and the width of the chips are determined at
+ * initialization. These widths are used to calculate the address for
+ * access CFI data structures.
*
* References
* JEDEC Standard JESD68 - Common Flash Interface (CFI)
@@ -55,7 +58,7 @@
* AMD/Spansion Application Note: Migration from Single-byte to Three-byte
* Device IDs, Publication Number 25538 Revision A, November 8, 2001
*
- * define CFG_WRITE_SWAPPED_DATA, if you have to swap the Bytes between
+ * Define CFG_WRITE_SWAPPED_DATA, if you have to swap the Bytes between
* reading and writing ... (yes there is such a Hardware).
*/
@@ -98,10 +101,6 @@
#define AMD_STATUS_TOGGLE 0x40
#define AMD_STATUS_ERROR 0x20
-#define AMD_ADDR_ERASE_START ((info->portwidth == FLASH_CFI_8BIT) ? 0xAAA : 0x555)
-#define AMD_ADDR_START ((info->portwidth == FLASH_CFI_8BIT) ? 0xAAA : 0x555)
-#define AMD_ADDR_ACK ((info->portwidth == FLASH_CFI_8BIT) ? 0x555 : 0x2AA)
-
#define FLASH_OFFSET_MANUFACTURER_ID 0x00
#define FLASH_OFFSET_DEVICE_ID 0x01
#define FLASH_OFFSET_DEVICE_ID2 0x0E
@@ -110,7 +109,8 @@
#define FLASH_OFFSET_CFI_ALT 0x555
#define FLASH_OFFSET_CFI_RESP 0x10
#define FLASH_OFFSET_PRIMARY_VENDOR 0x13
-#define FLASH_OFFSET_EXT_QUERY_T_P_ADDR 0x15 /* extended query table primary addr */
+/* extended query table primary address */
+#define FLASH_OFFSET_EXT_QUERY_T_P_ADDR 0x15
#define FLASH_OFFSET_WTOUT 0x1F
#define FLASH_OFFSET_WBTOUT 0x20
#define FLASH_OFFSET_ETOUT 0x21
@@ -149,16 +149,9 @@ typedef union {
unsigned long long ll;
} cfiword_t;
-typedef union {
- volatile unsigned char *cp;
- volatile unsigned short *wp;
- volatile unsigned long *lp;
- volatile unsigned long long *llp;
-} cfiptr_t;
-
#define NUM_ERASE_REGIONS 4 /* max. number of erase regions */
-static uint flash_offset_cfi[2]={FLASH_OFFSET_CFI,FLASH_OFFSET_CFI_ALT};
+static uint flash_offset_cfi[2] = { FLASH_OFFSET_CFI, FLASH_OFFSET_CFI_ALT };
/* use CFG_MAX_FLASH_BANKS_DETECT if defined */
#ifdef CFG_MAX_FLASH_BANKS_DETECT
@@ -176,46 +169,151 @@ flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* FLASH chips info */
#define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT
#endif
+typedef unsigned long flash_sect_t;
+
+/* CFI standard query structure */
+struct cfi_qry {
+ u8 qry[3];
+ u16 p_id;
+ u16 p_adr;
+ u16 a_id;
+ u16 a_adr;
+ u8 vcc_min;
+ u8 vcc_max;
+ u8 vpp_min;
+ u8 vpp_max;
+ u8 word_write_timeout_typ;
+ u8 buf_write_timeout_typ;
+ u8 block_erase_timeout_typ;
+ u8 chip_erase_timeout_typ;
+ u8 word_write_timeout_max;
+ u8 buf_write_timeout_max;
+ u8 block_erase_timeout_max;
+ u8 chip_erase_timeout_max;
+ u8 dev_size;
+ u16 interface_desc;
+ u16 max_buf_write_size;
+ u8 num_erase_regions;
+ u32 erase_region_info[NUM_ERASE_REGIONS];
+} __attribute__((packed));
+
+struct cfi_pri_hdr {
+ u8 pri[3];
+ u8 major_version;
+ u8 minor_version;
+} __attribute__((packed));
+
+static void flash_write8(u8 value, void *addr)
+{
+ __raw_writeb(value, addr);
+}
+
+static void flash_write16(u16 value, void *addr)
+{
+ __raw_writew(value, addr);
+}
+
+static void flash_write32(u32 value, void *addr)
+{
+ __raw_writel(value, addr);
+}
+
+static void flash_write64(u64 value, void *addr)
+{
+ /* No architectures currently implement __raw_writeq() */
+ *(volatile u64 *)addr = value;
+}
+
+static u8 flash_read8(void *addr)
+{
+ return __raw_readb(addr);
+}
+
+static u16 flash_read16(void *addr)
+{
+ return __raw_readw(addr);
+}
+
+static u32 flash_read32(void *addr)
+{
+ return __raw_readl(addr);
+}
+
+static u64 flash_read64(void *addr)
+{
+ /* No architectures currently implement __raw_readq() */
+ return *(volatile u64 *)addr;
+}
/*-----------------------------------------------------------------------
- * Functions
*/
+#if defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_ADDR_REDUND) || (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
+static flash_info_t *flash_get_info(ulong base)
+{
+ int i;
+ flash_info_t * info = 0;
-typedef unsigned long flash_sect_t;
+ for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
+ info = & flash_info[i];
+ if (info->size && info->start[0] <= base &&
+ base <= info->start[0] + info->size - 1)
+ break;
+ }
-static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c);
-static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf);
-static void flash_write_cmd (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
-static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect);
-static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
-static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
-static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
-static void flash_read_jedec_ids (flash_info_t * info);
-static int flash_detect_cfi (flash_info_t * info);
-static int flash_write_cfiword (flash_info_t * info, ulong dest, cfiword_t cword);
-static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
- ulong tout, char *prompt);
-ulong flash_get_size (ulong base, int banknum);
-#if defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_ADDR_REDUND) || (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
-static flash_info_t *flash_get_info(ulong base);
-#endif
-#ifdef CFG_FLASH_USE_BUFFER_WRITE
-static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, int len);
+ return i == CFG_MAX_FLASH_BANKS ? 0 : info;
+}
#endif
+unsigned long flash_sector_size(flash_info_t *info, flash_sect_t sect)
+{
+ if (sect != (info->sector_count - 1))
+ return info->start[sect + 1] - info->start[sect];
+ else
+ return info->start[0] + info->size - info->start[sect];
+}
+
/*-----------------------------------------------------------------------
* create an address based on the offset and the port width
*/
-inline uchar *flash_make_addr (flash_info_t * info, flash_sect_t sect, uint offset)
+static inline void *
+flash_map (flash_info_t * info, flash_sect_t sect, uint offset)
+{
+ unsigned int byte_offset = offset * info->portwidth;
+
+ return map_physmem(info->start[sect] + byte_offset,
+ flash_sector_size(info, sect) - byte_offset,
+ MAP_NOCACHE);
+}
+
+static inline void flash_unmap(flash_info_t *info, flash_sect_t sect,
+ unsigned int offset, void *addr)
{
- return ((uchar *) (info->start[sect] + (offset * info->portwidth)));
+ unsigned int byte_offset = offset * info->portwidth;
+
+ unmap_physmem(addr, flash_sector_size(info, sect) - byte_offset);
+}
+
+/*-----------------------------------------------------------------------
+ * make a proper sized command based on the port and chip widths
+ */
+static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf)
+{
+ int i;
+ uchar *cp = (uchar *) cmdbuf;
+
+#if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA)
+ for (i = info->portwidth; i > 0; i--)
+#else
+ for (i = 1; i <= info->portwidth; i++)
+#endif
+ *cp++ = (i & (info->chipwidth - 1)) ? '\0' : cmd;
}
#ifdef DEBUG
/*-----------------------------------------------------------------------
* Debug support
*/
-void print_longlong (char *str, unsigned long long data)
+static void print_longlong (char *str, unsigned long long data)
{
int i;
char *cp;
@@ -224,28 +322,25 @@ void print_longlong (char *str, unsigned long long data)
for (i = 0; i < 8; i++)
sprintf (&str[i * 2], "%2.2x", *cp++);
}
-static void flash_printqry (flash_info_t * info, flash_sect_t sect)
+
+static void flash_printqry (struct cfi_qry *qry)
{
- cfiptr_t cptr;
+ u8 *p = (u8 *)qry;
int x, y;
- for (x = 0; x < 0x40; x += 16U / info->portwidth) {
- cptr.cp =
- flash_make_addr (info, sect,
- x + FLASH_OFFSET_CFI_RESP);
- debug ("%p : ", cptr.cp);
- for (y = 0; y < 16; y++) {
- debug ("%2.2x ", cptr.cp[y]);
- }
- debug (" ");
+ for (x = 0; x < sizeof(struct cfi_qry); x += 16) {
+ debug("%02x : ", x);
+ for (y = 0; y < 16; y++)
+ debug("%2.2x ", p[x + y]);
+ debug(" ");
for (y = 0; y < 16; y++) {
- if (cptr.cp[y] >= 0x20 && cptr.cp[y] <= 0x7e) {
- debug ("%c", cptr.cp[y]);
- } else {
- debug (".");
- }
+ unsigned char c = p[x + y];
+ if (c >= 0x20 && c <= 0x7e)
+ debug("%c", c);
+ else
+ debug(".");
}
- debug ("\n");
+ debug("\n");
}
}
#endif
@@ -254,192 +349,658 @@ static void flash_printqry (flash_info_t * info, flash_sect_t sect)
/*-----------------------------------------------------------------------
* read a character at a port width address
*/
-inline uchar flash_read_uchar (flash_info_t * info, uint offset)
+static inline uchar flash_read_uchar (flash_info_t * info, uint offset)
{
uchar *cp;
+ uchar retval;
- cp = flash_make_addr (info, 0, offset);
+ cp = flash_map (info, 0, offset);
#if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA)
- return (cp[0]);
+ retval = flash_read8(cp);
#else
- return (cp[info->portwidth - 1]);
+ retval = flash_read8(cp + info->portwidth - 1);
#endif
+ flash_unmap (info, 0, offset, cp);
+ return retval;
}
/*-----------------------------------------------------------------------
- * read a short word by swapping for ppc format.
+ * read a long word by picking the least significant byte of each maximum
+ * port size word. Swap for ppc format.
*/
-ushort flash_read_ushort (flash_info_t * info, flash_sect_t sect, uint offset)
+static ulong flash_read_long (flash_info_t * info, flash_sect_t sect,
+ uint offset)
{
uchar *addr;
- ushort retval;
+ ulong retval;
#ifdef DEBUG
int x;
#endif
- addr = flash_make_addr (info, sect, offset);
+ addr = flash_map (info, sect, offset);
#ifdef DEBUG
- debug ("ushort addr is at %p info->portwidth = %d\n", addr,
+ debug ("long addr is at %p info->portwidth = %d\n", addr,
info->portwidth);
- for (x = 0; x < 2 * info->portwidth; x++) {
- debug ("addr[%x] = 0x%x\n", x, addr[x]);
+ for (x = 0; x < 4 * info->portwidth; x++) {
+ debug ("addr[%x] = 0x%x\n", x, flash_read8(addr + x));
}
#endif
#if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA)
- retval = ((addr[(info->portwidth)] << 8) | addr[0]);
+ retval = ((flash_read8(addr) << 16) |
+ (flash_read8(addr + info->portwidth) << 24) |
+ (flash_read8(addr + 2 * info->portwidth)) |
+ (flash_read8(addr + 3 * info->portwidth) << 8));
#else
- retval = ((addr[(2 * info->portwidth) - 1] << 8) |
- addr[info->portwidth - 1]);
+ retval = ((flash_read8(addr + 2 * info->portwidth - 1) << 24) |
+ (flash_read8(addr + info->portwidth - 1) << 16) |
+ (flash_read8(addr + 4 * info->portwidth - 1) << 8) |
+ (flash_read8(addr + 3 * info->portwidth - 1)));
#endif
+ flash_unmap(info, sect, offset, addr);
- debug ("retval = 0x%x\n", retval);
return retval;
}
-/*-----------------------------------------------------------------------
- * read a long word by picking the least significant byte of each maximum
- * port size word. Swap for ppc format.
+/*
+ * Write a proper sized command to the correct address
*/
-ulong flash_read_long (flash_info_t * info, flash_sect_t sect, uint offset)
+static void flash_write_cmd (flash_info_t * info, flash_sect_t sect,
+ uint offset, uchar cmd)
{
- uchar *addr;
- ulong retval;
+ void *addr;
+ cfiword_t cword;
+
+ addr = flash_map (info, sect, offset);
+ flash_make_cmd (info, cmd, &cword);
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", addr, cmd,
+ cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+ flash_write8(cword.c, addr);
+ break;
+ case FLASH_CFI_16BIT:
+ debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr,
+ cmd, cword.w,
+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+ flash_write16(cword.w, addr);
+ break;
+ case FLASH_CFI_32BIT:
+ debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr,
+ cmd, cword.l,
+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+ flash_write32(cword.l, addr);
+ break;
+ case FLASH_CFI_64BIT:
#ifdef DEBUG
- int x;
+ {
+ char str[20];
+
+ print_longlong (str, cword.ll);
+
+ debug ("fwrite addr %p cmd %x %s 64 bit x %d bit\n",
+ addr, cmd, str,
+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+ }
#endif
- addr = flash_make_addr (info, sect, offset);
+ flash_write64(cword.ll, addr);
+ break;
+ }
+ /* Ensure all the instructions are fully finished */
+ sync();
+
+ flash_unmap(info, sect, offset, addr);
+}
+
+static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect)
+{
+ flash_write_cmd (info, sect, info->addr_unlock1, AMD_CMD_UNLOCK_START);
+ flash_write_cmd (info, sect, info->addr_unlock2, AMD_CMD_UNLOCK_ACK);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static int flash_isequal (flash_info_t * info, flash_sect_t sect,
+ uint offset, uchar cmd)
+{
+ void *addr;
+ cfiword_t cword;
+ int retval;
+
+ addr = flash_map (info, sect, offset);
+ flash_make_cmd (info, cmd, &cword);
+
+ debug ("is= cmd %x(%c) addr %p ", cmd, cmd, addr);
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ debug ("is= %x %x\n", flash_read8(addr), cword.c);
+ retval = (flash_read8(addr) == cword.c);
+ break;
+ case FLASH_CFI_16BIT:
+ debug ("is= %4.4x %4.4x\n", flash_read16(addr), cword.w);
+ retval = (flash_read16(addr) == cword.w);
+ break;
+ case FLASH_CFI_32BIT:
+ debug ("is= %8.8lx %8.8lx\n", flash_read32(addr), cword.l);
+ retval = (flash_read32(addr) == cword.l);
+ break;
+ case FLASH_CFI_64BIT:
#ifdef DEBUG
- debug ("long addr is at %p info->portwidth = %d\n", addr,
- info->portwidth);
- for (x = 0; x < 4 * info->portwidth; x++) {
- debug ("addr[%x] = 0x%x\n", x, addr[x]);
- }
-#endif
-#if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA)
- retval = (addr[0] << 16) | (addr[(info->portwidth)] << 24) |
- (addr[(2 * info->portwidth)]) | (addr[(3 * info->portwidth)] << 8);
-#else
- retval = (addr[(2 * info->portwidth) - 1] << 24) |
- (addr[(info->portwidth) - 1] << 16) |
- (addr[(4 * info->portwidth) - 1] << 8) |
- addr[(3 * info->portwidth) - 1];
+ {
+ char str1[20];
+ char str2[20];
+
+ print_longlong (str1, flash_read64(addr));
+ print_longlong (str2, cword.ll);
+ debug ("is= %s %s\n", str1, str2);
+ }
#endif
+ retval = (flash_read64(addr) == cword.ll);
+ break;
+ default:
+ retval = 0;
+ break;
+ }
+ flash_unmap(info, sect, offset, addr);
+
return retval;
}
+/*-----------------------------------------------------------------------
+ */
+static int flash_isset (flash_info_t * info, flash_sect_t sect,
+ uint offset, uchar cmd)
+{
+ void *addr;
+ cfiword_t cword;
+ int retval;
+
+ addr = flash_map (info, sect, offset);
+ flash_make_cmd (info, cmd, &cword);
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ retval = ((flash_read8(addr) & cword.c) == cword.c);
+ break;
+ case FLASH_CFI_16BIT:
+ retval = ((flash_read16(addr) & cword.w) == cword.w);
+ break;
+ case FLASH_CFI_32BIT:
+ retval = ((flash_read32(addr) & cword.l) == cword.l);
+ break;
+ case FLASH_CFI_64BIT:
+ retval = ((flash_read64(addr) & cword.ll) == cword.ll);
+ break;
+ default:
+ retval = 0;
+ break;
+ }
+ flash_unmap(info, sect, offset, addr);
+
+ return retval;
+}
/*-----------------------------------------------------------------------
*/
-unsigned long flash_init (void)
+static int flash_toggle (flash_info_t * info, flash_sect_t sect,
+ uint offset, uchar cmd)
{
- unsigned long size = 0;
- int i;
+ void *addr;
+ cfiword_t cword;
+ int retval;
-#ifdef CFG_FLASH_PROTECTION
- char *s = getenv("unlock");
+ addr = flash_map (info, sect, offset);
+ flash_make_cmd (info, cmd, &cword);
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ retval = ((flash_read8(addr) & cword.c) !=
+ (flash_read8(addr) & cword.c));
+ break;
+ case FLASH_CFI_16BIT:
+ retval = ((flash_read16(addr) & cword.w) !=
+ (flash_read16(addr) & cword.w));
+ break;
+ case FLASH_CFI_32BIT:
+ retval = ((flash_read32(addr) & cword.l) !=
+ (flash_read32(addr) & cword.l));
+ break;
+ case FLASH_CFI_64BIT:
+ retval = ((flash_read64(addr) & cword.ll) !=
+ (flash_read64(addr) & cword.ll));
+ break;
+ default:
+ retval = 0;
+ break;
+ }
+ flash_unmap(info, sect, offset, addr);
+
+ return retval;
+}
+
+/*
+ * flash_is_busy - check to see if the flash is busy
+ *
+ * This routine checks the status of the chip and returns true if the
+ * chip is busy.
+ */
+static int flash_is_busy (flash_info_t * info, flash_sect_t sect)
+{
+ int retval;
+
+ switch (info->vendor) {
+ case CFI_CMDSET_INTEL_STANDARD:
+ case CFI_CMDSET_INTEL_EXTENDED:
+ retval = !flash_isset (info, sect, 0, FLASH_STATUS_DONE);
+ break;
+ case CFI_CMDSET_AMD_STANDARD:
+ case CFI_CMDSET_AMD_EXTENDED:
+#ifdef CONFIG_FLASH_CFI_LEGACY
+ case CFI_CMDSET_AMD_LEGACY:
#endif
+ retval = flash_toggle (info, sect, 0, AMD_STATUS_TOGGLE);
+ break;
+ default:
+ retval = 0;
+ }
+ debug ("flash_is_busy: %d\n", retval);
+ return retval;
+}
- /* Init: no FLASHes known */
- for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
- flash_info[i].flash_id = FLASH_UNKNOWN;
- size += flash_info[i].size = flash_get_size (bank_base[i], i);
- if (flash_info[i].flash_id == FLASH_UNKNOWN) {
-#ifndef CFG_FLASH_QUIET_TEST
- printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
- i+1, flash_info[i].size, flash_info[i].size << 20);
-#endif /* CFG_FLASH_QUIET_TEST */
- }
-#ifdef CFG_FLASH_PROTECTION
- else if ((s != NULL) && (strcmp(s, "yes") == 0)) {
- /*
- * Only the U-Boot image and it's environment is protected,
- * all other sectors are unprotected (unlocked) if flash
- * hardware protection is used (CFG_FLASH_PROTECTION) and
- * the environment variable "unlock" is set to "yes".
- */
- if (flash_info[i].legacy_unlock) {
- int k;
+/*-----------------------------------------------------------------------
+ * wait for XSR.7 to be set. Time out with an error if it does not.
+ * This routine does not set the flash to read-array mode.
+ */
+static int flash_status_check (flash_info_t * info, flash_sect_t sector,
+ ulong tout, char *prompt)
+{
+ ulong start;
- /*
- * Disable legacy_unlock temporarily, since
- * flash_real_protect would relock all other sectors
- * again otherwise.
- */
- flash_info[i].legacy_unlock = 0;
+#if CFG_HZ != 1000
+ tout *= CFG_HZ/1000;
+#endif
- /*
- * Legacy unlocking (e.g. Intel J3) -> unlock only one
- * sector. This will unlock all sectors.
- */
- flash_real_protect (&flash_info[i], 0, 0);
+ /* Wait for command completion */
+ start = get_timer (0);
+ while (flash_is_busy (info, sector)) {
+ if (get_timer (start) > tout) {
+ printf ("Flash %s timeout at address %lx data %lx\n",
+ prompt, info->start[sector],
+ flash_read_long (info, sector, 0));
+ flash_write_cmd (info, sector, 0, info->cmd_reset);
+ return ERR_TIMOUT;
+ }
+ udelay (1); /* also triggers watchdog */
+ }
+ return ERR_OK;
+}
- flash_info[i].legacy_unlock = 1;
+/*-----------------------------------------------------------------------
+ * Wait for XSR.7 to be set, if it times out print an error, otherwise
+ * do a full status check.
+ *
+ * This routine sets the flash to read-array mode.
+ */
+static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
+ ulong tout, char *prompt)
+{
+ int retcode;
- /*
- * Manually mark other sectors as unlocked (unprotected)
- */
- for (k = 1; k < flash_info[i].sector_count; k++)
- flash_info[i].protect[k] = 0;
- } else {
- /*
- * No legancy unlocking -> unlock all sectors
- */
- flash_protect (FLAG_PROTECT_CLEAR,
- flash_info[i].start[0],
- flash_info[i].start[0] + flash_info[i].size - 1,
- &flash_info[i]);
+ retcode = flash_status_check (info, sector, tout, prompt);
+ switch (info->vendor) {
+ case CFI_CMDSET_INTEL_EXTENDED:
+ case CFI_CMDSET_INTEL_STANDARD:
+ if ((retcode == ERR_OK)
+ && !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) {
+ retcode = ERR_INVAL;
+ printf ("Flash %s error at address %lx\n", prompt,
+ info->start[sector]);
+ if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS |
+ FLASH_STATUS_PSLBS)) {
+ puts ("Command Sequence Error.\n");
+ } else if (flash_isset (info, sector, 0,
+ FLASH_STATUS_ECLBS)) {
+ puts ("Block Erase Error.\n");
+ retcode = ERR_NOT_ERASED;
+ } else if (flash_isset (info, sector, 0,
+ FLASH_STATUS_PSLBS)) {
+ puts ("Locking Error\n");
}
+ if (flash_isset (info, sector, 0, FLASH_STATUS_DPS)) {
+ puts ("Block locked.\n");
+ retcode = ERR_PROTECTED;
+ }
+ if (flash_isset (info, sector, 0, FLASH_STATUS_VPENS))
+ puts ("Vpp Low Error.\n");
}
-#endif /* CFG_FLASH_PROTECTION */
+ flash_write_cmd (info, sector, 0, info->cmd_reset);
+ break;
+ default:
+ break;
}
+ return retcode;
+}
- /* Monitor protection ON by default */
-#if (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
- flash_protect (FLAG_PROTECT_SET,
- CFG_MONITOR_BASE,
- CFG_MONITOR_BASE + monitor_flash_len - 1,
- flash_get_info(CFG_MONITOR_BASE));
+/*-----------------------------------------------------------------------
+ */
+static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c)
+{
+#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
+ unsigned short w;
+ unsigned int l;
+ unsigned long long ll;
#endif
- /* Environment protection ON by default */
-#ifdef CFG_ENV_IS_IN_FLASH
- flash_protect (FLAG_PROTECT_SET,
- CFG_ENV_ADDR,
- CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1,
- flash_get_info(CFG_ENV_ADDR));
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ cword->c = c;
+ break;
+ case FLASH_CFI_16BIT:
+#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
+ w = c;
+ w <<= 8;
+ cword->w = (cword->w >> 8) | w;
+#else
+ cword->w = (cword->w << 8) | c;
#endif
-
- /* Redundant environment protection ON by default */
-#ifdef CFG_ENV_ADDR_REDUND
- flash_protect (FLAG_PROTECT_SET,
- CFG_ENV_ADDR_REDUND,
- CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1,
- flash_get_info(CFG_ENV_ADDR_REDUND));
+ break;
+ case FLASH_CFI_32BIT:
+#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
+ l = c;
+ l <<= 24;
+ cword->l = (cword->l >> 8) | l;
+#else
+ cword->l = (cword->l << 8) | c;
#endif
- return (size);
+ break;
+ case FLASH_CFI_64BIT:
+#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
+ ll = c;
+ ll <<= 56;
+ cword->ll = (cword->ll >> 8) | ll;
+#else
+ cword->ll = (cword->ll << 8) | c;
+#endif
+ break;
+ }
+}
+
+/* loop through the sectors from the highest address when the passed
+ * address is greater or equal to the sector address we have a match
+ */
+static flash_sect_t find_sector (flash_info_t * info, ulong addr)
+{
+ flash_sect_t sector;
+
+ for (sector = info->sector_count - 1; sector >= 0; sector--) {
+ if (addr >= info->start[sector])
+ break;
+ }
+ return sector;
}
/*-----------------------------------------------------------------------
*/
-#if defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_ADDR_REDUND) || (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
-static flash_info_t *flash_get_info(ulong base)
+static int flash_write_cfiword (flash_info_t * info, ulong dest,
+ cfiword_t cword)
{
- int i;
- flash_info_t * info = 0;
+ void *dstaddr;
+ int flag;
- for (i = 0; i < CFG_MAX_FLASH_BANKS; i ++) {
- info = & flash_info[i];
- if (info->size && info->start[0] <= base &&
- base <= info->start[0] + info->size - 1)
+ dstaddr = map_physmem(dest, info->portwidth, MAP_NOCACHE);
+
+ /* Check if Flash is (sufficiently) erased */
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ flag = ((flash_read8(dstaddr) & cword.c) == cword.c);
+ break;
+ case FLASH_CFI_16BIT:
+ flag = ((flash_read16(dstaddr) & cword.w) == cword.w);
+ break;
+ case FLASH_CFI_32BIT:
+ flag = ((flash_read32(dstaddr) & cword.l) == cword.l);
+ break;
+ case FLASH_CFI_64BIT:
+ flag = ((flash_read64(dstaddr) & cword.ll) == cword.ll);
+ break;
+ default:
+ flag = 0;
+ break;
+ }
+ if (!flag) {
+ unmap_physmem(dstaddr, info->portwidth);
+ return ERR_NOT_ERASED;
+ }
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts ();
+
+ switch (info->vendor) {
+ case CFI_CMDSET_INTEL_EXTENDED:
+ case CFI_CMDSET_INTEL_STANDARD:
+ flash_write_cmd (info, 0, 0, FLASH_CMD_CLEAR_STATUS);
+ flash_write_cmd (info, 0, 0, FLASH_CMD_WRITE);
+ break;
+ case CFI_CMDSET_AMD_EXTENDED:
+ case CFI_CMDSET_AMD_STANDARD:
+#ifdef CONFIG_FLASH_CFI_LEGACY
+ case CFI_CMDSET_AMD_LEGACY:
+#endif
+ flash_unlock_seq (info, 0);
+ flash_write_cmd (info, 0, info->addr_unlock1, AMD_CMD_WRITE);
+ break;
+ }
+
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ flash_write8(cword.c, dstaddr);
+ break;
+ case FLASH_CFI_16BIT:
+ flash_write16(cword.w, dstaddr);
+ break;
+ case FLASH_CFI_32BIT:
+ flash_write32(cword.l, dstaddr);
+ break;
+ case FLASH_CFI_64BIT:
+ flash_write64(cword.ll, dstaddr);
+ break;
+ }
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts ();
+
+ unmap_physmem(dstaddr, info->portwidth);
+
+ return flash_full_status_check (info, find_sector (info, dest),
+ info->write_tout, "write");
+}
+
+#ifdef CFG_FLASH_USE_BUFFER_WRITE
+
+static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
+ int len)
+{
+ flash_sect_t sector;
+ int cnt;
+ int retcode;
+ void *src = cp;
+ void *dst = map_physmem(dest, len, MAP_NOCACHE);
+ void *dst2 = dst;
+ int flag = 0;
+
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ cnt = len;
+ break;
+ case FLASH_CFI_16BIT:
+ cnt = len >> 1;
+ break;
+ case FLASH_CFI_32BIT:
+ cnt = len >> 2;
+ break;
+ case FLASH_CFI_64BIT:
+ cnt = len >> 3;
+ break;
+ default:
+ retcode = ERR_INVAL;
+ goto out_unmap;
+ }
+
+ while ((cnt-- > 0) && (flag == 0)) {
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ flag = ((flash_read8(dst2) & flash_read8(src)) ==
+ flash_read8(src));
+ src += 1, dst2 += 1;
break;
+ case FLASH_CFI_16BIT:
+ flag = ((flash_read16(dst2) & flash_read16(src)) ==
+ flash_read16(src));
+ src += 2, dst2 += 2;
+ break;
+ case FLASH_CFI_32BIT:
+ flag = ((flash_read32(dst2) & flash_read32(src)) ==
+ flash_read32(src));
+ src += 4, dst2 += 4;
+ break;
+ case FLASH_CFI_64BIT:
+ flag = ((flash_read64(dst2) & flash_read64(src)) ==
+ flash_read64(src));
+ src += 8, dst2 += 8;
+ break;
+ }
+ }
+ if (!flag) {
+ retcode = ERR_NOT_ERASED;
+ goto out_unmap;
}
- return i == CFG_MAX_FLASH_BANKS ? 0 : info;
+ src = cp;
+ sector = find_sector (info, dest);
+
+ switch (info->vendor) {
+ case CFI_CMDSET_INTEL_STANDARD:
+ case CFI_CMDSET_INTEL_EXTENDED:
+ flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
+ flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
+ retcode = flash_status_check (info, sector,
+ info->buffer_write_tout,
+ "write to buffer");
+ if (retcode == ERR_OK) {
+ /* reduce the number of loops by the width of
+ * the port */
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ cnt = len;
+ break;
+ case FLASH_CFI_16BIT:
+ cnt = len >> 1;
+ break;
+ case FLASH_CFI_32BIT:
+ cnt = len >> 2;
+ break;
+ case FLASH_CFI_64BIT:
+ cnt = len >> 3;
+ break;
+ default:
+ retcode = ERR_INVAL;
+ goto out_unmap;
+ }
+ flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
+ while (cnt-- > 0) {
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ flash_write8(flash_read8(src), dst);
+ src += 1, dst += 1;
+ break;
+ case FLASH_CFI_16BIT:
+ flash_write16(flash_read16(src), dst);
+ src += 2, dst += 2;
+ break;
+ case FLASH_CFI_32BIT:
+ flash_write32(flash_read32(src), dst);
+ src += 4, dst += 4;
+ break;
+ case FLASH_CFI_64BIT:
+ flash_write64(flash_read64(src), dst);
+ src += 8, dst += 8;
+ break;
+ default:
+ retcode = ERR_INVAL;
+ goto out_unmap;
+ }
+ }
+ flash_write_cmd (info, sector, 0,
+ FLASH_CMD_WRITE_BUFFER_CONFIRM);
+ retcode = flash_full_status_check (
+ info, sector, info->buffer_write_tout,
+ "buffer write");
+ }
+
+ break;
+
+ case CFI_CMDSET_AMD_STANDARD:
+ case CFI_CMDSET_AMD_EXTENDED:
+ flash_unlock_seq(info,0);
+ flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_TO_BUFFER);
+
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ cnt = len;
+ flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
+ while (cnt-- > 0) {
+ flash_write8(flash_read8(src), dst);
+ src += 1, dst += 1;
+ }
+ break;
+ case FLASH_CFI_16BIT:
+ cnt = len >> 1;
+ flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
+ while (cnt-- > 0) {
+ flash_write16(flash_read16(src), dst);
+ src += 2, dst += 2;
+ }
+ break;
+ case FLASH_CFI_32BIT:
+ cnt = len >> 2;
+ flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
+ while (cnt-- > 0) {
+ flash_write32(flash_read32(src), dst);
+ src += 4, dst += 4;
+ }
+ break;
+ case FLASH_CFI_64BIT:
+ cnt = len >> 3;
+ flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
+ while (cnt-- > 0) {
+ flash_write64(flash_read64(src), dst);
+ src += 8, dst += 8;
+ }
+ break;
+ default:
+ retcode = ERR_INVAL;
+ goto out_unmap;
+ }
+
+ flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM);
+ retcode = flash_full_status_check (info, sector,
+ info->buffer_write_tout,
+ "buffer write");
+ break;
+
+ default:
+ debug ("Unknown Command Set\n");
+ retcode = ERR_INVAL;
+ break;
+ }
+
+out_unmap:
+ unmap_physmem(dst, len);
+ return retcode;
}
-#endif
+#endif /* CFG_FLASH_USE_BUFFER_WRITE */
+
/*-----------------------------------------------------------------------
*/
@@ -465,7 +1026,8 @@ int flash_erase (flash_info_t * info, int s_first, int s_last)
}
}
if (prot) {
- printf ("- Warning: %d protected sectors will not be erased!\n", prot);
+ printf ("- Warning: %d protected sectors will not be erased!\n",
+ prot);
} else {
putc ('\n');
}
@@ -476,18 +1038,33 @@ int flash_erase (flash_info_t * info, int s_first, int s_last)
switch (info->vendor) {
case CFI_CMDSET_INTEL_STANDARD:
case CFI_CMDSET_INTEL_EXTENDED:
- flash_write_cmd (info, sect, 0, FLASH_CMD_CLEAR_STATUS);
- flash_write_cmd (info, sect, 0, FLASH_CMD_BLOCK_ERASE);
- flash_write_cmd (info, sect, 0, FLASH_CMD_ERASE_CONFIRM);
+ flash_write_cmd (info, sect, 0,
+ FLASH_CMD_CLEAR_STATUS);
+ flash_write_cmd (info, sect, 0,
+ FLASH_CMD_BLOCK_ERASE);
+ flash_write_cmd (info, sect, 0,
+ FLASH_CMD_ERASE_CONFIRM);
break;
case CFI_CMDSET_AMD_STANDARD:
case CFI_CMDSET_AMD_EXTENDED:
flash_unlock_seq (info, sect);
- flash_write_cmd (info, sect, AMD_ADDR_ERASE_START,
- AMD_CMD_ERASE_START);
+ flash_write_cmd (info, sect,
+ info->addr_unlock1,
+ AMD_CMD_ERASE_START);
flash_unlock_seq (info, sect);
- flash_write_cmd (info, sect, 0, AMD_CMD_ERASE_SECTOR);
+ flash_write_cmd (info, sect, 0,
+ AMD_CMD_ERASE_SECTOR);
+ break;
+#ifdef CONFIG_FLASH_CFI_LEGACY
+ case CFI_CMDSET_AMD_LEGACY:
+ flash_unlock_seq (info, 0);
+ flash_write_cmd (info, 0, info->addr_unlock1,
+ AMD_CMD_ERASE_START);
+ flash_unlock_seq (info, 0);
+ flash_write_cmd (info, sect, 0,
+ AMD_CMD_ERASE_SECTOR);
break;
+#endif
default:
debug ("Unkown flash vendor %d\n",
info->vendor);
@@ -516,10 +1093,15 @@ void flash_print_info (flash_info_t * info)
return;
}
- printf ("CFI conformant FLASH (%d x %d)",
+ printf ("%s FLASH (%d x %d)",
+ info->name,
(info->portwidth << 3), (info->chipwidth << 3));
- printf (" Size: %ld MB in %d Sectors\n",
- info->size >> 20, info->sector_count);
+ if (info->size < 1024*1024)
+ printf (" Size: %ld kB in %d Sectors\n",
+ info->size >> 10, info->sector_count);
+ else
+ printf (" Size: %ld MB in %d Sectors\n",
+ info->size >> 20, info->sector_count);
printf (" ");
switch (info->vendor) {
case CFI_CMDSET_INTEL_STANDARD:
@@ -534,6 +1116,11 @@ void flash_print_info (flash_info_t * info)
case CFI_CMDSET_AMD_EXTENDED:
printf ("AMD Extended");
break;
+#ifdef CONFIG_FLASH_CFI_LEGACY
+ case CFI_CMDSET_AMD_LEGACY:
+ printf ("AMD Legacy");
+ break;
+#endif
default:
printf ("Unknown (%d)", info->vendor);
break;
@@ -547,7 +1134,8 @@ void flash_print_info (flash_info_t * info)
info->erase_blk_tout,
info->write_tout);
if (info->buffer_size > 1) {
- printf (" Buffer write timeout: %ld ms, buffer size: %d bytes\n",
+ printf (" Buffer write timeout: %ld ms, "
+ "buffer size: %d bytes\n",
info->buffer_write_tout,
info->buffer_size);
}
@@ -565,10 +1153,7 @@ void flash_print_info (flash_info_t * info)
/*
* Check if whole sector is erased
*/
- if (i != (info->sector_count - 1))
- size = info->start[i + 1] - info->start[i];
- else
- size = info->start[0] + info->size - info->start[i];
+ size = flash_sector_size(info, i);
erased = 1;
flash = (volatile unsigned long *) info->start[i];
size = size >> 2; /* divide by 4 for longword access */
@@ -603,7 +1188,7 @@ void flash_print_info (flash_info_t * info)
int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
{
ulong wp;
- ulong cp;
+ uchar *p;
int aln;
cfiword_t cword;
int i, rc;
@@ -612,26 +1197,28 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
int buffered_size;
#endif
/* get lower aligned address */
- /* get lower aligned address */
wp = (addr & ~(info->portwidth - 1));
/* handle unaligned start */
if ((aln = addr - wp) != 0) {
cword.l = 0;
- cp = wp;
- for (i = 0; i < aln; ++i, ++cp)
- flash_add_byte (info, &cword, (*(uchar *) cp));
+ p = map_physmem(wp, info->portwidth, MAP_NOCACHE);
+ for (i = 0; i < aln; ++i)
+ flash_add_byte (info, &cword, flash_read8(p + i));
for (; (i < info->portwidth) && (cnt > 0); i++) {
flash_add_byte (info, &cword, *src++);
cnt--;
- cp++;
}
- for (; (cnt == 0) && (i < info->portwidth); ++i, ++cp)
- flash_add_byte (info, &cword, (*(uchar *) cp));
- if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
+ for (; (cnt == 0) && (i < info->portwidth); ++i)
+ flash_add_byte (info, &cword, flash_read8(p + i));
+
+ rc = flash_write_cfiword (info, wp, cword);
+ unmap_physmem(p, info->portwidth);
+ if (rc != 0)
return rc;
- wp = cp;
+
+ wp += i;
}
/* handle the aligned part */
@@ -682,13 +1269,14 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
* handle unaligned tail bytes
*/
cword.l = 0;
- for (i = 0, cp = wp; (i < info->portwidth) && (cnt > 0); ++i, ++cp) {
+ p = map_physmem(wp, info->portwidth, MAP_NOCACHE);
+ for (i = 0; (i < info->portwidth) && (cnt > 0); ++i) {
flash_add_byte (info, &cword, *src++);
--cnt;
}
- for (; i < info->portwidth; ++i, ++cp) {
- flash_add_byte (info, &cword, (*(uchar *) cp));
- }
+ for (; i < info->portwidth; ++i)
+ flash_add_byte (info, &cword, flash_read8(p + i));
+ unmap_physmem(p, info->portwidth);
return flash_write_cfiword (info, wp, cword);
}
@@ -740,10 +1328,11 @@ void flash_read_user_serial (flash_info_t * info, void *buffer, int offset,
uchar *dst;
dst = buffer;
- src = flash_make_addr (info, 0, FLASH_OFFSET_USER_PROTECTION);
+ src = flash_map (info, 0, FLASH_OFFSET_USER_PROTECTION);
flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
memcpy (dst, src + offset, len);
flash_write_cmd (info, 0, 0, info->cmd_reset);
+ flash_unmap(info, 0, FLASH_OFFSET_USER_PROTECTION, src);
}
/*
@@ -754,418 +1343,310 @@ void flash_read_factory_serial (flash_info_t * info, void *buffer, int offset,
{
uchar *src;
- src = flash_make_addr (info, 0, FLASH_OFFSET_INTEL_PROTECTION);
+ src = flash_map (info, 0, FLASH_OFFSET_INTEL_PROTECTION);
flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
memcpy (buffer, src + offset, len);
flash_write_cmd (info, 0, 0, info->cmd_reset);
+ flash_unmap(info, 0, FLASH_OFFSET_INTEL_PROTECTION, src);
}
#endif /* CFG_FLASH_PROTECTION */
-/*
- * flash_is_busy - check to see if the flash is busy
- * This routine checks the status of the chip and returns true if the chip is busy
+/*-----------------------------------------------------------------------
+ * Reverse the order of the erase regions in the CFI QRY structure.
+ * This is needed for chips that are either a) correctly detected as
+ * top-boot, or b) buggy.
*/
-static int flash_is_busy (flash_info_t * info, flash_sect_t sect)
+static void cfi_reverse_geometry(struct cfi_qry *qry)
{
- int retval;
+ unsigned int i, j;
+ u32 tmp;
- switch (info->vendor) {
- case CFI_CMDSET_INTEL_STANDARD:
- case CFI_CMDSET_INTEL_EXTENDED:
- retval = !flash_isset (info, sect, 0, FLASH_STATUS_DONE);
- break;
- case CFI_CMDSET_AMD_STANDARD:
- case CFI_CMDSET_AMD_EXTENDED:
- retval = flash_toggle (info, sect, 0, AMD_STATUS_TOGGLE);
- break;
- default:
- retval = 0;
+ for (i = 0, j = qry->num_erase_regions - 1; i < j; i++, j--) {
+ tmp = qry->erase_region_info[i];
+ qry->erase_region_info[i] = qry->erase_region_info[j];
+ qry->erase_region_info[j] = tmp;
}
- debug ("flash_is_busy: %d\n", retval);
- return retval;
}
/*-----------------------------------------------------------------------
- * wait for XSR.7 to be set. Time out with an error if it does not.
- * This routine does not set the flash to read-array mode.
+ * read jedec ids from device and set corresponding fields in info struct
+ *
+ * Note: assume cfi->vendor, cfi->portwidth and cfi->chipwidth are correct
+ *
*/
-static int flash_status_check (flash_info_t * info, flash_sect_t sector,
- ulong tout, char *prompt)
+static void cmdset_intel_read_jedec_ids(flash_info_t *info)
{
- ulong start;
-
-#if CFG_HZ != 1000
- tout *= CFG_HZ/1000;
-#endif
-
- /* Wait for command completion */
- start = get_timer (0);
- while (flash_is_busy (info, sector)) {
- if (get_timer (start) > tout) {
- printf ("Flash %s timeout at address %lx data %lx\n",
- prompt, info->start[sector],
- flash_read_long (info, sector, 0));
- flash_write_cmd (info, sector, 0, info->cmd_reset);
- return ERR_TIMOUT;
- }
- udelay (1); /* also triggers watchdog */
- }
- return ERR_OK;
+ flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
+ flash_write_cmd(info, 0, 0, FLASH_CMD_READ_ID);
+ udelay(1000); /* some flash are slow to respond */
+ info->manufacturer_id = flash_read_uchar (info,
+ FLASH_OFFSET_MANUFACTURER_ID);
+ info->device_id = flash_read_uchar (info,
+ FLASH_OFFSET_DEVICE_ID);
+ flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
}
-/*-----------------------------------------------------------------------
- * Wait for XSR.7 to be set, if it times out print an error, otherwise do a full status check.
- * This routine sets the flash to read-array mode.
- */
-static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
- ulong tout, char *prompt)
+static int cmdset_intel_init(flash_info_t *info, struct cfi_qry *qry)
{
- int retcode;
+ info->cmd_reset = FLASH_CMD_RESET;
- retcode = flash_status_check (info, sector, tout, prompt);
- switch (info->vendor) {
- case CFI_CMDSET_INTEL_EXTENDED:
- case CFI_CMDSET_INTEL_STANDARD:
- if ((retcode == ERR_OK)
- && !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) {
- retcode = ERR_INVAL;
- printf ("Flash %s error at address %lx\n", prompt,
- info->start[sector]);
- if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)) {
- puts ("Command Sequence Error.\n");
- } else if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS)) {
- puts ("Block Erase Error.\n");
- retcode = ERR_NOT_ERASED;
- } else if (flash_isset (info, sector, 0, FLASH_STATUS_PSLBS)) {
- puts ("Locking Error\n");
- }
- if (flash_isset (info, sector, 0, FLASH_STATUS_DPS)) {
- puts ("Block locked.\n");
- retcode = ERR_PROTECTED;
- }
- if (flash_isset (info, sector, 0, FLASH_STATUS_VPENS))
- puts ("Vpp Low Error.\n");
- }
- flash_write_cmd (info, sector, 0, info->cmd_reset);
- break;
- default:
- break;
+ cmdset_intel_read_jedec_ids(info);
+ flash_write_cmd(info, 0, info->cfi_offset, FLASH_CMD_CFI);
+
+#ifdef CFG_FLASH_PROTECTION
+ /* read legacy lock/unlock bit from intel flash */
+ if (info->ext_addr) {
+ info->legacy_unlock = flash_read_uchar (info,
+ info->ext_addr + 5) & 0x08;
}
- return retcode;
+#endif
+
+ return 0;
}
-/*-----------------------------------------------------------------------
- */
-static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c)
+static void cmdset_amd_read_jedec_ids(flash_info_t *info)
{
-#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
- unsigned short w;
- unsigned int l;
- unsigned long long ll;
-#endif
-
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- cword->c = c;
- break;
- case FLASH_CFI_16BIT:
-#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
- w = c;
- w <<= 8;
- cword->w = (cword->w >> 8) | w;
-#else
- cword->w = (cword->w << 8) | c;
-#endif
- break;
- case FLASH_CFI_32BIT:
-#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
- l = c;
- l <<= 24;
- cword->l = (cword->l >> 8) | l;
-#else
- cword->l = (cword->l << 8) | c;
-#endif
- break;
- case FLASH_CFI_64BIT:
-#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
- ll = c;
- ll <<= 56;
- cword->ll = (cword->ll >> 8) | ll;
-#else
- cword->ll = (cword->ll << 8) | c;
-#endif
- break;
+ flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
+ flash_unlock_seq(info, 0);
+ flash_write_cmd(info, 0, info->addr_unlock1, FLASH_CMD_READ_ID);
+ udelay(1000); /* some flash are slow to respond */
+ info->manufacturer_id = flash_read_uchar (info,
+ FLASH_OFFSET_MANUFACTURER_ID);
+ info->device_id = flash_read_uchar (info,
+ FLASH_OFFSET_DEVICE_ID);
+ if (info->device_id == 0x7E) {
+ /* AMD 3-byte (expanded) device ids */
+ info->device_id2 = flash_read_uchar (info,
+ FLASH_OFFSET_DEVICE_ID2);
+ info->device_id2 <<= 8;
+ info->device_id2 |= flash_read_uchar (info,
+ FLASH_OFFSET_DEVICE_ID3);
}
+ flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
}
-
-/*-----------------------------------------------------------------------
- * make a proper sized command based on the port and chip widths
- */
-static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf)
+static int cmdset_amd_init(flash_info_t *info, struct cfi_qry *qry)
{
- int i;
- uchar *cp = (uchar *) cmdbuf;
+ info->cmd_reset = AMD_CMD_RESET;
-#if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA)
- for (i = info->portwidth; i > 0; i--)
-#else
- for (i = 1; i <= info->portwidth; i++)
-#endif
- *cp++ = (i & (info->chipwidth - 1)) ? '\0' : cmd;
+ cmdset_amd_read_jedec_ids(info);
+ flash_write_cmd(info, 0, info->cfi_offset, FLASH_CMD_CFI);
+
+ return 0;
}
-/*
- * Write a proper sized command to the correct address
- */
-static void flash_write_cmd (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
+#ifdef CONFIG_FLASH_CFI_LEGACY
+static void flash_read_jedec_ids (flash_info_t * info)
{
+ info->manufacturer_id = 0;
+ info->device_id = 0;
+ info->device_id2 = 0;
- volatile cfiptr_t addr;
- cfiword_t cword;
-
- addr.cp = flash_make_addr (info, sect, offset);
- flash_make_cmd (info, cmd, &cword);
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", addr.cp, cmd,
- cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
- *addr.cp = cword.c;
- break;
- case FLASH_CFI_16BIT:
- debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr.wp,
- cmd, cword.w,
- info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
- *addr.wp = cword.w;
+ switch (info->vendor) {
+ case CFI_CMDSET_INTEL_STANDARD:
+ case CFI_CMDSET_INTEL_EXTENDED:
+ flash_read_jedec_ids_intel(info);
break;
- case FLASH_CFI_32BIT:
- debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr.lp,
- cmd, cword.l,
- info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
- *addr.lp = cword.l;
+ case CFI_CMDSET_AMD_STANDARD:
+ case CFI_CMDSET_AMD_EXTENDED:
+ flash_read_jedec_ids_amd(info);
break;
- case FLASH_CFI_64BIT:
-#ifdef DEBUG
- {
- char str[20];
-
- print_longlong (str, cword.ll);
-
- debug ("fwrite addr %p cmd %x %s 64 bit x %d bit\n",
- addr.llp, cmd, str,
- info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
- }
-#endif
- *addr.llp = cword.ll;
+ default:
break;
}
-
- /* Ensure all the instructions are fully finished */
- sync();
-}
-
-static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect)
-{
- flash_write_cmd (info, sect, AMD_ADDR_START, AMD_CMD_UNLOCK_START);
- flash_write_cmd (info, sect, AMD_ADDR_ACK, AMD_CMD_UNLOCK_ACK);
}
/*-----------------------------------------------------------------------
+ * Call board code to request info about non-CFI flash.
+ * board_flash_get_legacy needs to fill in at least:
+ * info->portwidth, info->chipwidth and info->interface for Jedec probing.
*/
-static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
+static int flash_detect_legacy(ulong base, int banknum)
{
- cfiptr_t cptr;
- cfiword_t cword;
- int retval;
-
- cptr.cp = flash_make_addr (info, sect, offset);
- flash_make_cmd (info, cmd, &cword);
+ flash_info_t *info = &flash_info[banknum];
- debug ("is= cmd %x(%c) addr %p ", cmd, cmd, cptr.cp);
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- debug ("is= %x %x\n", cptr.cp[0], cword.c);
- retval = (cptr.cp[0] == cword.c);
- break;
- case FLASH_CFI_16BIT:
- debug ("is= %4.4x %4.4x\n", cptr.wp[0], cword.w);
- retval = (cptr.wp[0] == cword.w);
- break;
- case FLASH_CFI_32BIT:
- debug ("is= %8.8lx %8.8lx\n", cptr.lp[0], cword.l);
- retval = (cptr.lp[0] == cword.l);
- break;
- case FLASH_CFI_64BIT:
-#ifdef DEBUG
- {
- char str1[20];
- char str2[20];
+ if (board_flash_get_legacy(base, banknum, info)) {
+ /* board code may have filled info completely. If not, we
+ use JEDEC ID probing. */
+ if (!info->vendor) {
+ int modes[] = {
+ CFI_CMDSET_AMD_STANDARD,
+ CFI_CMDSET_INTEL_STANDARD
+ };
+ int i;
+
+ for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) {
+ info->vendor = modes[i];
+ info->start[0] = base;
+ if (info->portwidth == FLASH_CFI_8BIT
+ && info->interface == FLASH_CFI_X8X16) {
+ info->addr_unlock1 = 0x2AAA;
+ info->addr_unlock2 = 0x5555;
+ } else {
+ info->addr_unlock1 = 0x5555;
+ info->addr_unlock2 = 0x2AAA;
+ }
+ flash_read_jedec_ids(info);
+ debug("JEDEC PROBE: ID %x %x %x\n",
+ info->manufacturer_id,
+ info->device_id,
+ info->device_id2);
+ if (jedec_flash_match(info, base))
+ break;
+ }
+ }
- print_longlong (str1, cptr.llp[0]);
- print_longlong (str2, cword.ll);
- debug ("is= %s %s\n", str1, str2);
+ switch(info->vendor) {
+ case CFI_CMDSET_INTEL_STANDARD:
+ case CFI_CMDSET_INTEL_EXTENDED:
+ info->cmd_reset = FLASH_CMD_RESET;
+ break;
+ case CFI_CMDSET_AMD_STANDARD:
+ case CFI_CMDSET_AMD_EXTENDED:
+ case CFI_CMDSET_AMD_LEGACY:
+ info->cmd_reset = AMD_CMD_RESET;
+ break;
}
-#endif
- retval = (cptr.llp[0] == cword.ll);
- break;
- default:
- retval = 0;
- break;
+ info->flash_id = FLASH_MAN_CFI;
+ return 1;
}
- return retval;
+ return 0; /* use CFI */
}
-
-/*-----------------------------------------------------------------------
- */
-static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
+#else
+static inline int flash_detect_legacy(ulong base, int banknum)
{
- cfiptr_t cptr;
- cfiword_t cword;
- int retval;
-
- cptr.cp = flash_make_addr (info, sect, offset);
- flash_make_cmd (info, cmd, &cword);
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- retval = ((cptr.cp[0] & cword.c) == cword.c);
- break;
- case FLASH_CFI_16BIT:
- retval = ((cptr.wp[0] & cword.w) == cword.w);
- break;
- case FLASH_CFI_32BIT:
- retval = ((cptr.lp[0] & cword.l) == cword.l);
- break;
- case FLASH_CFI_64BIT:
- retval = ((cptr.llp[0] & cword.ll) == cword.ll);
- break;
- default:
- retval = 0;
- break;
- }
- return retval;
+ return 0; /* use CFI */
}
+#endif
/*-----------------------------------------------------------------------
+ * detect if flash is compatible with the Common Flash Interface (CFI)
+ * http://www.jedec.org/download/search/jesd68.pdf
*/
-static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
+static void flash_read_cfi (flash_info_t *info, void *buf,
+ unsigned int start, size_t len)
{
- cfiptr_t cptr;
- cfiword_t cword;
- int retval;
+ u8 *p = buf;
+ unsigned int i;
- cptr.cp = flash_make_addr (info, sect, offset);
- flash_make_cmd (info, cmd, &cword);
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- retval = ((cptr.cp[0] & cword.c) != (cptr.cp[0] & cword.c));
- break;
- case FLASH_CFI_16BIT:
- retval = ((cptr.wp[0] & cword.w) != (cptr.wp[0] & cword.w));
- break;
- case FLASH_CFI_32BIT:
- retval = ((cptr.lp[0] & cword.l) != (cptr.lp[0] & cword.l));
- break;
- case FLASH_CFI_64BIT:
- retval = ((cptr.llp[0] & cword.ll) !=
- (cptr.llp[0] & cword.ll));
- break;
- default:
- retval = 0;
- break;
- }
- return retval;
+ for (i = 0; i < len; i++)
+ p[i] = flash_read_uchar(info, start + i);
}
-/*-----------------------------------------------------------------------
- * read jedec ids from device and set corresponding fields in info struct
- *
- * Note: assume cfi->vendor, cfi->portwidth and cfi->chipwidth are correct
- *
-*/
-static void flash_read_jedec_ids (flash_info_t * info)
+static int __flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry)
{
- info->manufacturer_id = 0;
- info->device_id = 0;
- info->device_id2 = 0;
+ int cfi_offset;
- switch (info->vendor) {
- case CFI_CMDSET_INTEL_STANDARD:
- case CFI_CMDSET_INTEL_EXTENDED:
- flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
- flash_write_cmd(info, 0, 0, FLASH_CMD_READ_ID);
- udelay(1000); /* some flash are slow to respond */
- info->manufacturer_id = flash_read_uchar (info,
- FLASH_OFFSET_MANUFACTURER_ID);
- info->device_id = flash_read_uchar (info,
- FLASH_OFFSET_DEVICE_ID);
- flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
- break;
- case CFI_CMDSET_AMD_STANDARD:
- case CFI_CMDSET_AMD_EXTENDED:
- flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
- flash_unlock_seq(info, 0);
- flash_write_cmd(info, 0, AMD_ADDR_START, FLASH_CMD_READ_ID);
- udelay(1000); /* some flash are slow to respond */
- info->manufacturer_id = flash_read_uchar (info,
- FLASH_OFFSET_MANUFACTURER_ID);
- info->device_id = flash_read_uchar (info,
- FLASH_OFFSET_DEVICE_ID);
- if (info->device_id == 0x7E) {
- /* AMD 3-byte (expanded) device ids */
- info->device_id2 = flash_read_uchar (info,
- FLASH_OFFSET_DEVICE_ID2);
- info->device_id2 <<= 8;
- info->device_id2 |= flash_read_uchar (info,
- FLASH_OFFSET_DEVICE_ID3);
+ flash_write_cmd (info, 0, 0, info->cmd_reset);
+ for (cfi_offset=0;
+ cfi_offset < sizeof(flash_offset_cfi) / sizeof(uint);
+ cfi_offset++) {
+ flash_write_cmd (info, 0, flash_offset_cfi[cfi_offset],
+ FLASH_CMD_CFI);
+ if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
+ && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R')
+ && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) {
+ flash_read_cfi(info, qry, FLASH_OFFSET_CFI_RESP,
+ sizeof(struct cfi_qry));
+ info->interface = le16_to_cpu(qry->interface_desc);
+
+ info->cfi_offset = flash_offset_cfi[cfi_offset];
+ debug ("device interface is %d\n",
+ info->interface);
+ debug ("found port %d chip %d ",
+ info->portwidth, info->chipwidth);
+ debug ("port %d bits chip %d bits\n",
+ info->portwidth << CFI_FLASH_SHIFT_WIDTH,
+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+
+ /* calculate command offsets as in the Linux driver */
+ info->addr_unlock1 = 0x555;
+ info->addr_unlock2 = 0x2aa;
+
+ /*
+ * modify the unlock address if we are
+ * in compatibility mode
+ */
+ if ( /* x8/x16 in x8 mode */
+ ((info->chipwidth == FLASH_CFI_BY8) &&
+ (info->interface == FLASH_CFI_X8X16)) ||
+ /* x16/x32 in x16 mode */
+ ((info->chipwidth == FLASH_CFI_BY16) &&
+ (info->interface == FLASH_CFI_X16X32)))
+ {
+ info->addr_unlock1 = 0xaaa;
+ info->addr_unlock2 = 0x555;
+ }
+
+ info->name = "CFI conformant";
+ return 1;
}
- flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
- break;
- default:
- break;
}
+
+ return 0;
}
-/*-----------------------------------------------------------------------
- * detect if flash is compatible with the Common Flash Interface (CFI)
- * http://www.jedec.org/download/search/jesd68.pdf
- *
-*/
-static int flash_detect_cfi (flash_info_t * info)
+static int flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry)
{
- int cfi_offset;
debug ("flash detect cfi\n");
for (info->portwidth = CFG_FLASH_CFI_WIDTH;
info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) {
for (info->chipwidth = FLASH_CFI_BY8;
info->chipwidth <= info->portwidth;
- info->chipwidth <<= 1) {
- flash_write_cmd (info, 0, 0, info->cmd_reset);
- for (cfi_offset=0; cfi_offset < sizeof(flash_offset_cfi)/sizeof(uint); cfi_offset++) {
- flash_write_cmd (info, 0, flash_offset_cfi[cfi_offset], FLASH_CMD_CFI);
- if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
- && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R')
- && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) {
- info->interface = flash_read_ushort (info, 0, FLASH_OFFSET_INTERFACE);
- info->cfi_offset=flash_offset_cfi[cfi_offset];
- debug ("device interface is %d\n",
- info->interface);
- debug ("found port %d chip %d ",
- info->portwidth, info->chipwidth);
- debug ("port %d bits chip %d bits\n",
- info->portwidth << CFI_FLASH_SHIFT_WIDTH,
- info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
- return 1;
- }
- }
- }
+ info->chipwidth <<= 1)
+ if (__flash_detect_cfi(info, qry))
+ return 1;
}
debug ("not found\n");
return 0;
}
/*
+ * Manufacturer-specific quirks. Add workarounds for geometry
+ * reversal, etc. here.
+ */
+static void flash_fixup_amd(flash_info_t *info, struct cfi_qry *qry)
+{
+ /* check if flash geometry needs reversal */
+ if (qry->num_erase_regions > 1) {
+ /* reverse geometry if top boot part */
+ if (info->cfi_version < 0x3131) {
+ /* CFI < 1.1, try to guess from device id */
+ if ((info->device_id & 0x80) != 0)
+ cfi_reverse_geometry(qry);
+ } else if (flash_read_uchar(info, info->ext_addr + 0xf) == 3) {
+ /* CFI >= 1.1, deduct from top/bottom flag */
+ /* note: ext_addr is valid since cfi_version > 0 */
+ cfi_reverse_geometry(qry);
+ }
+ }
+}
+
+static void flash_fixup_atmel(flash_info_t *info, struct cfi_qry *qry)
+{
+ int reverse_geometry = 0;
+
+ /* Check the "top boot" bit in the PRI */
+ if (info->ext_addr && !(flash_read_uchar(info, info->ext_addr + 6) & 1))
+ reverse_geometry = 1;
+
+ /* AT49BV6416(T) list the erase regions in the wrong order.
+ * However, the device ID is identical with the non-broken
+ * AT49BV642D since u-boot only reads the low byte (they
+ * differ in the high byte.) So leave out this fixup for now.
+ */
+#if 0
+ if (info->device_id == 0xd6 || info->device_id == 0xd2)
+ reverse_geometry = !reverse_geometry;
+#endif
+
+ if (reverse_geometry)
+ cfi_reverse_geometry(qry);
+}
+
+/*
* The following code cannot be run from FLASH!
*
*/
@@ -1180,7 +1661,7 @@ ulong flash_get_size (ulong base, int banknum)
uchar num_erase_regions;
int erase_region_size;
int erase_region_count;
- int geometry_reversed = 0;
+ struct cfi_qry qry;
info->ext_addr = 0;
info->cfi_version = 0;
@@ -1190,56 +1671,50 @@ ulong flash_get_size (ulong base, int banknum)
info->start[0] = base;
- if (flash_detect_cfi (info)) {
- info->vendor = flash_read_ushort (info, 0,
- FLASH_OFFSET_PRIMARY_VENDOR);
- flash_read_jedec_ids (info);
- flash_write_cmd (info, 0, info->cfi_offset, FLASH_CMD_CFI);
- num_erase_regions = flash_read_uchar (info,
- FLASH_OFFSET_NUM_ERASE_REGIONS);
- info->ext_addr = flash_read_ushort (info, 0,
- FLASH_OFFSET_EXT_QUERY_T_P_ADDR);
+ if (flash_detect_cfi (info, &qry)) {
+ info->vendor = le16_to_cpu(qry.p_id);
+ info->ext_addr = le16_to_cpu(qry.p_adr);
+ num_erase_regions = qry.num_erase_regions;
+
if (info->ext_addr) {
info->cfi_version = (ushort) flash_read_uchar (info,
info->ext_addr + 3) << 8;
info->cfi_version |= (ushort) flash_read_uchar (info,
info->ext_addr + 4);
}
+
#ifdef DEBUG
- flash_printqry (info, 0);
+ flash_printqry (&qry);
#endif
+
switch (info->vendor) {
case CFI_CMDSET_INTEL_STANDARD:
case CFI_CMDSET_INTEL_EXTENDED:
- default:
- info->cmd_reset = FLASH_CMD_RESET;
-#ifdef CFG_FLASH_PROTECTION
- /* read legacy lock/unlock bit from intel flash */
- if (info->ext_addr) {
- info->legacy_unlock = flash_read_uchar (info,
- info->ext_addr + 5) & 0x08;
- }
-#endif
+ cmdset_intel_init(info, &qry);
break;
case CFI_CMDSET_AMD_STANDARD:
case CFI_CMDSET_AMD_EXTENDED:
- info->cmd_reset = AMD_CMD_RESET;
- /* check if flash geometry needs reversal */
- if (num_erase_regions <= 1)
- break;
- /* reverse geometry if top boot part */
- if (info->cfi_version < 0x3131) {
- /* CFI < 1.1, try to guess from device id */
- if ((info->device_id & 0x80) != 0) {
- geometry_reversed = 1;
- }
- break;
- }
- /* CFI >= 1.1, deduct from top/bottom flag */
- /* note: ext_addr is valid since cfi_version > 0 */
- if (flash_read_uchar(info, info->ext_addr + 0xf) == 3) {
- geometry_reversed = 1;
- }
+ cmdset_amd_init(info, &qry);
+ break;
+ default:
+ printf("CFI: Unknown command set 0x%x\n",
+ info->vendor);
+ /*
+ * Unfortunately, this means we don't know how
+ * to get the chip back to Read mode. Might
+ * as well try an Intel-style reset...
+ */
+ flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
+ return 0;
+ }
+
+ /* Do manufacturer-specific fixups */
+ switch (info->manufacturer_id) {
+ case 0x0001:
+ flash_fixup_amd(info, &qry);
+ break;
+ case 0x001f:
+ flash_fixup_atmel(info, &qry);
break;
}
@@ -1267,26 +1742,27 @@ ulong flash_get_size (ulong base, int banknum)
num_erase_regions, NUM_ERASE_REGIONS);
break;
}
- if (geometry_reversed)
- tmp = flash_read_long (info, 0,
- FLASH_OFFSET_ERASE_REGIONS +
- (num_erase_regions - 1 - i) * 4);
- else
- tmp = flash_read_long (info, 0,
- FLASH_OFFSET_ERASE_REGIONS +
- i * 4);
+
+ tmp = le32_to_cpu(qry.erase_region_info[i]);
+ debug("erase region %u: 0x%08lx\n", i, tmp);
+
+ erase_region_count = (tmp & 0xffff) + 1;
+ tmp >>= 16;
erase_region_size =
(tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;
- tmp >>= 16;
- erase_region_count = (tmp & 0xffff) + 1;
debug ("erase_region_count = %d erase_region_size = %d\n",
erase_region_count, erase_region_size);
for (j = 0; j < erase_region_count; j++) {
+ if (sect_cnt >= CFG_MAX_FLASH_SECT) {
+ printf("ERROR: too many flash sectors\n");
+ break;
+ }
info->start[sect_cnt] = sector;
sector += (erase_region_size * size_ratio);
/*
- * Only read protection status from supported devices (intel...)
+ * Only read protection status from
+ * supported devices (intel...)
*/
switch (info->vendor) {
case CFI_CMDSET_INTEL_EXTENDED:
@@ -1297,7 +1773,8 @@ ulong flash_get_size (ulong base, int banknum)
FLASH_STATUS_PROTECT);
break;
default:
- info->protect[sect_cnt] = 0; /* default: not protected */
+ /* default: not protected */
+ info->protect[sect_cnt] = 0;
}
sect_cnt++;
@@ -1305,20 +1782,27 @@ ulong flash_get_size (ulong base, int banknum)
}
info->sector_count = sect_cnt;
+ info->size = 1 << qry.dev_size;
/* multiply the size by the number of chips */
- info->size = (1 << flash_read_uchar (info, FLASH_OFFSET_SIZE)) * size_ratio;
- info->buffer_size = (1 << flash_read_ushort (info, 0, FLASH_OFFSET_BUFFER_SIZE));
- tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_ETOUT);
- info->erase_blk_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_EMAX_TOUT)));
- tmp = (1 << flash_read_uchar (info, FLASH_OFFSET_WBTOUT)) *
- (1 << flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT));
- info->buffer_write_tout = tmp / 1000 + (tmp % 1000 ? 1 : 0); /* round up when converting to ms */
- tmp = (1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT)) *
- (1 << flash_read_uchar (info, FLASH_OFFSET_WMAX_TOUT));
- info->write_tout = tmp / 1000 + (tmp % 1000 ? 1 : 0); /* round up when converting to ms */
+ info->size *= size_ratio;
+ info->buffer_size = 1 << le16_to_cpu(qry.max_buf_write_size);
+ tmp = 1 << qry.block_erase_timeout_typ;
+ info->erase_blk_tout = tmp *
+ (1 << qry.block_erase_timeout_max);
+ tmp = (1 << qry.buf_write_timeout_typ) *
+ (1 << qry.buf_write_timeout_max);
+
+ /* round up when converting to ms */
+ info->buffer_write_tout = (tmp + 999) / 1000;
+ tmp = (1 << qry.word_write_timeout_typ) *
+ (1 << qry.word_write_timeout_max);
+ /* round up when converting to ms */
+ info->write_tout = (tmp + 999) / 1000;
info->flash_id = FLASH_MAN_CFI;
- if ((info->interface == FLASH_CFI_X8X16) && (info->chipwidth == FLASH_CFI_BY8)) {
- info->portwidth >>= 1; /* XXX - Need to test on x8/x16 in parallel. */
+ if ((info->interface == FLASH_CFI_X8X16) &&
+ (info->chipwidth == FLASH_CFI_BY8)) {
+ /* XXX - Need to test on x8/x16 in parallel. */
+ info->portwidth >>= 1;
}
}
@@ -1326,203 +1810,106 @@ ulong flash_get_size (ulong base, int banknum)
return (info->size);
}
-/* loop through the sectors from the highest address
- * when the passed address is greater or equal to the sector address
- * we have a match
- */
-static flash_sect_t find_sector (flash_info_t * info, ulong addr)
-{
- flash_sect_t sector;
-
- for (sector = info->sector_count - 1; sector >= 0; sector--) {
- if (addr >= info->start[sector])
- break;
- }
- return sector;
-}
-
/*-----------------------------------------------------------------------
*/
-static int flash_write_cfiword (flash_info_t * info, ulong dest,
- cfiword_t cword)
+unsigned long flash_init (void)
{
- cfiptr_t ctladdr;
- cfiptr_t cptr;
- int flag;
-
- ctladdr.cp = flash_make_addr (info, 0, 0);
- cptr.cp = (uchar *) dest;
-
- /* Check if Flash is (sufficiently) erased */
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- flag = ((cptr.cp[0] & cword.c) == cword.c);
- break;
- case FLASH_CFI_16BIT:
- flag = ((cptr.wp[0] & cword.w) == cword.w);
- break;
- case FLASH_CFI_32BIT:
- flag = ((cptr.lp[0] & cword.l) == cword.l);
- break;
- case FLASH_CFI_64BIT:
- flag = ((cptr.llp[0] & cword.ll) == cword.ll);
- break;
- default:
- return 2;
- }
- if (!flag)
- return 2;
-
- /* Disable interrupts which might cause a timeout here */
- flag = disable_interrupts ();
+ unsigned long size = 0;
+ int i;
- switch (info->vendor) {
- case CFI_CMDSET_INTEL_EXTENDED:
- case CFI_CMDSET_INTEL_STANDARD:
- flash_write_cmd (info, 0, 0, FLASH_CMD_CLEAR_STATUS);
- flash_write_cmd (info, 0, 0, FLASH_CMD_WRITE);
- break;
- case CFI_CMDSET_AMD_EXTENDED:
- case CFI_CMDSET_AMD_STANDARD:
- flash_unlock_seq (info, 0);
- flash_write_cmd (info, 0, AMD_ADDR_START, AMD_CMD_WRITE);
- break;
- }
+#ifdef CFG_FLASH_PROTECTION
+ char *s = getenv("unlock");
+#endif
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- cptr.cp[0] = cword.c;
- break;
- case FLASH_CFI_16BIT:
- cptr.wp[0] = cword.w;
- break;
- case FLASH_CFI_32BIT:
- cptr.lp[0] = cword.l;
- break;
- case FLASH_CFI_64BIT:
- cptr.llp[0] = cword.ll;
- break;
- }
+ /* Init: no FLASHes known */
+ for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
+ flash_info[i].flash_id = FLASH_UNKNOWN;
- /* re-enable interrupts if necessary */
- if (flag)
- enable_interrupts ();
+ if (!flash_detect_legacy (bank_base[i], i))
+ flash_get_size (bank_base[i], i);
+ size += flash_info[i].size;
+ if (flash_info[i].flash_id == FLASH_UNKNOWN) {
+#ifndef CFG_FLASH_QUIET_TEST
+ printf ("## Unknown FLASH on Bank %d "
+ "- Size = 0x%08lx = %ld MB\n",
+ i+1, flash_info[i].size,
+ flash_info[i].size << 20);
+#endif /* CFG_FLASH_QUIET_TEST */
+ }
+#ifdef CFG_FLASH_PROTECTION
+ else if ((s != NULL) && (strcmp(s, "yes") == 0)) {
+ /*
+ * Only the U-Boot image and it's environment
+ * is protected, all other sectors are
+ * unprotected (unlocked) if flash hardware
+ * protection is used (CFG_FLASH_PROTECTION)
+ * and the environment variable "unlock" is
+ * set to "yes".
+ */
+ if (flash_info[i].legacy_unlock) {
+ int k;
- return flash_full_status_check (info, find_sector (info, dest),
- info->write_tout, "write");
-}
+ /*
+ * Disable legacy_unlock temporarily,
+ * since flash_real_protect would
+ * relock all other sectors again
+ * otherwise.
+ */
+ flash_info[i].legacy_unlock = 0;
-#ifdef CFG_FLASH_USE_BUFFER_WRITE
+ /*
+ * Legacy unlocking (e.g. Intel J3) ->
+ * unlock only one sector. This will
+ * unlock all sectors.
+ */
+ flash_real_protect (&flash_info[i], 0, 0);
-static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
- int len)
-{
- flash_sect_t sector;
- int cnt;
- int retcode;
- volatile cfiptr_t src;
- volatile cfiptr_t dst;
+ flash_info[i].legacy_unlock = 1;
- switch (info->vendor) {
- case CFI_CMDSET_INTEL_STANDARD:
- case CFI_CMDSET_INTEL_EXTENDED:
- src.cp = cp;
- dst.cp = (uchar *) dest;
- sector = find_sector (info, dest);
- flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
- flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
- if ((retcode = flash_status_check (info, sector, info->buffer_write_tout,
- "write to buffer")) == ERR_OK) {
- /* reduce the number of loops by the width of the port */
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- cnt = len;
- break;
- case FLASH_CFI_16BIT:
- cnt = len >> 1;
- break;
- case FLASH_CFI_32BIT:
- cnt = len >> 2;
- break;
- case FLASH_CFI_64BIT:
- cnt = len >> 3;
- break;
- default:
- return ERR_INVAL;
- break;
- }
- flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
- while (cnt-- > 0) {
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- *dst.cp++ = *src.cp++;
- break;
- case FLASH_CFI_16BIT:
- *dst.wp++ = *src.wp++;
- break;
- case FLASH_CFI_32BIT:
- *dst.lp++ = *src.lp++;
- break;
- case FLASH_CFI_64BIT:
- *dst.llp++ = *src.llp++;
- break;
- default:
- return ERR_INVAL;
- break;
- }
+ /*
+ * Manually mark other sectors as
+ * unlocked (unprotected)
+ */
+ for (k = 1; k < flash_info[i].sector_count; k++)
+ flash_info[i].protect[k] = 0;
+ } else {
+ /*
+ * No legancy unlocking -> unlock all sectors
+ */
+ flash_protect (FLAG_PROTECT_CLEAR,
+ flash_info[i].start[0],
+ flash_info[i].start[0]
+ + flash_info[i].size - 1,
+ &flash_info[i]);
}
- flash_write_cmd (info, sector, 0,
- FLASH_CMD_WRITE_BUFFER_CONFIRM);
- retcode = flash_full_status_check (info, sector,
- info->buffer_write_tout,
- "buffer write");
}
- return retcode;
-
- case CFI_CMDSET_AMD_STANDARD:
- case CFI_CMDSET_AMD_EXTENDED:
- src.cp = cp;
- dst.cp = (uchar *) dest;
- sector = find_sector (info, dest);
-
- flash_unlock_seq(info,0);
- flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_TO_BUFFER);
+#endif /* CFG_FLASH_PROTECTION */
+ }
- switch (info->portwidth) {
- case FLASH_CFI_8BIT:
- cnt = len;
- flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
- while (cnt-- > 0) *dst.cp++ = *src.cp++;
- break;
- case FLASH_CFI_16BIT:
- cnt = len >> 1;
- flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
- while (cnt-- > 0) *dst.wp++ = *src.wp++;
- break;
- case FLASH_CFI_32BIT:
- cnt = len >> 2;
- flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
- while (cnt-- > 0) *dst.lp++ = *src.lp++;
- break;
- case FLASH_CFI_64BIT:
- cnt = len >> 3;
- flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
- while (cnt-- > 0) *dst.llp++ = *src.llp++;
- break;
- default:
- return ERR_INVAL;
- }
+ /* Monitor protection ON by default */
+#if (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
+ flash_protect (FLAG_PROTECT_SET,
+ CFG_MONITOR_BASE,
+ CFG_MONITOR_BASE + monitor_flash_len - 1,
+ flash_get_info(CFG_MONITOR_BASE));
+#endif
- flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM);
- retcode = flash_full_status_check (info, sector, info->buffer_write_tout,
- "buffer write");
- return retcode;
+ /* Environment protection ON by default */
+#ifdef CFG_ENV_IS_IN_FLASH
+ flash_protect (FLAG_PROTECT_SET,
+ CFG_ENV_ADDR,
+ CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1,
+ flash_get_info(CFG_ENV_ADDR));
+#endif
- default:
- debug ("Unknown Command Set\n");
- return ERR_INVAL;
- }
+ /* Redundant environment protection ON by default */
+#ifdef CFG_ENV_ADDR_REDUND
+ flash_protect (FLAG_PROTECT_SET,
+ CFG_ENV_ADDR_REDUND,
+ CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1,
+ flash_get_info(CFG_ENV_ADDR_REDUND));
+#endif
+ return (size);
}
-#endif /* CFG_FLASH_USE_BUFFER_WRITE */
#endif /* CFG_FLASH_CFI */
diff --git a/drivers/dataflash.c b/drivers/mtd/dataflash.c
index 91903c8..91903c8 100644
--- a/drivers/dataflash.c
+++ b/drivers/mtd/dataflash.c
diff --git a/drivers/mtd/jedec_flash.c b/drivers/mtd/jedec_flash.c
new file mode 100644
index 0000000..94e87cb
--- /dev/null
+++ b/drivers/mtd/jedec_flash.c
@@ -0,0 +1,311 @@
+/*
+ * (C) Copyright 2007
+ * Michael Schwingen, <michael@schwingen.org>
+ *
+ * based in great part on jedec_probe.c from linux kernel:
+ * (C) 2000 Red Hat. GPL'd.
+ * Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ *
+ */
+
+/* The DEBUG define must be before common to enable debugging */
+/*#define DEBUG*/
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <environment.h>
+
+#define P_ID_AMD_STD CFI_CMDSET_AMD_LEGACY
+
+/* Manufacturers */
+#define MANUFACTURER_AMD 0x0001
+#define MANUFACTURER_SST 0x00BF
+
+/* AMD */
+#define AM29DL800BB 0x22C8
+#define AM29DL800BT 0x224A
+
+#define AM29F800BB 0x2258
+#define AM29F800BT 0x22D6
+#define AM29LV400BB 0x22BA
+#define AM29LV400BT 0x22B9
+#define AM29LV800BB 0x225B
+#define AM29LV800BT 0x22DA
+#define AM29LV160DT 0x22C4
+#define AM29LV160DB 0x2249
+#define AM29F017D 0x003D
+#define AM29F016D 0x00AD
+#define AM29F080 0x00D5
+#define AM29F040 0x00A4
+#define AM29LV040B 0x004F
+#define AM29F032B 0x0041
+#define AM29F002T 0x00B0
+
+/* SST */
+#define SST39LF800 0x2781
+#define SST39LF160 0x2782
+#define SST39VF1601 0x234b
+#define SST39LF512 0x00D4
+#define SST39LF010 0x00D5
+#define SST39LF020 0x00D6
+#define SST39LF040 0x00D7
+#define SST39SF010A 0x00B5
+#define SST39SF020A 0x00B6
+
+
+/*
+ * Unlock address sets for AMD command sets.
+ * Intel command sets use the MTD_UADDR_UNNECESSARY.
+ * Each identifier, except MTD_UADDR_UNNECESSARY, and
+ * MTD_UADDR_NO_SUPPORT must be defined below in unlock_addrs[].
+ * MTD_UADDR_NOT_SUPPORTED must be 0 so that structure
+ * initialization need not require initializing all of the
+ * unlock addresses for all bit widths.
+ */
+enum uaddr {
+ MTD_UADDR_NOT_SUPPORTED = 0, /* data width not supported */
+ MTD_UADDR_0x0555_0x02AA,
+ MTD_UADDR_0x0555_0x0AAA,
+ MTD_UADDR_0x5555_0x2AAA,
+ MTD_UADDR_0x0AAA_0x0555,
+ MTD_UADDR_DONT_CARE, /* Requires an arbitrary address */
+ MTD_UADDR_UNNECESSARY, /* Does not require any address */
+};
+
+
+struct unlock_addr {
+ u32 addr1;
+ u32 addr2;
+};
+
+
+/*
+ * I don't like the fact that the first entry in unlock_addrs[]
+ * exists, but is for MTD_UADDR_NOT_SUPPORTED - and, therefore,
+ * should not be used. The problem is that structures with
+ * initializers have extra fields initialized to 0. It is _very_
+ * desireable to have the unlock address entries for unsupported
+ * data widths automatically initialized - that means that
+ * MTD_UADDR_NOT_SUPPORTED must be 0 and the first entry here
+ * must go unused.
+ */
+static const struct unlock_addr unlock_addrs[] = {
+ [MTD_UADDR_NOT_SUPPORTED] = {
+ .addr1 = 0xffff,
+ .addr2 = 0xffff
+ },
+
+ [MTD_UADDR_0x0555_0x02AA] = {
+ .addr1 = 0x0555,
+ .addr2 = 0x02aa
+ },
+
+ [MTD_UADDR_0x0555_0x0AAA] = {
+ .addr1 = 0x0555,
+ .addr2 = 0x0aaa
+ },
+
+ [MTD_UADDR_0x5555_0x2AAA] = {
+ .addr1 = 0x5555,
+ .addr2 = 0x2aaa
+ },
+
+ [MTD_UADDR_0x0AAA_0x0555] = {
+ .addr1 = 0x0AAA,
+ .addr2 = 0x0555
+ },
+
+ [MTD_UADDR_DONT_CARE] = {
+ .addr1 = 0x0000, /* Doesn't matter which address */
+ .addr2 = 0x0000 /* is used - must be last entry */
+ },
+
+ [MTD_UADDR_UNNECESSARY] = {
+ .addr1 = 0x0000,
+ .addr2 = 0x0000
+ }
+};
+
+
+struct amd_flash_info {
+ const __u16 mfr_id;
+ const __u16 dev_id;
+ const char *name;
+ const int DevSize;
+ const int NumEraseRegions;
+ const int CmdSet;
+ const __u8 uaddr[4]; /* unlock addrs for 8, 16, 32, 64 */
+ const ulong regions[6];
+};
+
+#define ERASEINFO(size,blocks) (size<<8)|(blocks-1)
+
+#define SIZE_64KiB 16
+#define SIZE_128KiB 17
+#define SIZE_256KiB 18
+#define SIZE_512KiB 19
+#define SIZE_1MiB 20
+#define SIZE_2MiB 21
+#define SIZE_4MiB 22
+#define SIZE_8MiB 23
+
+static const struct amd_flash_info jedec_table[] = {
+#ifdef CFG_FLASH_LEGACY_256Kx8
+ {
+ .mfr_id = MANUFACTURER_SST,
+ .dev_id = SST39LF020,
+ .name = "SST 39LF020",
+ .uaddr = {
+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+ },
+ .DevSize = SIZE_256KiB,
+ .CmdSet = P_ID_AMD_STD,
+ .NumEraseRegions= 1,
+ .regions = {
+ ERASEINFO(0x01000,64),
+ }
+ },
+#endif
+#ifdef CFG_FLASH_LEGACY_512Kx8
+ {
+ .mfr_id = MANUFACTURER_AMD,
+ .dev_id = AM29LV040B,
+ .name = "AMD AM29LV040B",
+ .uaddr = {
+ [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+ },
+ .DevSize = SIZE_512KiB,
+ .CmdSet = P_ID_AMD_STD,
+ .NumEraseRegions= 1,
+ .regions = {
+ ERASEINFO(0x10000,8),
+ }
+ },
+ {
+ .mfr_id = MANUFACTURER_SST,
+ .dev_id = SST39LF040,
+ .name = "SST 39LF040",
+ .uaddr = {
+ [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+ },
+ .DevSize = SIZE_512KiB,
+ .CmdSet = P_ID_AMD_STD,
+ .NumEraseRegions= 1,
+ .regions = {
+ ERASEINFO(0x01000,128),
+ }
+ },
+#endif
+};
+
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+
+static inline void fill_info(flash_info_t *info, const struct amd_flash_info *jedec_entry, ulong base)
+{
+ int i,j;
+ int sect_cnt;
+ int size_ratio;
+ int total_size;
+ enum uaddr uaddr_idx;
+
+ size_ratio = info->portwidth / info->chipwidth;
+
+ debug("Found JEDEC Flash: %s\n", jedec_entry->name);
+ info->vendor = jedec_entry->CmdSet;
+ /* Todo: do we need device-specific timeouts? */
+ info->erase_blk_tout = 30000;
+ info->buffer_write_tout = 1000;
+ info->write_tout = 100;
+ info->name = jedec_entry->name;
+
+ /* copy unlock addresses from device table to CFI info struct. This
+ is just here because the addresses are in the table anyway - if
+ the flash is not detected due to wrong unlock addresses,
+ flash_detect_legacy would have to try all of them before we even
+ get here. */
+ switch(info->chipwidth) {
+ case FLASH_CFI_8BIT:
+ uaddr_idx = jedec_entry->uaddr[0];
+ break;
+ case FLASH_CFI_16BIT:
+ uaddr_idx = jedec_entry->uaddr[1];
+ break;
+ case FLASH_CFI_32BIT:
+ uaddr_idx = jedec_entry->uaddr[2];
+ break;
+ default:
+ uaddr_idx = MTD_UADDR_NOT_SUPPORTED;
+ break;
+ }
+
+ debug("unlock address index %d\n", uaddr_idx);
+ info->addr_unlock1 = unlock_addrs[uaddr_idx].addr1;
+ info->addr_unlock2 = unlock_addrs[uaddr_idx].addr2;
+ debug("unlock addresses are 0x%x/0x%x\n", info->addr_unlock1, info->addr_unlock2);
+
+ sect_cnt = 0;
+ total_size = 0;
+ for (i = 0; i < jedec_entry->NumEraseRegions; i++) {
+ ulong erase_region_size = jedec_entry->regions[i] >> 8;
+ ulong erase_region_count = (jedec_entry->regions[i] & 0xff) + 1;
+
+ total_size += erase_region_size * erase_region_count;
+ debug ("erase_region_count = %d erase_region_size = %d\n",
+ erase_region_count, erase_region_size);
+ for (j = 0; j < erase_region_count; j++) {
+ if (sect_cnt >= CFG_MAX_FLASH_SECT) {
+ printf("ERROR: too many flash sectors\n");
+ break;
+ }
+ info->start[sect_cnt] = base;
+ base += (erase_region_size * size_ratio);
+ sect_cnt++;
+ }
+ }
+ info->sector_count = sect_cnt;
+ info->size = total_size * size_ratio;
+}
+
+/*-----------------------------------------------------------------------
+ * match jedec ids against table. If a match is found, fill flash_info entry
+ */
+int jedec_flash_match(flash_info_t *info, ulong base)
+{
+ int ret = 0;
+ int i;
+ ulong mask = 0xFFFF;
+ if (info->chipwidth == 1)
+ mask = 0xFF;
+
+ for (i = 0; i < ARRAY_SIZE(jedec_table); i++) {
+ if ((jedec_table[i].mfr_id & mask) == (info->manufacturer_id & mask) &&
+ (jedec_table[i].dev_id & mask) == (info->device_id & mask)) {
+ fill_info(info, &jedec_table[i], base);
+ ret = 1;
+ break;
+ }
+ }
+ return ret;
+}
diff --git a/drivers/mw_eeprom.c b/drivers/mtd/mw_eeprom.c
index 2b33488..2b33488 100644
--- a/drivers/mw_eeprom.c
+++ b/drivers/mtd/mw_eeprom.c
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
new file mode 100644
index 0000000..42864f9
--- /dev/null
+++ b/drivers/mtd/nand/Makefile
@@ -0,0 +1,51 @@
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB := $(obj)libnand.a
+
+COBJS-y += nand.o
+COBJS-y += nand_base.o
+COBJS-y += nand_ids.o
+COBJS-y += nand_ecc.o
+COBJS-y += nand_bbt.o
+COBJS-y += nand_util.o
+
+COBJS := $(COBJS-y)
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index e17af70..e17af70 100644
--- a/drivers/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
diff --git a/drivers/nand/nand.c b/drivers/mtd/nand/nand.c
index 27b5792..27b5792 100644
--- a/drivers/nand/nand.c
+++ b/drivers/mtd/nand/nand.c
diff --git a/drivers/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 151f535..151f535 100644
--- a/drivers/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
diff --git a/drivers/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 19a9bc2..19a9bc2 100644
--- a/drivers/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
diff --git a/drivers/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index 4c532b0..4c532b0 100644
--- a/drivers/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
diff --git a/drivers/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index 6d7e347..6d7e347 100644
--- a/drivers/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
diff --git a/drivers/nand/nand_util.c b/drivers/mtd/nand/nand_util.c
index 4fd4e16..4fd4e16 100644
--- a/drivers/nand/nand_util.c
+++ b/drivers/mtd/nand/nand_util.c
diff --git a/drivers/nand_legacy/Makefile b/drivers/mtd/nand_legacy/Makefile
index 95314d8..95314d8 100644
--- a/drivers/nand_legacy/Makefile
+++ b/drivers/mtd/nand_legacy/Makefile
diff --git a/drivers/nand_legacy/nand_legacy.c b/drivers/mtd/nand_legacy/nand_legacy.c
index 49d2ebb..49d2ebb 100644
--- a/drivers/nand_legacy/nand_legacy.c
+++ b/drivers/mtd/nand_legacy/nand_legacy.c
diff --git a/drivers/onenand/Makefile b/drivers/mtd/onenand/Makefile
index 2049413..2049413 100644
--- a/drivers/onenand/Makefile
+++ b/drivers/mtd/onenand/Makefile
diff --git a/drivers/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 7983a4a..7983a4a 100644
--- a/drivers/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
diff --git a/drivers/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
index 5a610ee..5a610ee 100644
--- a/drivers/onenand/onenand_bbt.c
+++ b/drivers/mtd/onenand/onenand_bbt.c
diff --git a/drivers/3c589.c b/drivers/net/3c589.c
index 080b686..080b686 100644
--- a/drivers/3c589.c
+++ b/drivers/net/3c589.c
diff --git a/drivers/3c589.h b/drivers/net/3c589.h
index 6735bf9..6735bf9 100644
--- a/drivers/3c589.h
+++ b/drivers/net/3c589.h
diff --git a/drivers/5701rls.c b/drivers/net/5701rls.c
index 86950d0..86950d0 100644
--- a/drivers/5701rls.c
+++ b/drivers/net/5701rls.c
diff --git a/drivers/5701rls.h b/drivers/net/5701rls.h
index 30b127a..30b127a 100644
--- a/drivers/5701rls.h
+++ b/drivers/net/5701rls.h
diff --git a/drivers/8390.h b/drivers/net/8390.h
index f087217..f087217 100644
--- a/drivers/8390.h
+++ b/drivers/net/8390.h
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 37d69b9..41e1bde 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -25,8 +25,39 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libnet.a
-COBJS := mcffec.o
+COBJS-y += 3c589.o
+COBJS-y += bcm570x.o bcm570x_autoneg.o 5701rls.o
+COBJS-y += cs8900.o
+COBJS-y += dc2114x.o
+COBJS-y += dm9000x.o
+COBJS-y += e1000.o
+COBJS-y += eepro100.o
+COBJS-y += enc28j60.o
+COBJS-y += inca-ip_sw.o
+COBJS-y += ks8695eth.o
+COBJS-y += lan91c96.o
+COBJS-y += macb.o
+COBJS-y += mcffec.o
+COBJS-y += natsemi.o
+COBJS-y += ne2000.o
+COBJS-y += netarm_eth.o
+COBJS-y += netconsole.o
+COBJS-y += ns7520_eth.o
+COBJS-y += ns8382x.o
+COBJS-y += ns9750_eth.o
+COBJS-y += pcnet.o
+COBJS-y += plb2800_eth.o
+COBJS-y += rtl8019.o
+COBJS-y += rtl8139.o
+COBJS-y += rtl8169.o
+COBJS-y += s3c4510b_eth.o
+COBJS-y += smc91111.o
+COBJS-y += tigon3.o
+COBJS-y += tsec.o
+COBJS-y += tsi108_eth.o
+COBJS-y += uli526x.o
+COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
diff --git a/drivers/bcm570x.c b/drivers/net/bcm570x.c
index c8f4064..c8f4064 100644
--- a/drivers/bcm570x.c
+++ b/drivers/net/bcm570x.c
diff --git a/drivers/bcm570x_autoneg.c b/drivers/net/bcm570x_autoneg.c
index 9023796..9023796 100644
--- a/drivers/bcm570x_autoneg.c
+++ b/drivers/net/bcm570x_autoneg.c
diff --git a/drivers/bcm570x_autoneg.h b/drivers/net/bcm570x_autoneg.h
index 7830944..7830944 100644
--- a/drivers/bcm570x_autoneg.h
+++ b/drivers/net/bcm570x_autoneg.h
diff --git a/drivers/bcm570x_bits.h b/drivers/net/bcm570x_bits.h
index 615d61e..615d61e 100644
--- a/drivers/bcm570x_bits.h
+++ b/drivers/net/bcm570x_bits.h
diff --git a/drivers/bcm570x_debug.h b/drivers/net/bcm570x_debug.h
index 88e209b..88e209b 100644
--- a/drivers/bcm570x_debug.h
+++ b/drivers/net/bcm570x_debug.h
diff --git a/drivers/bcm570x_lm.h b/drivers/net/bcm570x_lm.h
index 2ea6ca8..2ea6ca8 100644
--- a/drivers/bcm570x_lm.h
+++ b/drivers/net/bcm570x_lm.h
diff --git a/drivers/bcm570x_mm.h b/drivers/net/bcm570x_mm.h
index ff5302f..ff5302f 100644
--- a/drivers/bcm570x_mm.h
+++ b/drivers/net/bcm570x_mm.h
diff --git a/drivers/bcm570x_queue.h b/drivers/net/bcm570x_queue.h
index 336b3ca..336b3ca 100644
--- a/drivers/bcm570x_queue.h
+++ b/drivers/net/bcm570x_queue.h
diff --git a/drivers/cs8900.c b/drivers/net/cs8900.c
index 80c4ba2..80c4ba2 100644
--- a/drivers/cs8900.c
+++ b/drivers/net/cs8900.c
diff --git a/drivers/cs8900.h b/drivers/net/cs8900.h
index f886d10..f886d10 100644
--- a/drivers/cs8900.h
+++ b/drivers/net/cs8900.h
diff --git a/drivers/dc2114x.c b/drivers/net/dc2114x.c
index d5275dc..d5275dc 100644
--- a/drivers/dc2114x.c
+++ b/drivers/net/dc2114x.c
diff --git a/drivers/dm9000x.c b/drivers/net/dm9000x.c
index 6131b5c..6131b5c 100644
--- a/drivers/dm9000x.c
+++ b/drivers/net/dm9000x.c
diff --git a/drivers/dm9000x.h b/drivers/net/dm9000x.h
index f47ff8c..f47ff8c 100644
--- a/drivers/dm9000x.h
+++ b/drivers/net/dm9000x.h
diff --git a/drivers/e1000.c b/drivers/net/e1000.c
index f0741da..f0741da 100644
--- a/drivers/e1000.c
+++ b/drivers/net/e1000.c
diff --git a/drivers/e1000.h b/drivers/net/e1000.h
index 0fbdc90..0fbdc90 100644
--- a/drivers/e1000.h
+++ b/drivers/net/e1000.h
diff --git a/drivers/eepro100.c b/drivers/net/eepro100.c
index 738146e..738146e 100644
--- a/drivers/eepro100.c
+++ b/drivers/net/eepro100.c
diff --git a/drivers/enc28j60.c b/drivers/net/enc28j60.c
index 98303ac..98303ac 100644
--- a/drivers/enc28j60.c
+++ b/drivers/net/enc28j60.c
diff --git a/drivers/inca-ip_sw.c b/drivers/net/inca-ip_sw.c
index e4aaed6..e4aaed6 100644
--- a/drivers/inca-ip_sw.c
+++ b/drivers/net/inca-ip_sw.c
diff --git a/drivers/ks8695eth.c b/drivers/net/ks8695eth.c
index b598dd7..b598dd7 100644
--- a/drivers/ks8695eth.c
+++ b/drivers/net/ks8695eth.c
diff --git a/drivers/lan91c96.c b/drivers/net/lan91c96.c
index ecdcbd9..ecdcbd9 100644
--- a/drivers/lan91c96.c
+++ b/drivers/net/lan91c96.c
diff --git a/drivers/lan91c96.h b/drivers/net/lan91c96.h
index 7d33a82..7d33a82 100644
--- a/drivers/lan91c96.h
+++ b/drivers/net/lan91c96.h
diff --git a/drivers/macb.c b/drivers/net/macb.c
index 95cdc49..95cdc49 100644
--- a/drivers/macb.c
+++ b/drivers/net/macb.c
diff --git a/drivers/macb.h b/drivers/net/macb.h
index c778e4e..c778e4e 100644
--- a/drivers/macb.h
+++ b/drivers/net/macb.h
diff --git a/drivers/natsemi.c b/drivers/net/natsemi.c
index 075d6c5..075d6c5 100644
--- a/drivers/natsemi.c
+++ b/drivers/net/natsemi.c
diff --git a/drivers/ne2000.c b/drivers/net/ne2000.c
index 695a1dc..c978d62 100644
--- a/drivers/ne2000.c
+++ b/drivers/net/ne2000.c
@@ -723,7 +723,8 @@ static hw_info_t hw_info[] = {
{ /* SuperSocket RE450T */ 0x0110, 0x00, 0xe0, 0x98, 0 },
{ /* Volktek NPL-402CT */ 0x0060, 0x00, 0x40, 0x05, 0 },
{ /* NEC PC-9801N-J12 */ 0x0ff0, 0x00, 0x00, 0x4c, 0 },
- { /* PCMCIA Technology OEM */ 0x01c8, 0x00, 0xa0, 0x0c, 0 }
+ { /* PCMCIA Technology OEM */ 0x01c8, 0x00, 0xa0, 0x0c, 0 },
+ { /* Qemu */ 0x0, 0x52, 0x54, 0x00, 0 }
};
#define NR_INFO (sizeof(hw_info)/sizeof(hw_info_t))
@@ -824,30 +825,22 @@ static hw_info_t * get_prom(void ) {
/* U-boot specific routines */
-#define NB 5
static unsigned char *pbuf = NULL;
-static int plen[NB];
-static int nrx = 0;
static int pkey = -1;
static int initialized=0;
void uboot_push_packet_len(int len) {
- PRINTK("pushed len = %d, nrx = %d\n", len, nrx);
+ PRINTK("pushed len = %d\n", len);
if (len>=2000) {
printf("NE2000: packet too big\n");
return;
}
- if (nrx >= NB) {
- printf("losing packets in rx\n");
- return;
- }
- plen[nrx] = len;
- dp83902a_recv(&pbuf[nrx*2000], len);
+ dp83902a_recv(&pbuf[0], len);
/*Just pass it to the upper layer*/
- NetReceive(&pbuf[nrx*2000], plen[nrx]);
+ NetReceive(&pbuf[0], len);
}
void uboot_push_tx_done(int key, int val) {
@@ -862,9 +855,9 @@ int eth_init(bd_t *bd) {
PRINTK("### eth_init\n");
if (!pbuf) {
- pbuf = malloc(NB*2000);
+ pbuf = malloc(2000);
if (!pbuf) {
- printf("Cannot allocate rx buffers\n");
+ printf("Cannot allocate rx buffer\n");
return -1;
}
}
diff --git a/drivers/ne2000.h b/drivers/net/ne2000.h
index c13d9f0..c13d9f0 100644
--- a/drivers/ne2000.h
+++ b/drivers/net/ne2000.h
diff --git a/drivers/netarm_eth.c b/drivers/net/netarm_eth.c
index a99ee5d..a99ee5d 100644
--- a/drivers/netarm_eth.c
+++ b/drivers/net/netarm_eth.c
diff --git a/drivers/netarm_eth.h b/drivers/net/netarm_eth.h
index 8edab82..8edab82 100644
--- a/drivers/netarm_eth.h
+++ b/drivers/net/netarm_eth.h
diff --git a/drivers/netconsole.c b/drivers/net/netconsole.c
index 69089f9..69089f9 100644
--- a/drivers/netconsole.c
+++ b/drivers/net/netconsole.c
diff --git a/drivers/nicext.h b/drivers/net/nicext.h
index 4074972..4074972 100644
--- a/drivers/nicext.h
+++ b/drivers/net/nicext.h
diff --git a/drivers/ns7520_eth.c b/drivers/net/ns7520_eth.c
index a5a20df..a5a20df 100644
--- a/drivers/ns7520_eth.c
+++ b/drivers/net/ns7520_eth.c
diff --git a/drivers/ns8382x.c b/drivers/net/ns8382x.c
index f8b143a..f8b143a 100644
--- a/drivers/ns8382x.c
+++ b/drivers/net/ns8382x.c
diff --git a/drivers/ns9750_eth.c b/drivers/net/ns9750_eth.c
index 067ff8e..067ff8e 100644
--- a/drivers/ns9750_eth.c
+++ b/drivers/net/ns9750_eth.c
diff --git a/drivers/pcnet.c b/drivers/net/pcnet.c
index 2af0e8f..2af0e8f 100644
--- a/drivers/pcnet.c
+++ b/drivers/net/pcnet.c
diff --git a/drivers/plb2800_eth.c b/drivers/net/plb2800_eth.c
index 0ae5d80..0ae5d80 100644
--- a/drivers/plb2800_eth.c
+++ b/drivers/net/plb2800_eth.c
diff --git a/drivers/rtl8019.c b/drivers/net/rtl8019.c
index 409a69f..409a69f 100644
--- a/drivers/rtl8019.c
+++ b/drivers/net/rtl8019.c
diff --git a/drivers/rtl8019.h b/drivers/net/rtl8019.h
index 38116ad..38116ad 100644
--- a/drivers/rtl8019.h
+++ b/drivers/net/rtl8019.h
diff --git a/drivers/rtl8139.c b/drivers/net/rtl8139.c
index 2367180..2367180 100644
--- a/drivers/rtl8139.c
+++ b/drivers/net/rtl8139.c
diff --git a/drivers/rtl8169.c b/drivers/net/rtl8169.c
index 63ea2cc..63ea2cc 100644
--- a/drivers/rtl8169.c
+++ b/drivers/net/rtl8169.c
diff --git a/drivers/s3c4510b_eth.c b/drivers/net/s3c4510b_eth.c
index 48901aa..3d9066a 100644
--- a/drivers/s3c4510b_eth.c
+++ b/drivers/net/s3c4510b_eth.c
@@ -175,7 +175,7 @@ s32 eth_send(volatile void *packet, s32 length)
}
/* copy user data into frame data pointer */
- memcpy((void *)(eth->m_curTX_FD->m_frameDataPtr.bf.dataPtr),
+ memcpy((void *)((u32)(eth->m_curTX_FD->m_frameDataPtr.bf.dataPtr)),
(void *)packet,
length);
diff --git a/drivers/s3c4510b_eth.h b/drivers/net/s3c4510b_eth.h
index cbddba7..cbddba7 100644
--- a/drivers/s3c4510b_eth.h
+++ b/drivers/net/s3c4510b_eth.h
diff --git a/drivers/sk98lin/Makefile b/drivers/net/sk98lin/Makefile
index 7e50b1d..a7d4a3b 100644
--- a/drivers/sk98lin/Makefile
+++ b/drivers/net/sk98lin/Makefile
@@ -29,12 +29,26 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libsk98lin.a
-COBJS := skge.o skaddr.o skgehwt.o skgeinit.o skgepnmi.o skgesirq.o \
- ski2c.o sklm80.o skqueue.o skrlmt.o sktimer.o skvpd.o \
- skxmac2.o skcsum.o #skproc.o
-
-COBJS += uboot_skb.o uboot_drv.o
-
+COBJS-y += skge.o
+COBJS-y += skaddr.o
+COBJS-y += skgehwt.o
+COBJS-y += skgeinit.o
+COBJS-y += skgepnmi.o
+COBJS-y += skgesirq.o
+COBJS-y += ski2c.o
+COBJS-y += sklm80.o
+COBJS-y += skqueue.o
+COBJS-y += skrlmt.o
+COBJS-y += sktimer.o
+COBJS-y += skvpd.o
+COBJS-y += skxmac2.o
+COBJS-y += skcsum.o
+#COBJS-y += skproc.o
+
+COBJS-y += uboot_skb.o
+COBJS-y += uboot_drv.o
+
+COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
diff --git a/drivers/sk98lin/h/lm80.h b/drivers/net/sk98lin/h/lm80.h
index 981a4ca..981a4ca 100644
--- a/drivers/sk98lin/h/lm80.h
+++ b/drivers/net/sk98lin/h/lm80.h
diff --git a/drivers/sk98lin/h/skaddr.h b/drivers/net/sk98lin/h/skaddr.h
index 711f873..711f873 100644
--- a/drivers/sk98lin/h/skaddr.h
+++ b/drivers/net/sk98lin/h/skaddr.h
diff --git a/drivers/sk98lin/h/skcsum.h b/drivers/net/sk98lin/h/skcsum.h
index 2acae32..2acae32 100644
--- a/drivers/sk98lin/h/skcsum.h
+++ b/drivers/net/sk98lin/h/skcsum.h
diff --git a/drivers/sk98lin/h/skdebug.h b/drivers/net/sk98lin/h/skdebug.h
index cf5b5ad..cf5b5ad 100644
--- a/drivers/sk98lin/h/skdebug.h
+++ b/drivers/net/sk98lin/h/skdebug.h
diff --git a/drivers/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h
index af34d7b..af34d7b 100644
--- a/drivers/sk98lin/h/skdrv1st.h
+++ b/drivers/net/sk98lin/h/skdrv1st.h
diff --git a/drivers/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h
index a311827..a311827 100644
--- a/drivers/sk98lin/h/skdrv2nd.h
+++ b/drivers/net/sk98lin/h/skdrv2nd.h
diff --git a/drivers/sk98lin/h/skerror.h b/drivers/net/sk98lin/h/skerror.h
index a454d9d..a454d9d 100644
--- a/drivers/sk98lin/h/skerror.h
+++ b/drivers/net/sk98lin/h/skerror.h
diff --git a/drivers/sk98lin/h/skgedrv.h b/drivers/net/sk98lin/h/skgedrv.h
index 72ba9ce..72ba9ce 100644
--- a/drivers/sk98lin/h/skgedrv.h
+++ b/drivers/net/sk98lin/h/skgedrv.h
diff --git a/drivers/sk98lin/h/skgehw.h b/drivers/net/sk98lin/h/skgehw.h
index 2c98427..2c98427 100644
--- a/drivers/sk98lin/h/skgehw.h
+++ b/drivers/net/sk98lin/h/skgehw.h
diff --git a/drivers/sk98lin/h/skgehwt.h b/drivers/net/sk98lin/h/skgehwt.h
index 8aa9edd..8aa9edd 100644
--- a/drivers/sk98lin/h/skgehwt.h
+++ b/drivers/net/sk98lin/h/skgehwt.h
diff --git a/drivers/sk98lin/h/skgei2c.h b/drivers/net/sk98lin/h/skgei2c.h
index e639f73..e639f73 100644
--- a/drivers/sk98lin/h/skgei2c.h
+++ b/drivers/net/sk98lin/h/skgei2c.h
diff --git a/drivers/sk98lin/h/skgeinit.h b/drivers/net/sk98lin/h/skgeinit.h
index cdddef9..cdddef9 100644
--- a/drivers/sk98lin/h/skgeinit.h
+++ b/drivers/net/sk98lin/h/skgeinit.h
diff --git a/drivers/sk98lin/h/skgepnm2.h b/drivers/net/sk98lin/h/skgepnm2.h
index 5c44f47..5c44f47 100644
--- a/drivers/sk98lin/h/skgepnm2.h
+++ b/drivers/net/sk98lin/h/skgepnm2.h
diff --git a/drivers/sk98lin/h/skgepnmi.h b/drivers/net/sk98lin/h/skgepnmi.h
index 7532313..7532313 100644
--- a/drivers/sk98lin/h/skgepnmi.h
+++ b/drivers/net/sk98lin/h/skgepnmi.h
diff --git a/drivers/sk98lin/h/skgesirq.h b/drivers/net/sk98lin/h/skgesirq.h
index fc001b23..fc001b23 100644
--- a/drivers/sk98lin/h/skgesirq.h
+++ b/drivers/net/sk98lin/h/skgesirq.h
diff --git a/drivers/sk98lin/h/ski2c.h b/drivers/net/sk98lin/h/ski2c.h
index 5ffaf6e..5ffaf6e 100644
--- a/drivers/sk98lin/h/ski2c.h
+++ b/drivers/net/sk98lin/h/ski2c.h
diff --git a/drivers/sk98lin/h/skqueue.h b/drivers/net/sk98lin/h/skqueue.h
index bce20a7..bce20a7 100644
--- a/drivers/sk98lin/h/skqueue.h
+++ b/drivers/net/sk98lin/h/skqueue.h
diff --git a/drivers/sk98lin/h/skrlmt.h b/drivers/net/sk98lin/h/skrlmt.h
index 04d025b..04d025b 100644
--- a/drivers/sk98lin/h/skrlmt.h
+++ b/drivers/net/sk98lin/h/skrlmt.h
diff --git a/drivers/sk98lin/h/sktimer.h b/drivers/net/sk98lin/h/sktimer.h
index 36f8ccb..36f8ccb 100644
--- a/drivers/sk98lin/h/sktimer.h
+++ b/drivers/net/sk98lin/h/sktimer.h
diff --git a/drivers/sk98lin/h/sktypes.h b/drivers/net/sk98lin/h/sktypes.h
index e657016..e657016 100644
--- a/drivers/sk98lin/h/sktypes.h
+++ b/drivers/net/sk98lin/h/sktypes.h
diff --git a/drivers/sk98lin/h/skversion.h b/drivers/net/sk98lin/h/skversion.h
index ef46685..ef46685 100644
--- a/drivers/sk98lin/h/skversion.h
+++ b/drivers/net/sk98lin/h/skversion.h
diff --git a/drivers/sk98lin/h/skvpd.h b/drivers/net/sk98lin/h/skvpd.h
index 1be34c5..1be34c5 100644
--- a/drivers/sk98lin/h/skvpd.h
+++ b/drivers/net/sk98lin/h/skvpd.h
diff --git a/drivers/sk98lin/h/xmac_ii.h b/drivers/net/sk98lin/h/xmac_ii.h
index 2ef903a..2ef903a 100644
--- a/drivers/sk98lin/h/xmac_ii.h
+++ b/drivers/net/sk98lin/h/xmac_ii.h
diff --git a/drivers/sk98lin/skaddr.c b/drivers/net/sk98lin/skaddr.c
index ed79c04..ed79c04 100644
--- a/drivers/sk98lin/skaddr.c
+++ b/drivers/net/sk98lin/skaddr.c
diff --git a/drivers/sk98lin/skcsum.c b/drivers/net/sk98lin/skcsum.c
index a5dc572..a5dc572 100644
--- a/drivers/sk98lin/skcsum.c
+++ b/drivers/net/sk98lin/skcsum.c
diff --git a/drivers/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index 61a6094..61a6094 100644
--- a/drivers/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
diff --git a/drivers/sk98lin/skgehwt.c b/drivers/net/sk98lin/skgehwt.c
index f8681a8..f8681a8 100644
--- a/drivers/sk98lin/skgehwt.c
+++ b/drivers/net/sk98lin/skgehwt.c
diff --git a/drivers/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c
index a18dc0a..a18dc0a 100644
--- a/drivers/sk98lin/skgeinit.c
+++ b/drivers/net/sk98lin/skgeinit.c
diff --git a/drivers/sk98lin/skgemib.c b/drivers/net/sk98lin/skgemib.c
index 4a9e9e6..4a9e9e6 100644
--- a/drivers/sk98lin/skgemib.c
+++ b/drivers/net/sk98lin/skgemib.c
diff --git a/drivers/sk98lin/skgepnmi.c b/drivers/net/sk98lin/skgepnmi.c
index b5d32b0..b5d32b0 100644
--- a/drivers/sk98lin/skgepnmi.c
+++ b/drivers/net/sk98lin/skgepnmi.c
diff --git a/drivers/sk98lin/skgesirq.c b/drivers/net/sk98lin/skgesirq.c
index e5a4f7e..e5a4f7e 100644
--- a/drivers/sk98lin/skgesirq.c
+++ b/drivers/net/sk98lin/skgesirq.c
diff --git a/drivers/sk98lin/ski2c.c b/drivers/net/sk98lin/ski2c.c
index 2ab635a..2ab635a 100644
--- a/drivers/sk98lin/ski2c.c
+++ b/drivers/net/sk98lin/ski2c.c
diff --git a/drivers/sk98lin/sklm80.c b/drivers/net/sk98lin/sklm80.c
index 687572b..687572b 100644
--- a/drivers/sk98lin/sklm80.c
+++ b/drivers/net/sk98lin/sklm80.c
diff --git a/drivers/sk98lin/skproc.c b/drivers/net/sk98lin/skproc.c
index 4e34073..4e34073 100644
--- a/drivers/sk98lin/skproc.c
+++ b/drivers/net/sk98lin/skproc.c
diff --git a/drivers/sk98lin/skqueue.c b/drivers/net/sk98lin/skqueue.c
index c49baed..c49baed 100644
--- a/drivers/sk98lin/skqueue.c
+++ b/drivers/net/sk98lin/skqueue.c
diff --git a/drivers/sk98lin/skrlmt.c b/drivers/net/sk98lin/skrlmt.c
index f8a3b41..f8a3b41 100644
--- a/drivers/sk98lin/skrlmt.c
+++ b/drivers/net/sk98lin/skrlmt.c
diff --git a/drivers/sk98lin/sktimer.c b/drivers/net/sk98lin/sktimer.c
index 37cd4c9..37cd4c9 100644
--- a/drivers/sk98lin/sktimer.c
+++ b/drivers/net/sk98lin/sktimer.c
diff --git a/drivers/sk98lin/skvpd.c b/drivers/net/sk98lin/skvpd.c
index 3b81e67..3b81e67 100644
--- a/drivers/sk98lin/skvpd.c
+++ b/drivers/net/sk98lin/skvpd.c
diff --git a/drivers/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c
index e6b5a95..e6b5a95 100644
--- a/drivers/sk98lin/skxmac2.c
+++ b/drivers/net/sk98lin/skxmac2.c
diff --git a/drivers/sk98lin/u-boot_compat.h b/drivers/net/sk98lin/u-boot_compat.h
index 1e385f8..1e385f8 100644
--- a/drivers/sk98lin/u-boot_compat.h
+++ b/drivers/net/sk98lin/u-boot_compat.h
diff --git a/drivers/sk98lin/uboot_drv.c b/drivers/net/sk98lin/uboot_drv.c
index d02cd1b..d02cd1b 100644
--- a/drivers/sk98lin/uboot_drv.c
+++ b/drivers/net/sk98lin/uboot_drv.c
diff --git a/drivers/sk98lin/uboot_skb.c b/drivers/net/sk98lin/uboot_skb.c
index 3a487a8..3a487a8 100644
--- a/drivers/sk98lin/uboot_skb.c
+++ b/drivers/net/sk98lin/uboot_skb.c
diff --git a/drivers/smc91111.c b/drivers/net/smc91111.c
index 8061f12..8061f12 100644
--- a/drivers/smc91111.c
+++ b/drivers/net/smc91111.c
diff --git a/drivers/smc91111.h b/drivers/net/smc91111.h
index d03cbc3..d03cbc3 100644
--- a/drivers/smc91111.h
+++ b/drivers/net/smc91111.h
diff --git a/drivers/tigon3.c b/drivers/net/tigon3.c
index 5f6a4ec..5f6a4ec 100644
--- a/drivers/tigon3.c
+++ b/drivers/net/tigon3.c
diff --git a/drivers/tigon3.h b/drivers/net/tigon3.h
index c03347f..c03347f 100644
--- a/drivers/tigon3.h
+++ b/drivers/net/tigon3.h
diff --git a/drivers/tsec.c b/drivers/net/tsec.c
index 4ff3339..108cebd 100644
--- a/drivers/tsec.c
+++ b/drivers/net/tsec.c
@@ -117,10 +117,13 @@ struct phy_info *get_phy_info(struct eth_device *dev);
void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd);
static void adjust_link(struct eth_device *dev);
static void relocate_cmds(void);
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
+ && !defined(BITBANGMII)
static int tsec_miiphy_write(char *devname, unsigned char addr,
unsigned char reg, unsigned short value);
static int tsec_miiphy_read(char *devname, unsigned char addr,
unsigned char reg, unsigned short *value);
+#endif
#ifdef CONFIG_MCAST_TFTP
static int tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set);
#endif
@@ -671,6 +674,15 @@ uint mii_cis8204_setmode(uint mii_reg, struct tsec_private * priv)
return MIIM_CIS8204_EPHYCON_INIT;
}
+uint mii_m88e1111s_setmode(uint mii_reg, struct tsec_private *priv)
+{
+ uint mii_data = read_phy_reg(priv, mii_reg);
+
+ if (priv->flags & TSEC_REDUCED)
+ mii_data = (mii_data & 0xfff0) | 0x000b;
+ return mii_data;
+}
+
/* Initialized required registers to appropriate values, zeroing
* those we don't care about (unless zero is bad, in which case,
* choose a more appropriate value)
@@ -803,6 +815,7 @@ static void startup_tsec(struct eth_device *dev)
/* Tell the DMA it is clear to go */
regs->dmactrl |= DMACTRL_INIT_SETTINGS;
regs->tstat = TSTAT_CLEAR_THALT;
+ regs->rstat = RSTAT_CLEAR_RHALT;
regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
}
@@ -1030,6 +1043,7 @@ struct phy_info phy_info_M88E1111S = {
(struct phy_cmd[]){ /* config */
/* Reset and configure the PHY */
{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
+ {0x1b, 0x848f, &mii_m88e1111s_setmode},
{0x14, 0x0cd2, NULL}, /* Delay RGMII TX and RX */
{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
diff --git a/drivers/tsec.h b/drivers/net/tsec.h
index 2f0092a..2f0092a 100644
--- a/drivers/tsec.h
+++ b/drivers/net/tsec.h
diff --git a/drivers/tsi108_eth.c b/drivers/net/tsi108_eth.c
index 524e9da..524e9da 100644
--- a/drivers/tsi108_eth.c
+++ b/drivers/net/tsi108_eth.c
diff --git a/drivers/net/uli526x.c b/drivers/net/uli526x.c
new file mode 100644
index 0000000..1267c57
--- /dev/null
+++ b/drivers/net/uli526x.c
@@ -0,0 +1,996 @@
+/*
+ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Roy Zang <tie-fei.zang@freescale.com>, Sep, 2007
+ *
+ * Description:
+ * ULI 526x Ethernet port driver.
+ * Based on the Linux driver: drivers/net/tulip/uli526x.c
+ *
+ * This 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.
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <net.h>
+#include <asm/io.h>
+#include <pci.h>
+#include <miiphy.h>
+
+/* some kernel function compatible define */
+
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
+ defined(CONFIG_ULI526X)
+
+#undef DEBUG
+
+/* Board/System/Debug information/definition */
+#define ULI_VENDOR_ID 0x10B9
+#define ULI5261_DEVICE_ID 0x5261
+#define ULI5263_DEVICE_ID 0x5263
+/* ULi M5261 ID*/
+#define PCI_ULI5261_ID ULI5261_DEVICE_ID << 16 | ULI_VENDOR_ID
+/* ULi M5263 ID*/
+#define PCI_ULI5263_ID ULI5263_DEVICE_ID << 16 | ULI_VENDOR_ID
+
+#define ULI526X_IO_SIZE 0x100
+#define TX_DESC_CNT 0x10 /* Allocated Tx descriptors */
+#define RX_DESC_CNT PKTBUFSRX /* Allocated Rx descriptors */
+#define TX_FREE_DESC_CNT (TX_DESC_CNT - 2) /* Max TX packet count */
+#define TX_WAKE_DESC_CNT (TX_DESC_CNT - 3) /* TX wakeup count */
+#define DESC_ALL_CNT (TX_DESC_CNT + RX_DESC_CNT)
+#define TX_BUF_ALLOC 0x300
+#define RX_ALLOC_SIZE PKTSIZE
+#define ULI526X_RESET 1
+#define CR0_DEFAULT 0
+#define CR6_DEFAULT 0x22200000
+#define CR7_DEFAULT 0x180c1
+#define CR15_DEFAULT 0x06 /* TxJabber RxWatchdog */
+#define TDES0_ERR_MASK 0x4302 /* TXJT, LC, EC, FUE */
+#define MAX_PACKET_SIZE 1514
+#define ULI5261_MAX_MULTICAST 14
+#define RX_COPY_SIZE 100
+#define MAX_CHECK_PACKET 0x8000
+
+#define ULI526X_10MHF 0
+#define ULI526X_100MHF 1
+#define ULI526X_10MFD 4
+#define ULI526X_100MFD 5
+#define ULI526X_AUTO 8
+
+#define ULI526X_TXTH_72 0x400000 /* TX TH 72 byte */
+#define ULI526X_TXTH_96 0x404000 /* TX TH 96 byte */
+#define ULI526X_TXTH_128 0x0000 /* TX TH 128 byte */
+#define ULI526X_TXTH_256 0x4000 /* TX TH 256 byte */
+#define ULI526X_TXTH_512 0x8000 /* TX TH 512 byte */
+#define ULI526X_TXTH_1K 0xC000 /* TX TH 1K byte */
+
+/* CR9 definition: SROM/MII */
+#define CR9_SROM_READ 0x4800
+#define CR9_SRCS 0x1
+#define CR9_SRCLK 0x2
+#define CR9_CRDOUT 0x8
+#define SROM_DATA_0 0x0
+#define SROM_DATA_1 0x4
+#define PHY_DATA_1 0x20000
+#define PHY_DATA_0 0x00000
+#define MDCLKH 0x10000
+
+#define PHY_POWER_DOWN 0x800
+
+#define SROM_V41_CODE 0x14
+
+#define SROM_CLK_WRITE(data, ioaddr) do { \
+ outl(data|CR9_SROM_READ|CR9_SRCS, ioaddr); \
+ udelay(5); \
+ outl(data|CR9_SROM_READ|CR9_SRCS|CR9_SRCLK, ioaddr); \
+ udelay(5); \
+ outl(data|CR9_SROM_READ|CR9_SRCS, ioaddr); \
+ udelay(5); \
+ } while (0)
+
+/* Structure/enum declaration */
+
+struct tx_desc {
+ u32 tdes0, tdes1, tdes2, tdes3; /* Data for the card */
+ char *tx_buf_ptr; /* Data for us */
+ struct tx_desc *next_tx_desc;
+};
+
+struct rx_desc {
+ u32 rdes0, rdes1, rdes2, rdes3; /* Data for the card */
+ char *rx_buf_ptr; /* Data for us */
+ struct rx_desc *next_rx_desc;
+};
+
+struct uli526x_board_info {
+ u32 chip_id; /* Chip vendor/Device ID */
+ pci_dev_t pdev;
+
+ long ioaddr; /* I/O base address */
+ u32 cr0_data;
+ u32 cr5_data;
+ u32 cr6_data;
+ u32 cr7_data;
+ u32 cr15_data;
+
+ /* pointer for memory physical address */
+ dma_addr_t buf_pool_dma_ptr; /* Tx buffer pool memory */
+ dma_addr_t buf_pool_dma_start; /* Tx buffer pool align dword */
+ dma_addr_t desc_pool_dma_ptr; /* descriptor pool memory */
+ dma_addr_t first_tx_desc_dma;
+ dma_addr_t first_rx_desc_dma;
+
+ /* descriptor pointer */
+ unsigned char *buf_pool_ptr; /* Tx buffer pool memory */
+ unsigned char *buf_pool_start; /* Tx buffer pool align dword */
+ unsigned char *desc_pool_ptr; /* descriptor pool memory */
+ struct tx_desc *first_tx_desc;
+ struct tx_desc *tx_insert_ptr;
+ struct tx_desc *tx_remove_ptr;
+ struct rx_desc *first_rx_desc;
+ struct rx_desc *rx_ready_ptr; /* packet come pointer */
+ unsigned long tx_packet_cnt; /* transmitted packet count */
+
+ u16 PHY_reg4; /* Saved Phyxcer register 4 value */
+
+ u8 media_mode; /* user specify media mode */
+ u8 op_mode; /* real work dedia mode */
+ u8 phy_addr;
+
+ /* NIC SROM data */
+ unsigned char srom[128];
+};
+
+enum uli526x_offsets {
+ DCR0 = 0x00, DCR1 = 0x08, DCR2 = 0x10, DCR3 = 0x18, DCR4 = 0x20,
+ DCR5 = 0x28, DCR6 = 0x30, DCR7 = 0x38, DCR8 = 0x40, DCR9 = 0x48,
+ DCR10 = 0x50, DCR11 = 0x58, DCR12 = 0x60, DCR13 = 0x68, DCR14 = 0x70,
+ DCR15 = 0x78
+};
+
+enum uli526x_CR6_bits {
+ CR6_RXSC = 0x2, CR6_PBF = 0x8, CR6_PM = 0x40, CR6_PAM = 0x80,
+ CR6_FDM = 0x200, CR6_TXSC = 0x2000, CR6_STI = 0x100000,
+ CR6_SFT = 0x200000, CR6_RXA = 0x40000000, CR6_NO_PURGE = 0x20000000
+};
+
+/* Global variable declaration -- */
+
+static unsigned char uli526x_media_mode = ULI526X_AUTO;
+
+static struct tx_desc desc_pool_array[DESC_ALL_CNT + 0x20]
+ __attribute__ ((aligned(32)));
+static char buf_pool[TX_BUF_ALLOC * TX_DESC_CNT + 4];
+
+/* For module input parameter */
+static int mode = 8;
+
+/* function declaration -- */
+static int uli526x_start_xmit(struct eth_device *dev,
+ volatile void *packet, int length);
+static const struct ethtool_ops netdev_ethtool_ops;
+static u16 read_srom_word(long, int);
+static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long);
+static void allocate_rx_buffer(struct uli526x_board_info *);
+static void update_cr6(u32, unsigned long);
+static u16 phy_read(unsigned long, u8, u8, u32);
+static u16 phy_readby_cr10(unsigned long, u8, u8);
+static void phy_write(unsigned long, u8, u8, u16, u32);
+static void phy_writeby_cr10(unsigned long, u8, u8, u16);
+static void phy_write_1bit(unsigned long, u32, u32);
+static u16 phy_read_1bit(unsigned long, u32);
+static int uli526x_rx_packet(struct eth_device *);
+static void uli526x_free_tx_pkt(struct eth_device *,
+ struct uli526x_board_info *);
+static void uli526x_reuse_buf(struct rx_desc *);
+static void uli526x_init(struct eth_device *);
+static void uli526x_set_phyxcer(struct uli526x_board_info *);
+
+
+static int uli526x_init_one(struct eth_device *, bd_t *);
+static void uli526x_disable(struct eth_device *);
+static void set_mac_addr(struct eth_device *);
+
+static struct pci_device_id uli526x_pci_tbl[] = {
+ { ULI_VENDOR_ID, ULI5261_DEVICE_ID}, /* 5261 device */
+ { ULI_VENDOR_ID, ULI5263_DEVICE_ID}, /* 5263 device */
+ {}
+};
+
+/* ULI526X network board routine */
+
+/*
+ * Search ULI526X board, register it
+ */
+
+int uli526x_initialize(bd_t *bis)
+{
+ pci_dev_t devno;
+ int card_number = 0;
+ struct eth_device *dev;
+ struct uli526x_board_info *db; /* board information structure */
+
+ u32 iobase;
+ int idx = 0;
+
+ while (1) {
+ /* Find PCI device */
+ devno = pci_find_devices(uli526x_pci_tbl, idx++);
+ if (devno < 0)
+ break;
+
+ pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase);
+ iobase &= ~0xf;
+
+ dev = (struct eth_device *)malloc(sizeof *dev);
+ sprintf(dev->name, "uli526x#%d\n", card_number);
+ db = (struct uli526x_board_info *)
+ malloc(sizeof(struct uli526x_board_info));
+
+ dev->priv = db;
+ db->pdev = devno;
+ dev->iobase = iobase;
+
+ dev->init = uli526x_init_one;
+ dev->halt = uli526x_disable;
+ dev->send = uli526x_start_xmit;
+ dev->recv = uli526x_rx_packet;
+
+ /* init db */
+ db->ioaddr = dev->iobase;
+ /* get chip id */
+
+ pci_read_config_dword(devno, PCI_VENDOR_ID, &db->chip_id);
+#ifdef DEBUG
+ printf("uli526x: uli526x @0x%x\n", iobase);
+ printf("uli526x: chip_id%x\n", db->chip_id);
+#endif
+ eth_register(dev);
+ card_number++;
+ pci_write_config_byte(devno, PCI_LATENCY_TIMER, 0x20);
+ udelay(10 * 1000);
+ }
+ return card_number;
+}
+
+static int uli526x_init_one(struct eth_device *dev, bd_t *bis)
+{
+
+ struct uli526x_board_info *db = dev->priv;
+ int i;
+
+ switch (mode) {
+ case ULI526X_10MHF:
+ case ULI526X_100MHF:
+ case ULI526X_10MFD:
+ case ULI526X_100MFD:
+ uli526x_media_mode = mode;
+ break;
+ default:
+ uli526x_media_mode = ULI526X_AUTO;
+ break;
+ }
+
+ /* Allocate Tx/Rx descriptor memory */
+ db->desc_pool_ptr = (uchar *)&desc_pool_array[0];
+ db->desc_pool_dma_ptr = (dma_addr_t)&desc_pool_array[0];
+ if (db->desc_pool_ptr == NULL)
+ return 0;
+
+ db->buf_pool_ptr = &buf_pool[0];
+ db->buf_pool_dma_ptr = (dma_addr_t)&buf_pool[0];
+ if (db->buf_pool_ptr == NULL)
+ return 0;
+
+ db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr;
+ db->first_tx_desc_dma = db->desc_pool_dma_ptr;
+
+ db->buf_pool_start = db->buf_pool_ptr;
+ db->buf_pool_dma_start = db->buf_pool_dma_ptr;
+
+#ifdef DEBUG
+ printf("%s(): db->ioaddr= 0x%x\n",
+ __FUNCTION__, db->ioaddr);
+ printf("%s(): media_mode= 0x%x\n",
+ __FUNCTION__, uli526x_media_mode);
+ printf("%s(): db->desc_pool_ptr= 0x%x\n",
+ __FUNCTION__, db->desc_pool_ptr);
+ printf("%s(): db->desc_pool_dma_ptr= 0x%x\n",
+ __FUNCTION__, db->desc_pool_dma_ptr);
+ printf("%s(): db->buf_pool_ptr= 0x%x\n",
+ __FUNCTION__, db->buf_pool_ptr);
+ printf("%s(): db->buf_pool_dma_ptr= 0x%x\n",
+ __FUNCTION__, db->buf_pool_dma_ptr);
+#endif
+
+ /* read 64 word srom data */
+ for (i = 0; i < 64; i++)
+ ((u16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db->ioaddr,
+ i));
+
+ /* Set Node address */
+ if (((u16 *) db->srom)[0] == 0xffff || ((u16 *) db->srom)[0] == 0)
+ /* SROM absent, so write MAC address to ID Table */
+ set_mac_addr(dev);
+ else { /*Exist SROM*/
+ for (i = 0; i < 6; i++)
+ dev->enetaddr[i] = db->srom[20 + i];
+ }
+#ifdef DEBUG
+ for (i = 0; i < 6; i++)
+ printf("%c%02x", i ? ':' : ' ', dev->enetaddr[i]);
+#endif
+ db->PHY_reg4 = 0x1e0;
+
+ /* system variable init */
+ db->cr6_data = CR6_DEFAULT ;
+ db->cr6_data |= ULI526X_TXTH_256;
+ db->cr0_data = CR0_DEFAULT;
+ uli526x_init(dev);
+ return 1;
+}
+
+static void uli526x_disable(struct eth_device *dev)
+{
+#ifdef DEBUG
+ printf("uli526x_disable\n");
+#endif
+ struct uli526x_board_info *db = dev->priv;
+
+ if (!((inl(db->ioaddr + DCR12)) & 0x8)) {
+ /* Reset & stop ULI526X board */
+ outl(ULI526X_RESET, db->ioaddr + DCR0);
+ udelay(5);
+ phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id);
+
+ /* reset the board */
+ db->cr6_data &= ~(CR6_RXSC | CR6_TXSC); /* Disable Tx/Rx */
+ update_cr6(db->cr6_data, dev->iobase);
+ outl(0, dev->iobase + DCR7); /* Disable Interrupt */
+ outl(inl(dev->iobase + DCR5), dev->iobase + DCR5);
+ }
+}
+
+/* Initialize ULI526X board
+ * Reset ULI526X board
+ * Initialize TX/Rx descriptor chain structure
+ * Send the set-up frame
+ * Enable Tx/Rx machine
+ */
+
+static void uli526x_init(struct eth_device *dev)
+{
+
+ struct uli526x_board_info *db = dev->priv;
+ u8 phy_tmp;
+ u16 phy_value;
+ u16 phy_reg_reset;
+
+ /* Reset M526x MAC controller */
+ outl(ULI526X_RESET, db->ioaddr + DCR0); /* RESET MAC */
+ udelay(100);
+ outl(db->cr0_data, db->ioaddr + DCR0);
+ udelay(5);
+
+ /* Phy addr : In some boards,M5261/M5263 phy address != 1 */
+ db->phy_addr = 1;
+ db->tx_packet_cnt = 0;
+ for (phy_tmp = 0; phy_tmp < 32; phy_tmp++) {
+ /* peer add */
+ phy_value = phy_read(db->ioaddr, phy_tmp, 3, db->chip_id);
+ if (phy_value != 0xffff && phy_value != 0) {
+ db->phy_addr = phy_tmp;
+ break;
+ }
+ }
+
+#ifdef DEBUG
+ printf("%s(): db->ioaddr= 0x%x\n", __FUNCTION__, db->ioaddr);
+ printf("%s(): db->phy_addr= 0x%x\n", __FUNCTION__, db->phy_addr);
+#endif
+ if (phy_tmp == 32)
+ printf("Can not find the phy address!!!");
+
+ /* Parser SROM and media mode */
+ db->media_mode = uli526x_media_mode;
+
+ if (!(inl(db->ioaddr + DCR12) & 0x8)) {
+ /* Phyxcer capability setting */
+ phy_reg_reset = phy_read(db->ioaddr,
+ db->phy_addr, 0, db->chip_id);
+ phy_reg_reset = (phy_reg_reset | 0x8000);
+ phy_write(db->ioaddr, db->phy_addr, 0,
+ phy_reg_reset, db->chip_id);
+ udelay(500);
+
+ /* Process Phyxcer Media Mode */
+ uli526x_set_phyxcer(db);
+ }
+ /* Media Mode Process */
+ if (!(db->media_mode & ULI526X_AUTO))
+ db->op_mode = db->media_mode; /* Force Mode */
+
+ /* Initialize Transmit/Receive decriptor and CR3/4 */
+ uli526x_descriptor_init(db, db->ioaddr);
+
+ /* Init CR6 to program M526X operation */
+ update_cr6(db->cr6_data, db->ioaddr);
+
+ /* Init CR7, interrupt active bit */
+ db->cr7_data = CR7_DEFAULT;
+ outl(db->cr7_data, db->ioaddr + DCR7);
+
+ /* Init CR15, Tx jabber and Rx watchdog timer */
+ outl(db->cr15_data, db->ioaddr + DCR15);
+
+ /* Enable ULI526X Tx/Rx function */
+ db->cr6_data |= CR6_RXSC | CR6_TXSC;
+ update_cr6(db->cr6_data, db->ioaddr);
+ while (!(inl(db->ioaddr + DCR12) & 0x8))
+ udelay(10);
+}
+
+/*
+ * Hardware start transmission.
+ * Send a packet to media from the upper layer.
+ */
+
+static int uli526x_start_xmit(struct eth_device *dev,
+ volatile void *packet, int length)
+{
+ struct uli526x_board_info *db = dev->priv;
+ struct tx_desc *txptr;
+ unsigned int len = length;
+ /* Too large packet check */
+ if (len > MAX_PACKET_SIZE) {
+ printf(": big packet = %d\n", len);
+ return 0;
+ }
+
+ /* No Tx resource check, it never happen nromally */
+ if (db->tx_packet_cnt >= TX_FREE_DESC_CNT) {
+ printf("No Tx resource %ld\n", db->tx_packet_cnt);
+ return 0;
+ }
+
+ /* Disable NIC interrupt */
+ outl(0, dev->iobase + DCR7);
+
+ /* transmit this packet */
+ txptr = db->tx_insert_ptr;
+ memcpy((char *)txptr->tx_buf_ptr, (char *)packet, (int)length);
+ txptr->tdes1 = cpu_to_le32(0xe1000000 | length);
+
+ /* Point to next transmit free descriptor */
+ db->tx_insert_ptr = txptr->next_tx_desc;
+
+ /* Transmit Packet Process */
+ if ((db->tx_packet_cnt < TX_DESC_CNT)) {
+ txptr->tdes0 = cpu_to_le32(0x80000000); /* Set owner bit */
+ db->tx_packet_cnt++; /* Ready to send */
+ outl(0x1, dev->iobase + DCR1); /* Issue Tx polling */
+ }
+
+ /* Got ULI526X status */
+ db->cr5_data = inl(db->ioaddr + DCR5);
+ outl(db->cr5_data, db->ioaddr + DCR5);
+
+#ifdef TX_DEBUG
+ printf("%s(): length = 0x%x\n", __FUNCTION__, length);
+ printf("%s(): cr5_data=%x\n", __FUNCTION__, db->cr5_data);
+#endif
+
+ outl(db->cr7_data, dev->iobase + DCR7);
+ uli526x_free_tx_pkt(dev, db);
+
+ return length;
+}
+
+/*
+ * Free TX resource after TX complete
+ */
+
+static void uli526x_free_tx_pkt(struct eth_device *dev,
+ struct uli526x_board_info *db)
+{
+ struct tx_desc *txptr;
+ u32 tdes0;
+
+ txptr = db->tx_remove_ptr;
+ while (db->tx_packet_cnt) {
+ tdes0 = le32_to_cpu(txptr->tdes0);
+ /* printf(DRV_NAME ": tdes0=%x\n", tdes0); */
+ if (tdes0 & 0x80000000)
+ break;
+
+ /* A packet sent completed */
+ db->tx_packet_cnt--;
+
+ if (tdes0 != 0x7fffffff) {
+#ifdef TX_DEBUG
+ printf("%s()tdes0=%x\n", __FUNCTION__, tdes0);
+#endif
+ if (tdes0 & TDES0_ERR_MASK) {
+ if (tdes0 & 0x0002) { /* UnderRun */
+ if (!(db->cr6_data & CR6_SFT)) {
+ db->cr6_data = db->cr6_data |
+ CR6_SFT;
+ update_cr6(db->cr6_data,
+ db->ioaddr);
+ }
+ }
+ }
+ }
+
+ txptr = txptr->next_tx_desc;
+ }/* End of while */
+
+ /* Update TX remove pointer to next */
+ db->tx_remove_ptr = txptr;
+}
+
+
+/*
+ * Receive the come packet and pass to upper layer
+ */
+
+static int uli526x_rx_packet(struct eth_device *dev)
+{
+ struct uli526x_board_info *db = dev->priv;
+ struct rx_desc *rxptr;
+ int rxlen = 0;
+ u32 rdes0;
+
+ rxptr = db->rx_ready_ptr;
+
+ rdes0 = le32_to_cpu(rxptr->rdes0);
+#ifdef RX_DEBUG
+ printf("%s(): rxptr->rdes0=%x:%x\n", __FUNCTION__, rxptr->rdes0);
+#endif
+ if (!(rdes0 & 0x80000000)) { /* packet owner check */
+ if ((rdes0 & 0x300) != 0x300) {
+ /* A packet without First/Last flag */
+ /* reuse this buf */
+ printf("A packet without First/Last flag");
+ uli526x_reuse_buf(rxptr);
+ } else {
+ /* A packet with First/Last flag */
+ rxlen = ((rdes0 >> 16) & 0x3fff) - 4;
+#ifdef RX_DEBUG
+ printf("%s(): rxlen =%x\n", __FUNCTION__, rxlen);
+#endif
+ /* error summary bit check */
+ if (rdes0 & 0x8000) {
+ /* This is a error packet */
+ printf("Eroor: rdes0: %lx\n", rdes0);
+ }
+
+ if (!(rdes0 & 0x8000) ||
+ ((db->cr6_data & CR6_PM) && (rxlen > 6))) {
+
+#ifdef RX_DEBUG
+ printf("%s(): rx_skb_ptr =%x\n",
+ __FUNCTION__, rxptr->rx_buf_ptr);
+ printf("%s(): rxlen =%x\n",
+ __FUNCTION__, rxlen);
+
+ printf("%s(): buf addr =%x\n",
+ __FUNCTION__, rxptr->rx_buf_ptr);
+ printf("%s(): rxlen =%x\n",
+ __FUNCTION__, rxlen);
+ int i;
+ for (i = 0; i < 0x20; i++)
+ printf("%s(): data[%x] =%x\n",
+ __FUNCTION__, i, rxptr->rx_buf_ptr[i]);
+#endif
+
+ NetReceive(rxptr->rx_buf_ptr, rxlen);
+ uli526x_reuse_buf(rxptr);
+
+ } else {
+ /* Reuse SKB buffer when the packet is error */
+ printf("Reuse buffer, rdes0");
+ uli526x_reuse_buf(rxptr);
+ }
+ }
+
+ rxptr = rxptr->next_rx_desc;
+ }
+
+ db->rx_ready_ptr = rxptr;
+ return rxlen;
+}
+
+/*
+ * Reuse the RX buffer
+ */
+
+static void uli526x_reuse_buf(struct rx_desc *rxptr)
+{
+
+ if (!(rxptr->rdes0 & cpu_to_le32(0x80000000)))
+ rxptr->rdes0 = cpu_to_le32(0x80000000);
+ else
+ printf("Buffer reuse method error");
+}
+/*
+ * Initialize transmit/Receive descriptor
+ * Using Chain structure, and allocate Tx/Rx buffer
+ */
+
+static void uli526x_descriptor_init(struct uli526x_board_info *db,
+ unsigned long ioaddr)
+{
+ struct tx_desc *tmp_tx;
+ struct rx_desc *tmp_rx;
+ unsigned char *tmp_buf;
+ dma_addr_t tmp_tx_dma, tmp_rx_dma;
+ dma_addr_t tmp_buf_dma;
+ int i;
+ /* tx descriptor start pointer */
+ db->tx_insert_ptr = db->first_tx_desc;
+ db->tx_remove_ptr = db->first_tx_desc;
+
+ outl(db->first_tx_desc_dma, ioaddr + DCR4); /* TX DESC address */
+
+ /* rx descriptor start pointer */
+ db->first_rx_desc = (void *)db->first_tx_desc +
+ sizeof(struct tx_desc) * TX_DESC_CNT;
+ db->first_rx_desc_dma = db->first_tx_desc_dma +
+ sizeof(struct tx_desc) * TX_DESC_CNT;
+ db->rx_ready_ptr = db->first_rx_desc;
+ outl(db->first_rx_desc_dma, ioaddr + DCR3); /* RX DESC address */
+#ifdef DEBUG
+ printf("%s(): db->first_tx_desc= 0x%x\n",
+ __FUNCTION__, db->first_tx_desc);
+ printf("%s(): db->first_rx_desc_dma= 0x%x\n",
+ __FUNCTION__, db->first_rx_desc_dma);
+#endif
+ /* Init Transmit chain */
+ tmp_buf = db->buf_pool_start;
+ tmp_buf_dma = db->buf_pool_dma_start;
+ tmp_tx_dma = db->first_tx_desc_dma;
+ for (tmp_tx = db->first_tx_desc, i = 0;
+ i < TX_DESC_CNT; i++, tmp_tx++) {
+ tmp_tx->tx_buf_ptr = tmp_buf;
+ tmp_tx->tdes0 = cpu_to_le32(0);
+ tmp_tx->tdes1 = cpu_to_le32(0x81000000); /* IC, chain */
+ tmp_tx->tdes2 = cpu_to_le32(tmp_buf_dma);
+ tmp_tx_dma += sizeof(struct tx_desc);
+ tmp_tx->tdes3 = cpu_to_le32(tmp_tx_dma);
+ tmp_tx->next_tx_desc = tmp_tx + 1;
+ tmp_buf = tmp_buf + TX_BUF_ALLOC;
+ tmp_buf_dma = tmp_buf_dma + TX_BUF_ALLOC;
+ }
+ (--tmp_tx)->tdes3 = cpu_to_le32(db->first_tx_desc_dma);
+ tmp_tx->next_tx_desc = db->first_tx_desc;
+
+ /* Init Receive descriptor chain */
+ tmp_rx_dma = db->first_rx_desc_dma;
+ for (tmp_rx = db->first_rx_desc, i = 0; i < RX_DESC_CNT;
+ i++, tmp_rx++) {
+ tmp_rx->rdes0 = cpu_to_le32(0);
+ tmp_rx->rdes1 = cpu_to_le32(0x01000600);
+ tmp_rx_dma += sizeof(struct rx_desc);
+ tmp_rx->rdes3 = cpu_to_le32(tmp_rx_dma);
+ tmp_rx->next_rx_desc = tmp_rx + 1;
+ }
+ (--tmp_rx)->rdes3 = cpu_to_le32(db->first_rx_desc_dma);
+ tmp_rx->next_rx_desc = db->first_rx_desc;
+
+ /* pre-allocate Rx buffer */
+ allocate_rx_buffer(db);
+}
+
+/*
+ * Update CR6 value
+ * Firstly stop ULI526X, then written value and start
+ */
+
+static void update_cr6(u32 cr6_data, unsigned long ioaddr)
+{
+
+ outl(cr6_data, ioaddr + DCR6);
+ udelay(5);
+}
+
+/*
+ * Allocate rx buffer,
+ */
+
+static void allocate_rx_buffer(struct uli526x_board_info *db)
+{
+ int index;
+ struct rx_desc *rxptr;
+ rxptr = db->first_rx_desc;
+ u32 addr;
+
+ for (index = 0; index < RX_DESC_CNT; index++) {
+ addr = (u32)NetRxPackets[index];
+ addr += (16 - (addr & 15));
+ rxptr->rx_buf_ptr = (char *) addr;
+ rxptr->rdes2 = cpu_to_le32(addr);
+ rxptr->rdes0 = cpu_to_le32(0x80000000);
+#ifdef DEBUG
+ printf("%s(): Number 0x%x:\n", __FUNCTION__, index);
+ printf("%s(): addr 0x%x:\n", __FUNCTION__, addr);
+ printf("%s(): rxptr address = 0x%x\n", __FUNCTION__, rxptr);
+ printf("%s(): rxptr buf address = 0x%x\n", \
+ __FUNCTION__, rxptr->rx_buf_ptr);
+ printf("%s(): rdes2 = 0x%x\n", __FUNCTION__, rxptr->rdes2);
+#endif
+ rxptr = rxptr->next_rx_desc;
+ }
+}
+
+/*
+ * Read one word data from the serial ROM
+ */
+
+static u16 read_srom_word(long ioaddr, int offset)
+{
+ int i;
+ u16 srom_data = 0;
+ long cr9_ioaddr = ioaddr + DCR9;
+
+ outl(CR9_SROM_READ, cr9_ioaddr);
+ outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+
+ /* Send the Read Command 110b */
+ SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
+ SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);
+ SROM_CLK_WRITE(SROM_DATA_0, cr9_ioaddr);
+
+ /* Send the offset */
+ for (i = 5; i >= 0; i--) {
+ srom_data = (offset & (1 << i)) ? SROM_DATA_1 : SROM_DATA_0;
+ SROM_CLK_WRITE(srom_data, cr9_ioaddr);
+ }
+
+ outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+
+ for (i = 16; i > 0; i--) {
+ outl(CR9_SROM_READ | CR9_SRCS | CR9_SRCLK, cr9_ioaddr);
+ udelay(5);
+ srom_data = (srom_data << 1) | ((inl(cr9_ioaddr) & CR9_CRDOUT)
+ ? 1 : 0);
+ outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);
+ udelay(5);
+ }
+
+ outl(CR9_SROM_READ, cr9_ioaddr);
+ return srom_data;
+}
+
+/*
+ * Set 10/100 phyxcer capability
+ * AUTO mode : phyxcer register4 is NIC capability
+ * Force mode: phyxcer register4 is the force media
+ */
+
+static void uli526x_set_phyxcer(struct uli526x_board_info *db)
+{
+ u16 phy_reg;
+
+ /* Phyxcer capability setting */
+ phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x01e0;
+
+ if (db->media_mode & ULI526X_AUTO) {
+ /* AUTO Mode */
+ phy_reg |= db->PHY_reg4;
+ } else {
+ /* Force Mode */
+ switch (db->media_mode) {
+ case ULI526X_10MHF: phy_reg |= 0x20; break;
+ case ULI526X_10MFD: phy_reg |= 0x40; break;
+ case ULI526X_100MHF: phy_reg |= 0x80; break;
+ case ULI526X_100MFD: phy_reg |= 0x100; break;
+ }
+
+ }
+
+ /* Write new capability to Phyxcer Reg4 */
+ if (!(phy_reg & 0x01e0)) {
+ phy_reg |= db->PHY_reg4;
+ db->media_mode |= ULI526X_AUTO;
+ }
+ phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id);
+
+ /* Restart Auto-Negotiation */
+ phy_write(db->ioaddr, db->phy_addr, 0, 0x1200, db->chip_id);
+ udelay(50);
+}
+
+/*
+ * Write a word to Phy register
+ */
+
+static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset,
+ u16 phy_data, u32 chip_id)
+{
+ u16 i;
+ unsigned long ioaddr;
+
+ if (chip_id == PCI_ULI5263_ID) {
+ phy_writeby_cr10(iobase, phy_addr, offset, phy_data);
+ return;
+ }
+ /* M5261/M5263 Chip */
+ ioaddr = iobase + DCR9;
+
+ /* Send 33 synchronization clock to Phy controller */
+ for (i = 0; i < 35; i++)
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send start command(01) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send write command(01) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send Phy address */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr, phy_addr & i ?
+ PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+ /* Send register address */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr, offset & i ?
+ PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+ /* written trasnition */
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+
+ /* Write a word data to PHY controller */
+ for (i = 0x8000; i > 0; i >>= 1)
+ phy_write_1bit(ioaddr, phy_data & i ?
+ PHY_DATA_1 : PHY_DATA_0, chip_id);
+}
+
+/*
+ * Read a word data from phy register
+ */
+
+static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id)
+{
+ int i;
+ u16 phy_data;
+ unsigned long ioaddr;
+
+ if (chip_id == PCI_ULI5263_ID)
+ return phy_readby_cr10(iobase, phy_addr, offset);
+ /* M5261/M5263 Chip */
+ ioaddr = iobase + DCR9;
+
+ /* Send 33 synchronization clock to Phy controller */
+ for (i = 0; i < 35; i++)
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send start command(01) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+
+ /* Send read command(10) to Phy */
+ phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
+ phy_write_1bit(ioaddr, PHY_DATA_0, chip_id);
+
+ /* Send Phy address */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr, phy_addr & i ?
+ PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+ /* Send register address */
+ for (i = 0x10; i > 0; i = i >> 1)
+ phy_write_1bit(ioaddr, offset & i ?
+ PHY_DATA_1 : PHY_DATA_0, chip_id);
+
+ /* Skip transition state */
+ phy_read_1bit(ioaddr, chip_id);
+
+ /* read 16bit data */
+ for (phy_data = 0, i = 0; i < 16; i++) {
+ phy_data <<= 1;
+ phy_data |= phy_read_1bit(ioaddr, chip_id);
+ }
+
+ return phy_data;
+}
+
+static u16 phy_readby_cr10(unsigned long iobase, u8 phy_addr, u8 offset)
+{
+ unsigned long ioaddr, cr10_value;
+
+ ioaddr = iobase + DCR10;
+ cr10_value = phy_addr;
+ cr10_value = (cr10_value<<5) + offset;
+ cr10_value = (cr10_value<<16) + 0x08000000;
+ outl(cr10_value, ioaddr);
+ udelay(1);
+ while (1) {
+ cr10_value = inl(ioaddr);
+ if (cr10_value & 0x10000000)
+ break;
+ }
+ return (cr10_value&0x0ffff);
+}
+
+static void phy_writeby_cr10(unsigned long iobase, u8 phy_addr,
+ u8 offset, u16 phy_data)
+{
+ unsigned long ioaddr, cr10_value;
+
+ ioaddr = iobase + DCR10;
+ cr10_value = phy_addr;
+ cr10_value = (cr10_value<<5) + offset;
+ cr10_value = (cr10_value<<16) + 0x04000000 + phy_data;
+ outl(cr10_value, ioaddr);
+ udelay(1);
+}
+/*
+ * Write one bit data to Phy Controller
+ */
+
+static void phy_write_1bit(unsigned long ioaddr, u32 phy_data, u32 chip_id)
+{
+ outl(phy_data , ioaddr); /* MII Clock Low */
+ udelay(1);
+ outl(phy_data | MDCLKH, ioaddr); /* MII Clock High */
+ udelay(1);
+ outl(phy_data , ioaddr); /* MII Clock Low */
+ udelay(1);
+}
+
+/*
+ * Read one bit phy data from PHY controller
+ */
+
+static u16 phy_read_1bit(unsigned long ioaddr, u32 chip_id)
+{
+ u16 phy_data;
+
+ outl(0x50000 , ioaddr);
+ udelay(1);
+ phy_data = (inl(ioaddr) >> 19) & 0x1;
+ outl(0x40000 , ioaddr);
+ udelay(1);
+
+ return phy_data;
+}
+
+/*
+ * Set MAC address to ID Table
+ */
+
+static void set_mac_addr(struct eth_device *dev)
+{
+ int i;
+ u16 addr;
+ struct uli526x_board_info *db = dev->priv;
+ outl(0x10000, db->ioaddr + DCR0); /* Diagnosis mode */
+ /* Reset dianostic pointer port */
+ outl(0x1c0, db->ioaddr + DCR13);
+ outl(0, db->ioaddr + DCR14); /* Clear reset port */
+ outl(0x10, db->ioaddr + DCR14); /* Reset ID Table pointer */
+ outl(0, db->ioaddr + DCR14); /* Clear reset port */
+ outl(0, db->ioaddr + DCR13); /* Clear CR13 */
+ /* Select ID Table access port */
+ outl(0x1b0, db->ioaddr + DCR13);
+ /* Read MAC address from CR14 */
+ for (i = 0; i < 3; i++) {
+ addr = dev->enetaddr[2 * i] | (dev->enetaddr[2 * i + 1] << 8);
+ outl(addr, db->ioaddr + DCR14);
+ }
+ /* write end */
+ outl(0, db->ioaddr + DCR13); /* Clear CR13 */
+ outl(0, db->ioaddr + DCR0); /* Clear CR0 */
+ udelay(10);
+ return;
+}
+#endif
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
new file mode 100644
index 0000000..fe45839
--- /dev/null
+++ b/drivers/pci/Makefile
@@ -0,0 +1,51 @@
+#
+# (C) Copyright 2000-2007
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB := $(obj)libpci.a
+
+COBJS-y += fsl_pci_init.o
+COBJS-y += pci.o
+COBJS-y += pci_auto.o
+COBJS-y += pci_indirect.o
+COBJS-y += tsi108_pci.o
+COBJS-y += w83c553f.o
+
+COBJS := $(COBJS-y)
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c
index 1e77884..68e45e1 100644
--- a/drivers/fsl_pci_init.c
+++ b/drivers/pci/fsl_pci_init.c
@@ -112,6 +112,29 @@ fsl_pci_init(struct pci_controller *hose)
pci_hose_read_config_word(hose, dev, PCI_LTSSM, &ltssm);
enabled = ltssm >= PCI_LTSSM_L0;
+#ifdef CONFIG_FSL_PCIE_RESET
+ if (ltssm == 1) {
+ int i;
+ debug("....PCIe link error. "
+ "LTSSM=0x%02x.", ltssm);
+ pci->pdb_stat |= 0x08000000; /* assert PCIe reset */
+ temp32 = pci->pdb_stat;
+ udelay(100);
+ debug(" Asserting PCIe reset @%x = %x\n",
+ &pci->pdb_stat, pci->pdb_stat);
+ pci->pdb_stat &= ~0x08000000; /* clear reset */
+ asm("sync;isync");
+ for (i=0; i<100 && ltssm < PCI_LTSSM_L0; i++) {
+ pci_hose_read_config_word(hose, dev, PCI_LTSSM,
+ &ltssm);
+ udelay(1000);
+ debug("....PCIe link error. "
+ "LTSSM=0x%02x.\n", ltssm);
+ }
+ enabled = ltssm >= PCI_LTSSM_L0;
+ }
+#endif
+
if (!enabled) {
debug("....PCIE link error. Skipping scan."
"LTSSM=0x%02x\n", ltssm);
diff --git a/drivers/pci.c b/drivers/pci/pci.c
index 50ca6b0..50ca6b0 100644
--- a/drivers/pci.c
+++ b/drivers/pci/pci.c
diff --git a/drivers/pci_auto.c b/drivers/pci/pci_auto.c
index acfda83..acfda83 100644
--- a/drivers/pci_auto.c
+++ b/drivers/pci/pci_auto.c
diff --git a/drivers/pci_indirect.c b/drivers/pci/pci_indirect.c
index a8220fb..a8220fb 100644
--- a/drivers/pci_indirect.c
+++ b/drivers/pci/pci_indirect.c
diff --git a/drivers/tsi108_pci.c b/drivers/pci/tsi108_pci.c
index 9f606df..d5f11e4 100644
--- a/drivers/tsi108_pci.c
+++ b/drivers/pci/tsi108_pci.c
@@ -33,6 +33,9 @@
#include <pci.h>
#include <asm/io.h>
#include <tsi108.h>
+#ifdef CONFIG_OF_FLAT_TREE
+#include <ft_build.h>
+#endif
struct pci_controller local_hose;
diff --git a/drivers/w83c553f.c b/drivers/pci/w83c553f.c
index 5d82ed4..5d82ed4 100644
--- a/drivers/w83c553f.c
+++ b/drivers/pci/w83c553f.c
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
new file mode 100644
index 0000000..bba1ab8
--- /dev/null
+++ b/drivers/pcmcia/Makefile
@@ -0,0 +1,51 @@
+#
+# (C) Copyright 2000-2007
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB := $(obj)libpcmcia.a
+
+COBJS-y += mpc8xx_pcmcia.o
+COBJS-y += pxa_pcmcia.o
+COBJS-y += rpx_pcmcia.o
+COBJS-y += ti_pci1410a.o
+COBJS-y += tqm8xx_pcmcia.o
+COBJS-y += marubun_pcmcia.o
+
+COBJS := $(COBJS-y)
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/i82365.c b/drivers/pcmcia/i82365.c
index a40fcf4..a40fcf4 100644
--- a/drivers/i82365.c
+++ b/drivers/pcmcia/i82365.c
diff --git a/drivers/pcmcia/marubun_pcmcia.c b/drivers/pcmcia/marubun_pcmcia.c
new file mode 100644
index 0000000..7b112af
--- /dev/null
+++ b/drivers/pcmcia/marubun_pcmcia.c
@@ -0,0 +1,113 @@
+/*
+ * Marubun MR-SHPC-01 PCMCIA controller device driver
+ *
+ * (c) 2007 Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+ *
+ * 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
+ *
+ */
+
+#include <common.h>
+#include <config.h>
+#include <pcmcia.h>
+#include <asm/io.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
+#define CONFIG_PCMCIA
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_IDE)
+#define CONFIG_PCMCIA
+#endif
+
+#if defined(CONFIG_PCMCIA) \
+ && (defined(CONFIG_MARUBUN_PCCARD))
+
+/* MR-SHPC-01 register */
+#define MRSHPC_MODE (CFG_MARUBUN_MRSHPC + 4)
+#define MRSHPC_OPTION (CFG_MARUBUN_MRSHPC + 6)
+#define MRSHPC_CSR (CFG_MARUBUN_MRSHPC + 8)
+#define MRSHPC_ISR (CFG_MARUBUN_MRSHPC + 10)
+#define MRSHPC_ICR (CFG_MARUBUN_MRSHPC + 12)
+#define MRSHPC_CPWCR (CFG_MARUBUN_MRSHPC + 14)
+#define MRSHPC_MW0CR1 (CFG_MARUBUN_MRSHPC + 16)
+#define MRSHPC_MW1CR1 (CFG_MARUBUN_MRSHPC + 18)
+#define MRSHPC_IOWCR1 (CFG_MARUBUN_MRSHPC + 20)
+#define MRSHPC_MW0CR2 (CFG_MARUBUN_MRSHPC + 22)
+#define MRSHPC_MW1CR2 (CFG_MARUBUN_MRSHPC + 24)
+#define MRSHPC_IOWCR2 (CFG_MARUBUN_MRSHPC + 26)
+#define MRSHPC_CDCR (CFG_MARUBUN_MRSHPC + 28)
+#define MRSHPC_PCIC_INFO (CFG_MARUBUN_MRSHPC + 30)
+
+int pcmcia_on (void)
+{
+ printf("Enable PCMCIA " PCMCIA_SLOT_MSG "\n");
+
+ /* Init */
+ outw( 0x0000 , MRSHPC_MODE );
+
+ if ((inw(MRSHPC_CSR) & 0x000c) == 0){ /* if card detect is true */
+ if ((inw(MRSHPC_CSR) & 0x0080) == 0){
+ outw(0x0674 ,MRSHPC_CPWCR); /* Card Vcc is 3.3v? */
+ }else{
+ outw(0x0678 ,MRSHPC_CPWCR); /* Card Vcc is 5V */
+ }
+ udelay( 100000 ); /* wait for power on */
+ }else{
+ return 1;
+ }
+ /*
+ * PC-Card window open
+ * flag == COMMON/ATTRIBUTE/IO
+ */
+ /* common window open */
+ outw(0x8a84,MRSHPC_MW0CR1); /* window 0xb8400000 */
+ if ((inw(MRSHPC_CSR) & 0x4000) != 0)
+ outw(0x0b00,MRSHPC_MW0CR2); /* common mode & bus width 16bit SWAP = 1 */
+ else
+ outw(0x0300,MRSHPC_MW0CR2); /* common mode & bus width 16bit SWAP = 0 */
+
+ /* attribute window open */
+ outw(0x8a85,MRSHPC_MW1CR1); /* window 0xb8500000 */
+ if ((inw(MRSHPC_CSR) & 0x4000) != 0)
+ outw(0x0a00,MRSHPC_MW1CR2); /* attribute mode & bus width 16bit SWAP = 1 */
+ else
+ outw(0x0200,MRSHPC_MW1CR2); /* attribute mode & bus width 16bit SWAP = 0 */
+
+ /* I/O window open */
+ outw(0x8a86,MRSHPC_IOWCR1); /* I/O window 0xb8600000 */
+ outw(0x0008,MRSHPC_CDCR); /* I/O card mode */
+ if ((inw(MRSHPC_CSR) & 0x4000) != 0)
+ outw(0x0a00,MRSHPC_IOWCR2); /* bus width 16bit SWAP = 1 */
+ else
+ outw(0x0200,MRSHPC_IOWCR2); /* bus width 16bit SWAP = 0 */
+
+ outw(0x0000,MRSHPC_ISR);
+ outw(0x2000,MRSHPC_ICR);
+ outb(0x00,(CFG_MARUBUN_MW2 + 0x206));
+ outb(0x42,(CFG_MARUBUN_MW2 + 0x200));
+
+ return 0;
+}
+
+int pcmcia_off (void)
+{
+ printf ("Disable PCMCIA " PCMCIA_SLOT_MSG "\n");
+
+ return 0;
+}
+
+#endif /* CONFIG_MARUBUN_PCCARD */
diff --git a/drivers/mpc8xx_pcmcia.c b/drivers/pcmcia/mpc8xx_pcmcia.c
index 8a34cd3..8a34cd3 100644
--- a/drivers/mpc8xx_pcmcia.c
+++ b/drivers/pcmcia/mpc8xx_pcmcia.c
diff --git a/drivers/pxa_pcmcia.c b/drivers/pcmcia/pxa_pcmcia.c
index 6020e46..6020e46 100644
--- a/drivers/pxa_pcmcia.c
+++ b/drivers/pcmcia/pxa_pcmcia.c
diff --git a/drivers/rpx_pcmcia.c b/drivers/pcmcia/rpx_pcmcia.c
index c7c425b..c7c425b 100644
--- a/drivers/rpx_pcmcia.c
+++ b/drivers/pcmcia/rpx_pcmcia.c
diff --git a/drivers/ti_pci1410a.c b/drivers/pcmcia/ti_pci1410a.c
index 208ca50..208ca50 100644
--- a/drivers/ti_pci1410a.c
+++ b/drivers/pcmcia/ti_pci1410a.c
diff --git a/drivers/tqm8xx_pcmcia.c b/drivers/pcmcia/tqm8xx_pcmcia.c
index 132c7a5..132c7a5 100644
--- a/drivers/tqm8xx_pcmcia.c
+++ b/drivers/pcmcia/tqm8xx_pcmcia.c
diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c
index dc2765b..a27c12a 100644
--- a/drivers/qe/uec.c
+++ b/drivers/qe/uec.c
@@ -69,6 +69,25 @@ static uec_info_t eth2_uec_info = {
};
#endif
+#ifdef CONFIG_UEC_ETH3
+static uec_info_t eth3_uec_info = {
+ .uf_info = {
+ .ucc_num = CFG_UEC3_UCC_NUM,
+ .rx_clock = CFG_UEC3_RX_CLK,
+ .tx_clock = CFG_UEC3_TX_CLK,
+ .eth_type = CFG_UEC3_ETH_TYPE,
+ },
+ .num_threads_tx = UEC_NUM_OF_THREADS_4,
+ .num_threads_rx = UEC_NUM_OF_THREADS_4,
+ .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
+ .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
+ .tx_bd_ring_len = 16,
+ .rx_bd_ring_len = 16,
+ .phy_address = CFG_UEC3_PHY_ADDR,
+ .enet_interface = CFG_UEC3_INTERFACE_MODE,
+};
+#endif
+
static int uec_mac_enable(uec_private_t *uec, comm_dir_e mode)
{
uec_t *uec_regs;
@@ -1238,6 +1257,10 @@ int uec_initialize(int index)
#ifdef CONFIG_UEC_ETH2
uec_info = &eth2_uec_info;
#endif
+ } else if (index == 2) {
+#ifdef CONFIG_UEC_ETH3
+ uec_info = &eth3_uec_info;
+#endif
} else {
printf("%s: index is illegal.\n", __FUNCTION__);
return -EINVAL;
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
new file mode 100644
index 0000000..8c7f148
--- /dev/null
+++ b/drivers/rtc/Makefile
@@ -0,0 +1,73 @@
+#
+# (C) Copyright 2001-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+#CFLAGS += -DDEBUG
+
+LIB = $(obj)librtc.a
+
+COBJS-y += date.o
+COBJS-y += bf5xx_rtc.o
+COBJS-y += ds12887.o
+COBJS-y += ds1302.o
+COBJS-y += ds1306.o
+COBJS-y += ds1307.o
+COBJS-y += ds1337.o
+COBJS-y += ds1374.o
+COBJS-y += ds1556.o
+COBJS-y += ds164x.o
+COBJS-y += ds174x.o
+COBJS-y += ds3231.o
+COBJS-y += m41t11.o
+COBJS-y += m41t60.o
+COBJS-y += max6900.o
+COBJS-y += m48t35ax.o
+COBJS-y += mc146818.o
+COBJS-y += mk48t59.o
+COBJS-y += mpc5xxx.o
+COBJS-y += mpc8xx.o
+COBJS-y += pcf8563.o
+COBJS-y += s3c24x0_rtc.o
+COBJS-y += rs5c372.o
+COBJS-y += rx8025.o
+COBJS-y += mcfrtc.o
+COBJS-y += x1205.o
+
+COBJS := $(COBJS-y)
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/rtc/bf5xx_rtc.c b/drivers/rtc/bf5xx_rtc.c
new file mode 100644
index 0000000..8856bb9
--- /dev/null
+++ b/drivers/rtc/bf5xx_rtc.c
@@ -0,0 +1,143 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ * Real Time Clock interface of ADI21535 (Blackfin) for uCLinux
+ *
+ * Copyright (C) 2003 Motorola Corporation. All rights reserved.
+ * Richard Xiao (A2590C@email.mot.com)
+ *
+ * Copyright (C) 1996 Paul Gortmaker
+ *
+ *
+ * Based on other minimal char device drivers, like Alan's
+ * watchdog, Ted's random, etc. etc.
+ *
+ * 1.07 Paul Gortmaker.
+ * 1.08 Miquel van Smoorenburg: disallow certain things on the
+ * DEC Alpha as the CMOS clock is also used for other things.
+ * 1.09 Nikita Schmidt: epoch support and some Alpha cleanup.
+ * 1.09a Pete Zaitcev: Sun SPARC
+ * 1.09b Jeff Garzik: Modularize, init cleanup
+ * 1.09c Jeff Garzik: SMP cleanup
+ * 1.10 Paul Barton-Davis: add support for async I/O
+ * 1.10a Andrea Arcangeli: Alpha updates
+ * 1.10b Andrew Morton: SMP lock fix
+ * 1.10c Cesar Barros: SMP locking fixes and cleanup
+ * 1.10d Paul Gortmaker: delete paranoia check in rtc_exit
+ * 1.10e LG Soft India: Register access is different in BF533.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+
+#if defined(CONFIG_RTC_BFIN) && defined(CONFIG_CMD_DATE)
+
+#include <asm/blackfin.h>
+#include <asm/arch/bf5xx_rtc.h>
+
+void rtc_reset(void)
+{
+ return; /* nothing to do */
+}
+
+/* Wait for pending writes to complete */
+void wait_for_complete(void)
+{
+ while (!(*(volatile unsigned short *)RTC_ISTAT & 0x8000)) {
+ printf("");
+ }
+ *(volatile unsigned short *)RTC_ISTAT = 0x8000;
+}
+
+/* Enable the RTC prescaler enable register */
+void rtc_init()
+{
+ *(volatile unsigned short *)RTC_PREN = 0x1;
+ wait_for_complete();
+}
+
+/* Set the time. Get the time_in_secs which is the number of seconds since Jan 1970 and set the RTC registers
+ * based on this value.
+ */
+void rtc_set(struct rtc_time *tmp)
+{
+ unsigned long n_days_1970 = 0;
+ unsigned long n_secs_rem = 0;
+ unsigned long n_hrs = 0;
+ unsigned long n_mins = 0;
+ unsigned long n_secs = 0;
+ unsigned long time_in_secs;
+
+ if (tmp == NULL) {
+ printf("Error setting the date/time \n");
+ return;
+ }
+
+ time_in_secs =
+ mktime(tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_hour,
+ tmp->tm_min, tmp->tm_sec);
+
+ /* Compute no. of days since 1970 */
+ n_days_1970 = (unsigned long)(time_in_secs / (NUM_SECS_IN_DAY));
+
+ /* From the remining secs, compute the hrs(0-23), mins(0-59) and secs(0-59) */
+ n_secs_rem = (unsigned long)(time_in_secs % (NUM_SECS_IN_DAY));
+ n_hrs = n_secs_rem / (NUM_SECS_IN_HOUR);
+ n_secs_rem = n_secs_rem % (NUM_SECS_IN_HOUR);
+ n_mins = n_secs_rem / (NUM_SECS_IN_MIN);
+ n_secs = n_secs_rem % (NUM_SECS_IN_MIN);
+
+ /* Store the new time in the RTC_STAT register */
+ *(volatile unsigned long *)RTC_STAT =
+ ((n_days_1970 << DAY_BITS_OFF) | (n_hrs << HOUR_BITS_OFF) |
+ (n_mins << MIN_BITS_OFF) | (n_secs << SEC_BITS_OFF));
+
+ wait_for_complete();
+}
+
+/* Read the time from the RTC_STAT. time_in_seconds is seconds since Jan 1970 */
+void rtc_get(struct rtc_time *tmp)
+{
+ unsigned long cur_rtc_stat = 0;
+ unsigned long time_in_sec;
+ unsigned long tm_sec = 0, tm_min = 0, tm_hour = 0, tm_day = 0;
+
+ if (tmp == NULL) {
+ printf("Error getting the date/time \n");
+ return;
+ }
+
+ /* Read the RTC_STAT register */
+ cur_rtc_stat = *(volatile unsigned long *)RTC_STAT;
+
+ /* Get the secs (0-59), mins (0-59), hrs (0-23) and the days since Jan 1970 */
+ tm_sec = (cur_rtc_stat >> SEC_BITS_OFF) & 0x3f;
+ tm_min = (cur_rtc_stat >> MIN_BITS_OFF) & 0x3f;
+ tm_hour = (cur_rtc_stat >> HOUR_BITS_OFF) & 0x1f;
+ tm_day = (cur_rtc_stat >> DAY_BITS_OFF) & 0x7fff;
+
+ /* Calculate the total number of seconds since Jan 1970 */
+ time_in_sec = (tm_sec) +
+ MIN_TO_SECS(tm_min) + HRS_TO_SECS(tm_hour) + DAYS_TO_SECS(tm_day);
+ to_tm(time_in_sec, tmp);
+}
+#endif
diff --git a/drivers/rtc/date.c b/drivers/rtc/date.c
new file mode 100644
index 0000000..a83a723
--- /dev/null
+++ b/drivers/rtc/date.c
@@ -0,0 +1,156 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support for Philips PCF8563 RTC
+ */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+
+#if defined(CONFIG_CMD_DATE) || defined(CONFIG_TIMESTAMP)
+
+#define FEBRUARY 2
+#define STARTOFTIME 1970
+#define SECDAY 86400L
+#define SECYR (SECDAY * 365)
+#define leapyear(year) ((year) % 4 == 0)
+#define days_in_year(a) (leapyear(a) ? 366 : 365)
+#define days_in_month(a) (month_days[(a) - 1])
+
+static int month_days[12] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+/*
+ * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
+ */
+void GregorianDay(struct rtc_time * tm)
+{
+ int leapsToDate;
+ int lastYear;
+ int day;
+ int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
+
+ lastYear=tm->tm_year-1;
+
+ /*
+ * Number of leap corrections to apply up to end of last year
+ */
+ leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;
+
+ /*
+ * This year is a leap year if it is divisible by 4 except when it is
+ * divisible by 100 unless it is divisible by 400
+ *
+ * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be
+ */
+ if((tm->tm_year%4==0) &&
+ ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) &&
+ (tm->tm_mon>2)) {
+ /*
+ * We are past Feb. 29 in a leap year
+ */
+ day=1;
+ } else {
+ day=0;
+ }
+
+ day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday;
+
+ tm->tm_wday=day%7;
+}
+
+void to_tm(int tim, struct rtc_time * tm)
+{
+ register int i;
+ register long hms, day;
+
+ day = tim / SECDAY;
+ hms = tim % SECDAY;
+
+ /* Hours, minutes, seconds are easy */
+ tm->tm_hour = hms / 3600;
+ tm->tm_min = (hms % 3600) / 60;
+ tm->tm_sec = (hms % 3600) % 60;
+
+ /* Number of years in days */
+ for (i = STARTOFTIME; day >= days_in_year(i); i++) {
+ day -= days_in_year(i);
+ }
+ tm->tm_year = i;
+
+ /* Number of months in days left */
+ if (leapyear(tm->tm_year)) {
+ days_in_month(FEBRUARY) = 29;
+ }
+ for (i = 1; day >= days_in_month(i); i++) {
+ day -= days_in_month(i);
+ }
+ days_in_month(FEBRUARY) = 28;
+ tm->tm_mon = i;
+
+ /* Days are what is left over (+1) from all that. */
+ tm->tm_mday = day + 1;
+
+ /*
+ * Determine the day of week
+ */
+ GregorianDay(tm);
+}
+
+/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
+ * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
+ * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
+ *
+ * [For the Julian calendar (which was used in Russia before 1917,
+ * Britain & colonies before 1752, anywhere else before 1582,
+ * and is still in use by some communities) leave out the
+ * -year/100+year/400 terms, and add 10.]
+ *
+ * This algorithm was first published by Gauss (I think).
+ *
+ * WARNING: this function will overflow on 2106-02-07 06:28:16 on
+ * machines were long is 32-bit! (However, as time_t is signed, we
+ * will already get problems at other places on 2038-01-19 03:14:08)
+ */
+unsigned long
+mktime (unsigned int year, unsigned int mon,
+ unsigned int day, unsigned int hour,
+ unsigned int min, unsigned int sec)
+{
+ if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
+ mon += 12; /* Puts Feb last since it has leap day */
+ year -= 1;
+ }
+
+ return (((
+ (unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) +
+ year*365 - 719499
+ )*24 + hour /* now have hours */
+ )*60 + min /* now have minutes */
+ )*60 + sec; /* finally seconds */
+}
+
+#endif
diff --git a/drivers/rtc/ds12887.c b/drivers/rtc/ds12887.c
new file mode 100644
index 0000000..84fecf0
--- /dev/null
+++ b/drivers/rtc/ds12887.c
@@ -0,0 +1,238 @@
+/*
+ * (C) Copyright 2003
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support for the DS12887 RTC
+ */
+
+#undef RTC_DEBUG
+
+#include <common.h>
+#include <command.h>
+#include <config.h>
+#include <rtc.h>
+
+#if defined(CONFIG_RTC_DS12887) && defined(CONFIG_CMD_DATE)
+
+#define RTC_SECONDS 0x00
+#define RTC_SECONDS_ALARM 0x01
+#define RTC_MINUTES 0x02
+#define RTC_MINUTES_ALARM 0x03
+#define RTC_HOURS 0x04
+#define RTC_HOURS_ALARM 0x05
+#define RTC_DAY_OF_WEEK 0x06
+#define RTC_DATE_OF_MONTH 0x07
+#define RTC_MONTH 0x08
+#define RTC_YEAR 0x09
+#define RTC_CONTROL_A 0x0A
+#define RTC_CONTROL_B 0x0B
+#define RTC_CONTROL_C 0x0C
+#define RTC_CONTROL_D 0x0D
+
+#define RTC_CA_UIP 0x80
+#define RTC_CB_DM 0x04
+#define RTC_CB_24_12 0x02
+#define RTC_CB_SET 0x80
+
+#if defined(CONFIG_ATC)
+
+static uchar rtc_read (uchar reg)
+{
+ uchar val;
+
+ *(volatile unsigned char*)(RTC_PORT_ADDR) = reg;
+ __asm__ __volatile__ ("sync");
+
+ val = *(volatile unsigned char*)(RTC_PORT_DATA);
+ return (val);
+}
+
+static void rtc_write (uchar reg, uchar val)
+{
+ *(volatile unsigned char*)(RTC_PORT_ADDR) = reg;
+ __asm__ __volatile__ ("sync");
+
+ *(volatile unsigned char*)(RTC_PORT_DATA) = val;
+ __asm__ __volatile__ ("sync");
+}
+
+#else
+# error Board specific rtc access functions should be supplied
+#endif
+
+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));
+}
+
+/* ------------------------------------------------------------------------- */
+
+void rtc_get (struct rtc_time *tmp)
+{
+ uchar sec, min, hour, mday, wday, mon, year;
+
+ /* check if rtc is available for access */
+ while( rtc_read(RTC_CONTROL_A) & RTC_CA_UIP)
+ ;
+
+ sec = rtc_read(RTC_SECONDS);
+ min = rtc_read(RTC_MINUTES);
+ hour = rtc_read(RTC_HOURS);
+ mday = rtc_read(RTC_DATE_OF_MONTH);
+ wday = rtc_read(RTC_DAY_OF_WEEK);
+ mon = rtc_read(RTC_MONTH);
+ year = rtc_read(RTC_YEAR);
+
+#ifdef RTC_DEBUG
+ printf( "Get RTC year: %d; mon: %d; mday: %d; wday: %d; "
+ "hr: %d; min: %d; sec: %d\n",
+ year, mon, mday, wday, hour, min, sec );
+
+ printf ( "Alarms: hour: %02x min: %02x sec: %02x\n",
+ rtc_read (RTC_HOURS_ALARM),
+ rtc_read (RTC_MINUTES_ALARM),
+ rtc_read (RTC_SECONDS_ALARM) );
+#endif
+
+ if( !(rtc_read(RTC_CONTROL_B) & RTC_CB_DM))
+ { /* Information is in BCD format */
+printf(" Get: Convert BSD to BIN\n");
+ tmp->tm_sec = bcd2bin (sec & 0x7F);
+ tmp->tm_min = bcd2bin (min & 0x7F);
+ tmp->tm_hour = bcd2bin (hour & 0x3F);
+ tmp->tm_mday = bcd2bin (mday & 0x3F);
+ tmp->tm_mon = bcd2bin (mon & 0x1F);
+ tmp->tm_year = bcd2bin (year);
+ tmp->tm_wday = bcd2bin (wday & 0x07);
+ }
+else
+ {
+ tmp->tm_sec = sec & 0x7F;
+ tmp->tm_min = min & 0x7F;
+ tmp->tm_hour = hour & 0x3F;
+ tmp->tm_mday = mday & 0x3F;
+ tmp->tm_mon = mon & 0x1F;
+ tmp->tm_year = year;
+ tmp->tm_wday = wday & 0x07;
+ }
+
+
+ if(tmp->tm_year<70)
+ tmp->tm_year+=2000;
+ else
+ tmp->tm_year+=1900;
+
+ tmp->tm_yday = 0;
+ tmp->tm_isdst= 0;
+#ifdef RTC_DEBUG
+ printf ( "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);
+#endif
+}
+
+void rtc_set (struct rtc_time *tmp)
+{
+ uchar save_ctrl_b;
+ uchar sec, min, hour, mday, wday, mon, year;
+
+#ifdef RTC_DEBUG
+ printf ( "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);
+#endif
+
+ if( !(rtc_read(RTC_CONTROL_B) & RTC_CB_DM))
+ { /* Information is in BCD format */
+ year = bin2bcd(tmp->tm_year % 100);
+ mon = bin2bcd(tmp->tm_mon);
+ wday = bin2bcd(tmp->tm_wday);
+ mday = bin2bcd(tmp->tm_mday);
+ hour = bin2bcd(tmp->tm_hour);
+ min = bin2bcd(tmp->tm_min);
+ sec = bin2bcd(tmp->tm_sec);
+ }
+ else
+ {
+ year = tmp->tm_year % 100;
+ mon = tmp->tm_mon;
+ wday = tmp->tm_wday;
+ mday = tmp->tm_mday;
+ hour = tmp->tm_hour;
+ min = tmp->tm_min;
+ sec = tmp->tm_sec;
+ }
+
+ /* disables the RTC to update the regs */
+ save_ctrl_b = rtc_read(RTC_CONTROL_B);
+ save_ctrl_b |= RTC_CB_SET;
+ rtc_write(RTC_CONTROL_B, save_ctrl_b);
+
+ rtc_write (RTC_YEAR, year);
+ rtc_write (RTC_MONTH, mon);
+ rtc_write (RTC_DAY_OF_WEEK, wday);
+ rtc_write (RTC_DATE_OF_MONTH, mday);
+ rtc_write (RTC_HOURS, hour);
+ rtc_write (RTC_MINUTES, min);
+ rtc_write (RTC_SECONDS, sec);
+
+ /* enables the RTC to update the regs */
+ save_ctrl_b &= ~RTC_CB_SET;
+ rtc_write(RTC_CONTROL_B, save_ctrl_b);
+}
+
+void rtc_reset (void)
+{
+ struct rtc_time tmp;
+ uchar ctrl_rg;
+
+ ctrl_rg = RTC_CB_SET;
+ rtc_write(RTC_CONTROL_B,ctrl_rg);
+
+ tmp.tm_year = 1970 % 100;
+ tmp.tm_mon = 1;
+ tmp.tm_mday= 1;
+ tmp.tm_hour = 0;
+ tmp.tm_min = 0;
+ tmp.tm_sec = 0;
+
+#ifdef RTC_DEBUG
+ printf ( "RTC: %4d-%02d-%02d %2d:%02d:%02d UTC\n",
+ tmp.tm_year, tmp.tm_mon, tmp.tm_mday,
+ tmp.tm_hour, tmp.tm_min, tmp.tm_sec);
+#endif
+
+ ctrl_rg = RTC_CB_SET | RTC_CB_24_12 | RTC_CB_DM;
+ rtc_write(RTC_CONTROL_B,ctrl_rg);
+ rtc_set(&tmp);
+
+ rtc_write(RTC_HOURS_ALARM, 0),
+ rtc_write(RTC_MINUTES_ALARM, 0),
+ rtc_write(RTC_SECONDS_ALARM, 0);
+
+ ctrl_rg = RTC_CB_24_12 | RTC_CB_DM;
+ rtc_write(RTC_CONTROL_B,ctrl_rg);
+}
+
+#endif
diff --git a/drivers/rtc/ds1302.c b/drivers/rtc/ds1302.c
new file mode 100644
index 0000000..55af130
--- /dev/null
+++ b/drivers/rtc/ds1302.c
@@ -0,0 +1,327 @@
+/*
+ * ds1302.c - Support for the Dallas Semiconductor DS1302 Timekeeping Chip
+ *
+ * Rex G. Feany <rfeany@zumanetworks.com>
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+
+#if defined(CONFIG_RTC_DS1302) && defined(CONFIG_CMD_DATE)
+
+/* GPP Pins */
+#define DATA 0x200
+#define SCLK 0x400
+#define RST 0x800
+
+/* Happy Fun Defines(tm) */
+#define RESET rtc_go_low(RST), rtc_go_low(SCLK)
+#define N_RESET rtc_go_high(RST), rtc_go_low(SCLK)
+
+#define CLOCK_HIGH rtc_go_high(SCLK)
+#define CLOCK_LOW rtc_go_low(SCLK)
+
+#define DATA_HIGH rtc_go_high(DATA)
+#define DATA_LOW rtc_go_low(DATA)
+#define DATA_READ (GTREGREAD(GPP_VALUE) & DATA)
+
+#undef RTC_DEBUG
+
+#ifdef RTC_DEBUG
+# define DPRINTF(x,args...) printf("ds1302: " x , ##args)
+static inline void DUMP(const char *ptr, int num)
+{
+ while (num--) printf("%x ", *ptr++);
+ printf("]\n");
+}
+#else
+# define DPRINTF(x,args...)
+# define DUMP(ptr, num)
+#endif
+
+/* time data format for DS1302 */
+struct ds1302_st
+{
+ unsigned char CH:1; /* clock halt 1=stop 0=start */
+ unsigned char sec10:3;
+ unsigned char sec:4;
+
+ unsigned char zero0:1;
+ unsigned char min10:3;
+ unsigned char min:4;
+
+ unsigned char fmt:1; /* 1=12 hour 0=24 hour */
+ unsigned char zero1:1;
+ unsigned char hr10:2; /* 10 (0-2) or am/pm (am/pm, 0-1) */
+ unsigned char hr:4;
+
+ unsigned char zero2:2;
+ unsigned char date10:2;
+ unsigned char date:4;
+
+ unsigned char zero3:3;
+ unsigned char month10:1;
+ unsigned char month:4;
+
+ unsigned char zero4:5;
+ unsigned char day:3; /* day of week */
+
+ unsigned char year10:4;
+ unsigned char year:4;
+
+ unsigned char WP:1; /* write protect 1=protect 0=unprot */
+ unsigned char zero5:7;
+};
+
+static int ds1302_initted=0;
+
+/* Pin control */
+static inline void
+rtc_go_high(unsigned int mask)
+{
+ unsigned int f = GTREGREAD(GPP_VALUE) | mask;
+
+ GT_REG_WRITE(GPP_VALUE, f);
+}
+
+static inline void
+rtc_go_low(unsigned int mask)
+{
+ unsigned int f = GTREGREAD(GPP_VALUE) & ~mask;
+
+ GT_REG_WRITE(GPP_VALUE, f);
+}
+
+static inline void
+rtc_go_input(unsigned int mask)
+{
+ unsigned int f = GTREGREAD(GPP_IO_CONTROL) & ~mask;
+
+ GT_REG_WRITE(GPP_IO_CONTROL, f);
+}
+
+static inline void
+rtc_go_output(unsigned int mask)
+{
+ unsigned int f = GTREGREAD(GPP_IO_CONTROL) | mask;
+
+ GT_REG_WRITE(GPP_IO_CONTROL, f);
+}
+
+/* Access data in RTC */
+
+static void
+write_byte(unsigned char b)
+{
+ int i;
+ unsigned char mask=1;
+
+ for(i=0;i<8;i++) {
+ CLOCK_LOW; /* Lower clock */
+ (b&mask)?DATA_HIGH:DATA_LOW; /* set data */
+ udelay(1);
+ CLOCK_HIGH; /* latch data with rising clock */
+ udelay(1);
+ mask=mask<<1;
+ }
+}
+
+static unsigned char
+read_byte(void)
+{
+ int i;
+ unsigned char mask=1;
+ unsigned char b=0;
+
+ for(i=0;i<8;i++) {
+ CLOCK_LOW;
+ udelay(1);
+ if (DATA_READ) b|=mask; /* if this bit is high, set in b */
+ CLOCK_HIGH; /* clock out next bit */
+ udelay(1);
+ mask=mask<<1;
+ }
+ return b;
+}
+
+static void
+read_ser_drv(unsigned char addr, unsigned char *buf, int count)
+{
+ int i;
+#ifdef RTC_DEBUG
+ char *foo = buf;
+#endif
+
+ DPRINTF("READ 0x%x bytes @ 0x%x [ ", count, addr);
+
+ addr|=1; /* READ */
+ N_RESET;
+ udelay(4);
+ write_byte(addr);
+ rtc_go_input(DATA); /* Put gpp pin into input mode */
+ udelay(1);
+ for(i=0;i<count;i++) *(buf++)=read_byte();
+ RESET;
+ rtc_go_output(DATA);/* Reset gpp for output */
+ udelay(4);
+
+ DUMP(foo, count);
+}
+
+static void
+write_ser_drv(unsigned char addr, unsigned char *buf, int count)
+{
+ int i;
+
+ DPRINTF("WRITE 0x%x bytes @ 0x%x [ ", count, addr);
+ DUMP(buf, count);
+
+ addr&=~1; /* WRITE */
+ N_RESET;
+ udelay(4);
+ write_byte(addr);
+ for(i=0;i<count;i++) write_byte(*(buf++));
+ RESET;
+ udelay(4);
+
+}
+
+void
+rtc_init(void)
+{
+ struct ds1302_st bbclk;
+ unsigned char b;
+ int mod;
+
+ DPRINTF("init\n");
+
+ rtc_go_output(DATA|SCLK|RST);
+
+ /* disable write protect */
+ b = 0;
+ write_ser_drv(0x8e,&b,1);
+
+ /* enable trickle */
+ b = 0xa5; /* 1010.0101 */
+ write_ser_drv(0x90,&b,1);
+
+ /* read burst */
+ read_ser_drv(0xbe, (unsigned char *)&bbclk, 8);
+
+ /* Sanity checks */
+ mod = 0;
+ if (bbclk.CH) {
+ printf("ds1302: Clock was halted, starting clock\n");
+ bbclk.CH=0;
+ mod=1;
+ }
+
+ if (bbclk.fmt) {
+ printf("ds1302: Clock was in 12 hour mode, fixing\n");
+ bbclk.fmt=0;
+ mod=1;
+ }
+
+ if (bbclk.year>9) {
+ printf("ds1302: Year was corrupted, fixing\n");
+ bbclk.year10=100/10; /* 2000 - why not? ;) */
+ bbclk.year=0;
+ mod=1;
+ }
+
+ /* Write out the changes if needed */
+ if (mod) {
+ /* enable write protect */
+ bbclk.WP = 1;
+ write_ser_drv(0xbe,(unsigned char *)&bbclk,8);
+ } else {
+ /* Else just turn write protect on */
+ b = 0x80;
+ write_ser_drv(0x8e,&b,1);
+ }
+ DPRINTF("init done\n");
+
+ ds1302_initted=1;
+}
+
+void
+rtc_reset(void)
+{
+ if(!ds1302_initted) rtc_init();
+ /* TODO */
+}
+
+void
+rtc_get(struct rtc_time *tmp)
+{
+ struct ds1302_st bbclk;
+
+ if(!ds1302_initted) rtc_init();
+
+ read_ser_drv(0xbe,(unsigned char *)&bbclk, 8); /* read burst */
+
+ if (bbclk.CH) {
+ printf("ds1302: rtc_get: Clock was halted, clock probably "
+ "corrupt\n");
+ }
+
+ tmp->tm_sec=10*bbclk.sec10+bbclk.sec;
+ tmp->tm_min=10*bbclk.min10+bbclk.min;
+ tmp->tm_hour=10*bbclk.hr10+bbclk.hr;
+ tmp->tm_wday=bbclk.day;
+ tmp->tm_mday=10*bbclk.date10+bbclk.date;
+ tmp->tm_mon=10*bbclk.month10+bbclk.month;
+ tmp->tm_year=10*bbclk.year10+bbclk.year + 1900;
+
+ tmp->tm_yday = 0;
+ tmp->tm_isdst= 0;
+
+ DPRINTF("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)
+{
+ struct ds1302_st bbclk;
+ unsigned char b=0;
+
+ if(!ds1302_initted) rtc_init();
+
+ DPRINTF("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);
+
+ memset(&bbclk,0,sizeof(bbclk));
+ bbclk.CH=0; /* dont halt */
+ bbclk.WP=1; /* write protect when we're done */
+
+ bbclk.sec10=tmp->tm_sec/10;
+ bbclk.sec=tmp->tm_sec%10;
+
+ bbclk.min10=tmp->tm_min/10;
+ bbclk.min=tmp->tm_min%10;
+
+ bbclk.hr10=tmp->tm_hour/10;
+ bbclk.hr=tmp->tm_hour%10;
+
+ bbclk.day=tmp->tm_wday;
+
+ bbclk.date10=tmp->tm_mday/10;
+ bbclk.date=tmp->tm_mday%10;
+
+ bbclk.month10=tmp->tm_mon/10;
+ bbclk.month=tmp->tm_mon%10;
+
+ tmp->tm_year -= 1900;
+ bbclk.year10=tmp->tm_year/10;
+ bbclk.year=tmp->tm_year%10;
+
+ write_ser_drv(0x8e,&b,1); /* disable write protect */
+ write_ser_drv(0xbe,(unsigned char *)&bbclk, 8); /* write burst */
+}
+
+#endif
diff --git a/drivers/rtc/ds1306.c b/drivers/rtc/ds1306.c
new file mode 100644
index 0000000..89e433d
--- /dev/null
+++ b/drivers/rtc/ds1306.c
@@ -0,0 +1,438 @@
+/*
+ * (C) Copyright 2002 SIXNET, dge@sixnetio.com.
+ *
+ * (C) Copyright 2004, Li-Pro.Net <www.li-pro.net>
+ * Stephan Linz <linz@li-pro.net>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support for DS1306 RTC using SPI:
+ *
+ * - SXNI855T: it uses its own soft SPI here in this file
+ * - all other: use the external spi_xfer() function
+ * (see include/spi.h)
+ */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+#include <spi.h>
+
+#if defined(CONFIG_RTC_DS1306) && defined(CONFIG_CMD_DATE)
+
+#define RTC_SECONDS 0x00
+#define RTC_MINUTES 0x01
+#define RTC_HOURS 0x02
+#define RTC_DAY_OF_WEEK 0x03
+#define RTC_DATE_OF_MONTH 0x04
+#define RTC_MONTH 0x05
+#define RTC_YEAR 0x06
+
+#define RTC_SECONDS_ALARM0 0x07
+#define RTC_MINUTES_ALARM0 0x08
+#define RTC_HOURS_ALARM0 0x09
+#define RTC_DAY_OF_WEEK_ALARM0 0x0a
+
+#define RTC_SECONDS_ALARM1 0x0b
+#define RTC_MINUTES_ALARM1 0x0c
+#define RTC_HOURS_ALARM1 0x0d
+#define RTC_DAY_OF_WEEK_ALARM1 0x0e
+
+#define RTC_CONTROL 0x0f
+#define RTC_STATUS 0x10
+#define RTC_TRICKLE_CHARGER 0x11
+
+#define RTC_USER_RAM_BASE 0x20
+
+/*
+ * External table of chip select functions (see the appropriate board
+ * support for the actual definition of the table).
+ */
+extern spi_chipsel_type spi_chipsel[];
+extern int spi_chipsel_cnt;
+
+static unsigned int bin2bcd (unsigned int n);
+static unsigned char bcd2bin (unsigned char c);
+
+/* ************************************************************************* */
+#ifdef CONFIG_SXNI855T /* !!! SHOULD BE CHANGED TO NEW CODE !!! */
+
+static void soft_spi_send (unsigned char n);
+static unsigned char soft_spi_read (void);
+static void init_spi (void);
+
+/*-----------------------------------------------------------------------
+ * Definitions
+ */
+
+#define PB_SPISCK 0x00000002 /* PB 30 */
+#define PB_SPIMOSI 0x00000004 /* PB 29 */
+#define PB_SPIMISO 0x00000008 /* PB 28 */
+#define PB_SPI_CE 0x00010000 /* PB 15 */
+
+/* ------------------------------------------------------------------------- */
+
+/* read clock time from DS1306 and return it in *tmp */
+void rtc_get (struct rtc_time *tmp)
+{
+ volatile immap_t *immap = (immap_t *) CFG_IMMR;
+ unsigned char spi_byte; /* Data Byte */
+
+ init_spi (); /* set port B for software SPI */
+
+ /* Now we can enable the DS1306 RTC */
+ immap->im_cpm.cp_pbdat |= PB_SPI_CE;
+ udelay (10);
+
+ /* Shift out the address (0) of the time in the Clock Chip */
+ soft_spi_send (0);
+
+ /* Put the clock readings into the rtc_time structure */
+ tmp->tm_sec = bcd2bin (soft_spi_read ()); /* Read seconds */
+ tmp->tm_min = bcd2bin (soft_spi_read ()); /* Read minutes */
+
+ /* Hours are trickier */
+ spi_byte = soft_spi_read (); /* Read Hours into temporary value */
+ if (spi_byte & 0x40) {
+ /* 12 hour mode bit is set (time is in 1-12 format) */
+ if (spi_byte & 0x20) {
+ /* since PM we add 11 to get 0-23 for hours */
+ tmp->tm_hour = (bcd2bin (spi_byte & 0x1F)) + 11;
+ } else {
+ /* since AM we subtract 1 to get 0-23 for hours */
+ tmp->tm_hour = (bcd2bin (spi_byte & 0x1F)) - 1;
+ }
+ } else {
+ /* Otherwise, 0-23 hour format */
+ tmp->tm_hour = (bcd2bin (spi_byte & 0x3F));
+ }
+
+ soft_spi_read (); /* Read and discard Day of week */
+ tmp->tm_mday = bcd2bin (soft_spi_read ()); /* Read Day of the Month */
+ tmp->tm_mon = bcd2bin (soft_spi_read ()); /* Read Month */
+
+ /* Read Year and convert to this century */
+ tmp->tm_year = bcd2bin (soft_spi_read ()) + 2000;
+
+ /* Now we can disable the DS1306 RTC */
+ immap->im_cpm.cp_pbdat &= ~PB_SPI_CE; /* Disable DS1306 Chip */
+ udelay (10);
+
+ GregorianDay (tmp); /* Determine the day of week */
+
+ 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);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* set clock time in DS1306 RTC and in MPC8xx RTC */
+void rtc_set (struct rtc_time *tmp)
+{
+ volatile immap_t *immap = (immap_t *) CFG_IMMR;
+
+ init_spi (); /* set port B for software SPI */
+
+ /* Now we can enable the DS1306 RTC */
+ immap->im_cpm.cp_pbdat |= PB_SPI_CE; /* Enable DS1306 Chip */
+ udelay (10);
+
+ /* First disable write protect in the clock chip control register */
+ soft_spi_send (0x8F); /* send address of the control register */
+ soft_spi_send (0x00); /* send control register contents */
+
+ /* Now disable the DS1306 to terminate the write */
+ immap->im_cpm.cp_pbdat &= ~PB_SPI_CE;
+ udelay (10);
+
+ /* Now enable the DS1306 to initiate a new write */
+ immap->im_cpm.cp_pbdat |= PB_SPI_CE;
+ udelay (10);
+
+ /* Next, send the address of the clock time write registers */
+ soft_spi_send (0x80); /* send address of the first time register */
+
+ /* Use Burst Mode to send all of the time data to the clock */
+ bin2bcd (tmp->tm_sec);
+ soft_spi_send (bin2bcd (tmp->tm_sec)); /* Send Seconds */
+ soft_spi_send (bin2bcd (tmp->tm_min)); /* Send Minutes */
+ soft_spi_send (bin2bcd (tmp->tm_hour)); /* Send Hour */
+ soft_spi_send (bin2bcd (tmp->tm_wday)); /* Send Day of the Week */
+ soft_spi_send (bin2bcd (tmp->tm_mday)); /* Send Day of Month */
+ soft_spi_send (bin2bcd (tmp->tm_mon)); /* Send Month */
+ soft_spi_send (bin2bcd (tmp->tm_year - 2000)); /* Send Year */
+
+ /* Now we can disable the Clock chip to terminate the burst write */
+ immap->im_cpm.cp_pbdat &= ~PB_SPI_CE; /* Disable DS1306 Chip */
+ udelay (10);
+
+ /* Now we can enable the Clock chip to initiate a new write */
+ immap->im_cpm.cp_pbdat |= PB_SPI_CE; /* Enable DS1306 Chip */
+ udelay (10);
+
+ /* First we Enable write protect in the clock chip control register */
+ soft_spi_send (0x8F); /* send address of the control register */
+ soft_spi_send (0x40); /* send out Control Register contents */
+
+ /* Now disable the DS1306 */
+ immap->im_cpm.cp_pbdat &= ~PB_SPI_CE; /* Disable DS1306 Chip */
+ udelay (10);
+
+ /* Set standard MPC8xx clock to the same time so Linux will
+ * see the time even if it doesn't have a DS1306 clock driver.
+ * This helps with experimenting with standard kernels.
+ */
+ {
+ ulong tim;
+
+ tim = mktime (tmp->tm_year, tmp->tm_mon, tmp->tm_mday,
+ tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+
+ immap->im_sitk.sitk_rtck = KAPWR_KEY;
+ immap->im_sit.sit_rtc = tim;
+ }
+
+ 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);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Initialize Port B for software SPI */
+static void init_spi (void)
+{
+ volatile immap_t *immap = (immap_t *) CFG_IMMR;
+
+ /* Force output pins to begin at logic 0 */
+ immap->im_cpm.cp_pbdat &= ~(PB_SPI_CE | PB_SPIMOSI | PB_SPISCK);
+
+ /* Set these 3 signals as outputs */
+ immap->im_cpm.cp_pbdir |= (PB_SPIMOSI | PB_SPI_CE | PB_SPISCK);
+
+ immap->im_cpm.cp_pbdir &= ~PB_SPIMISO; /* Make MISO pin an input */
+ udelay (10);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* NOTE: soft_spi_send() assumes that the I/O lines are configured already */
+static void soft_spi_send (unsigned char n)
+{
+ volatile immap_t *immap = (immap_t *) CFG_IMMR;
+ unsigned char bitpos; /* bit position to receive */
+ unsigned char i; /* Loop Control */
+
+ /* bit position to send, start with most significant bit */
+ bitpos = 0x80;
+
+ /* Send 8 bits to software SPI */
+ for (i = 0; i < 8; i++) { /* Loop for 8 bits */
+ immap->im_cpm.cp_pbdat |= PB_SPISCK; /* Raise SCK */
+
+ if (n & bitpos)
+ immap->im_cpm.cp_pbdat |= PB_SPIMOSI; /* Set MOSI to 1 */
+ else
+ immap->im_cpm.cp_pbdat &= ~PB_SPIMOSI; /* Set MOSI to 0 */
+ udelay (10);
+
+ immap->im_cpm.cp_pbdat &= ~PB_SPISCK; /* Lower SCK */
+ udelay (10);
+
+ bitpos >>= 1; /* Shift for next bit position */
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* NOTE: soft_spi_read() assumes that the I/O lines are configured already */
+static unsigned char soft_spi_read (void)
+{
+ volatile immap_t *immap = (immap_t *) CFG_IMMR;
+
+ unsigned char spi_byte = 0; /* Return value, assume success */
+ unsigned char bitpos; /* bit position to receive */
+ unsigned char i; /* Loop Control */
+
+ /* bit position to receive, start with most significant bit */
+ bitpos = 0x80;
+
+ /* Read 8 bits here */
+ for (i = 0; i < 8; i++) { /* Do 8 bits in loop */
+ immap->im_cpm.cp_pbdat |= PB_SPISCK; /* Raise SCK */
+ udelay (10);
+ if (immap->im_cpm.cp_pbdat & PB_SPIMISO) /* Get a bit of data */
+ spi_byte |= bitpos; /* Set data accordingly */
+ immap->im_cpm.cp_pbdat &= ~PB_SPISCK; /* Lower SCK */
+ udelay (10);
+ bitpos >>= 1; /* Shift for next bit position */
+ }
+
+ return spi_byte; /* Return the byte read */
+}
+
+/* ------------------------------------------------------------------------- */
+
+void rtc_reset (void)
+{
+ return; /* nothing to do */
+}
+
+#else /* not CONFIG_SXNI855T */
+/* ************************************************************************* */
+
+static unsigned char rtc_read (unsigned char reg);
+static void rtc_write (unsigned char reg, unsigned char val);
+
+/* read clock time from DS1306 and return it in *tmp */
+void rtc_get (struct rtc_time *tmp)
+{
+ unsigned char sec, min, hour, mday, wday, mon, year;
+
+ sec = rtc_read (RTC_SECONDS);
+ min = rtc_read (RTC_MINUTES);
+ hour = rtc_read (RTC_HOURS);
+ mday = rtc_read (RTC_DATE_OF_MONTH);
+ wday = rtc_read (RTC_DAY_OF_WEEK);
+ mon = rtc_read (RTC_MONTH);
+ year = rtc_read (RTC_YEAR);
+
+ debug ("Get RTC year: %02x mon: %02x mday: %02x wday: %02x "
+ "hr: %02x min: %02x sec: %02x\n",
+ year, mon, mday, wday, hour, min, sec);
+ debug ("Alarms[0]: wday: %02x hour: %02x min: %02x sec: %02x\n",
+ rtc_read (RTC_DAY_OF_WEEK_ALARM0),
+ rtc_read (RTC_HOURS_ALARM0),
+ rtc_read (RTC_MINUTES_ALARM0), rtc_read (RTC_SECONDS_ALARM0));
+ debug ("Alarms[1]: wday: %02x hour: %02x min: %02x sec: %02x\n",
+ rtc_read (RTC_DAY_OF_WEEK_ALARM1),
+ rtc_read (RTC_HOURS_ALARM1),
+ rtc_read (RTC_MINUTES_ALARM1), rtc_read (RTC_SECONDS_ALARM1));
+
+ tmp->tm_sec = bcd2bin (sec & 0x7F); /* convert Seconds */
+ tmp->tm_min = bcd2bin (min & 0x7F); /* convert Minutes */
+
+ /* convert Hours */
+ tmp->tm_hour = (hour & 0x40)
+ ? ((hour & 0x20) /* 12 hour mode */
+ ? bcd2bin (hour & 0x1F) + 11 /* PM */
+ : bcd2bin (hour & 0x1F) - 1 /* AM */
+ )
+ : bcd2bin (hour & 0x3F); /* 24 hour mode */
+
+ tmp->tm_mday = bcd2bin (mday & 0x3F); /* convert Day of the Month */
+ tmp->tm_mon = bcd2bin (mon & 0x1F); /* convert Month */
+ tmp->tm_year = bcd2bin (year) + 2000; /* convert Year */
+ tmp->tm_wday = bcd2bin (wday & 0x07) - 1; /* convert Day of the Week */
+ 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);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* set clock time from *tmp in DS1306 RTC */
+void rtc_set (struct rtc_time *tmp)
+{
+ 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);
+
+ rtc_write (RTC_SECONDS, bin2bcd (tmp->tm_sec));
+ rtc_write (RTC_MINUTES, bin2bcd (tmp->tm_min));
+ rtc_write (RTC_HOURS, bin2bcd (tmp->tm_hour));
+ rtc_write (RTC_DAY_OF_WEEK, bin2bcd (tmp->tm_wday + 1));
+ rtc_write (RTC_DATE_OF_MONTH, bin2bcd (tmp->tm_mday));
+ rtc_write (RTC_MONTH, bin2bcd (tmp->tm_mon));
+ rtc_write (RTC_YEAR, bin2bcd (tmp->tm_year - 2000));
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* reset the DS1306 */
+void rtc_reset (void)
+{
+ /* clear the control register */
+ rtc_write (RTC_CONTROL, 0x00); /* 1st step: reset WP */
+ rtc_write (RTC_CONTROL, 0x00); /* 2nd step: reset 1Hz, AIE1, AIE0 */
+
+ /* reset all alarms */
+ rtc_write (RTC_SECONDS_ALARM0, 0x00);
+ rtc_write (RTC_SECONDS_ALARM1, 0x00);
+ rtc_write (RTC_MINUTES_ALARM0, 0x00);
+ rtc_write (RTC_MINUTES_ALARM1, 0x00);
+ rtc_write (RTC_HOURS_ALARM0, 0x00);
+ rtc_write (RTC_HOURS_ALARM1, 0x00);
+ rtc_write (RTC_DAY_OF_WEEK_ALARM0, 0x00);
+ rtc_write (RTC_DAY_OF_WEEK_ALARM1, 0x00);
+}
+
+/* ------------------------------------------------------------------------- */
+
+static unsigned char rtc_read (unsigned char reg)
+{
+ unsigned char dout[2]; /* SPI Output Data Bytes */
+ unsigned char din[2]; /* SPI Input Data Bytes */
+
+ dout[0] = reg;
+
+ if (spi_xfer (spi_chipsel[CFG_SPI_RTC_DEVID], 16, dout, din) != 0) {
+ return 0;
+ } else {
+ return din[1];
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void rtc_write (unsigned char reg, unsigned char val)
+{
+ unsigned char dout[2]; /* SPI Output Data Bytes */
+ unsigned char din[2]; /* SPI Input Data Bytes */
+
+ dout[0] = 0x80 | reg;
+ dout[1] = val;
+
+ spi_xfer (spi_chipsel[CFG_SPI_RTC_DEVID], 16, dout, din);
+}
+
+#endif /* end of code exclusion (see #ifdef CONFIG_SXNI855T above) */
+
+/* ------------------------------------------------------------------------- */
+
+static unsigned char bcd2bin (unsigned char n)
+{
+ return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
+}
+
+/* ------------------------------------------------------------------------- */
+
+static unsigned int bin2bcd (unsigned int n)
+{
+ return (((n / 10) << 4) | (n % 10));
+}
+/* ------------------------------------------------------------------------- */
+
+#endif
diff --git a/drivers/rtc/ds1307.c b/drivers/rtc/ds1307.c
new file mode 100644
index 0000000..c882d79
--- /dev/null
+++ b/drivers/rtc/ds1307.c
@@ -0,0 +1,204 @@
+/*
+ * (C) Copyright 2001, 2002, 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Keith Outwater, keith_outwater@mvis.com`
+ * Steven Scholz, steven.scholz@imc-berlin.de
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support (no alarms) for Dallas Semiconductor (now Maxim)
+ * DS1307 and DS1338 Real Time Clock (RTC).
+ *
+ * based on ds1337.c
+ */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+#include <i2c.h>
+
+#if (defined(CONFIG_RTC_DS1307) || defined(CONFIG_RTC_DS1338) ) && \
+ defined(CONFIG_CMD_DATE)
+
+/*---------------------------------------------------------------------*/
+#undef DEBUG_RTC
+
+#ifdef DEBUG_RTC
+#define DEBUGR(fmt,args...) printf(fmt ,##args)
+#else
+#define DEBUGR(fmt,args...)
+#endif
+/*---------------------------------------------------------------------*/
+
+#ifndef CFG_I2C_RTC_ADDR
+# define CFG_I2C_RTC_ADDR 0x68
+#endif
+
+#if defined(CONFIG_RTC_DS1307) && (CFG_I2C_SPEED > 100000)
+# error The DS1307 is specified only up to 100kHz!
+#endif
+
+/*
+ * RTC register addresses
+ */
+#define RTC_SEC_REG_ADDR 0x00
+#define RTC_MIN_REG_ADDR 0x01
+#define RTC_HR_REG_ADDR 0x02
+#define RTC_DAY_REG_ADDR 0x03
+#define RTC_DATE_REG_ADDR 0x04
+#define RTC_MON_REG_ADDR 0x05
+#define RTC_YR_REG_ADDR 0x06
+#define RTC_CTL_REG_ADDR 0x07
+
+#define RTC_SEC_BIT_CH 0x80 /* Clock Halt (in Register 0) */
+
+#define RTC_CTL_BIT_RS0 0x01 /* Rate select 0 */
+#define RTC_CTL_BIT_RS1 0x02 /* Rate select 1 */
+#define RTC_CTL_BIT_SQWE 0x10 /* Square Wave Enable */
+#define RTC_CTL_BIT_OUT 0x80 /* Output Control */
+
+static uchar rtc_read (uchar reg);
+static void rtc_write (uchar reg, uchar val);
+static uchar bin2bcd (unsigned int n);
+static unsigned bcd2bin (uchar c);
+
+/*
+ * Get the current time from the RTC
+ */
+void rtc_get (struct rtc_time *tmp)
+{
+ uchar sec, min, hour, mday, wday, mon, year;
+
+ sec = rtc_read (RTC_SEC_REG_ADDR);
+ min = rtc_read (RTC_MIN_REG_ADDR);
+ hour = rtc_read (RTC_HR_REG_ADDR);
+ wday = rtc_read (RTC_DAY_REG_ADDR);
+ mday = rtc_read (RTC_DATE_REG_ADDR);
+ mon = rtc_read (RTC_MON_REG_ADDR);
+ year = rtc_read (RTC_YR_REG_ADDR);
+
+ DEBUGR ("Get RTC year: %02x mon: %02x mday: %02x wday: %02x "
+ "hr: %02x min: %02x sec: %02x\n",
+ year, mon, mday, wday, hour, min, sec);
+
+ if (sec & RTC_SEC_BIT_CH) {
+ printf ("### Warning: RTC oscillator has stopped\n");
+ /* clear the CH flag */
+ rtc_write (RTC_SEC_REG_ADDR,
+ rtc_read (RTC_SEC_REG_ADDR) & ~RTC_SEC_BIT_CH);
+ }
+
+ tmp->tm_sec = bcd2bin (sec & 0x7F);
+ tmp->tm_min = bcd2bin (min & 0x7F);
+ tmp->tm_hour = bcd2bin (hour & 0x3F);
+ tmp->tm_mday = bcd2bin (mday & 0x3F);
+ tmp->tm_mon = bcd2bin (mon & 0x1F);
+ tmp->tm_year = bcd2bin (year) + ( bcd2bin (year) >= 70 ? 1900 : 2000);
+ tmp->tm_wday = bcd2bin ((wday - 1) & 0x07);
+ tmp->tm_yday = 0;
+ tmp->tm_isdst= 0;
+
+ DEBUGR ("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);
+}
+
+
+/*
+ * Set the RTC
+ */
+void rtc_set (struct rtc_time *tmp)
+{
+ DEBUGR ("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);
+
+ if (tmp->tm_year < 1970 || tmp->tm_year > 2069)
+ printf("WARNING: year should be between 1970 and 2069!\n");
+
+ rtc_write (RTC_YR_REG_ADDR, bin2bcd (tmp->tm_year % 100));
+ rtc_write (RTC_MON_REG_ADDR, bin2bcd (tmp->tm_mon));
+ rtc_write (RTC_DAY_REG_ADDR, bin2bcd (tmp->tm_wday + 1));
+ rtc_write (RTC_DATE_REG_ADDR, bin2bcd (tmp->tm_mday));
+ rtc_write (RTC_HR_REG_ADDR, bin2bcd (tmp->tm_hour));
+ rtc_write (RTC_MIN_REG_ADDR, bin2bcd (tmp->tm_min));
+ rtc_write (RTC_SEC_REG_ADDR, bin2bcd (tmp->tm_sec));
+}
+
+
+/*
+ * Reset the RTC. We setting the date back to 1970-01-01.
+ * We also enable the oscillator output on the SQW/OUT pin and program
+ * it for 32,768 Hz output. Note that according to the datasheet, turning
+ * on the square wave output increases the current drain on the backup
+ * battery to something between 480nA and 800nA.
+ */
+void rtc_reset (void)
+{
+ struct rtc_time tmp;
+
+ rtc_write (RTC_SEC_REG_ADDR, 0x00); /* clearing Clock Halt */
+ rtc_write (RTC_CTL_REG_ADDR, RTC_CTL_BIT_SQWE | RTC_CTL_BIT_RS1 | RTC_CTL_BIT_RS0);
+
+ tmp.tm_year = 1970;
+ tmp.tm_mon = 1;
+ tmp.tm_mday= 1;
+ tmp.tm_hour = 0;
+ tmp.tm_min = 0;
+ tmp.tm_sec = 0;
+
+ rtc_set(&tmp);
+
+ printf ( "RTC: %4d-%02d-%02d %2d:%02d:%02d UTC\n",
+ tmp.tm_year, tmp.tm_mon, tmp.tm_mday,
+ tmp.tm_hour, tmp.tm_min, tmp.tm_sec);
+
+ return;
+}
+
+
+/*
+ * Helper functions
+ */
+
+static
+uchar rtc_read (uchar reg)
+{
+ return (i2c_reg_read (CFG_I2C_RTC_ADDR, reg));
+}
+
+
+static void rtc_write (uchar reg, uchar val)
+{
+ i2c_reg_write (CFG_I2C_RTC_ADDR, reg, val);
+}
+
+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));
+}
+
+#endif
diff --git a/drivers/rtc/ds1337.c b/drivers/rtc/ds1337.c
new file mode 100644
index 0000000..c636ac5
--- /dev/null
+++ b/drivers/rtc/ds1337.c
@@ -0,0 +1,191 @@
+/*
+ * (C) Copyright 2001, 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Keith Outwater, keith_outwater@mvis.com`
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support (no alarms) for Dallas Semiconductor (now Maxim)
+ * DS1337 Real Time Clock (RTC).
+ */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+#include <i2c.h>
+
+#if defined(CONFIG_RTC_DS1337) && defined(CONFIG_CMD_DATE)
+
+/*---------------------------------------------------------------------*/
+#undef DEBUG_RTC
+
+#ifdef DEBUG_RTC
+#define DEBUGR(fmt,args...) printf(fmt ,##args)
+#else
+#define DEBUGR(fmt,args...)
+#endif
+/*---------------------------------------------------------------------*/
+
+/*
+ * RTC register addresses
+ */
+#define RTC_SEC_REG_ADDR 0x0
+#define RTC_MIN_REG_ADDR 0x1
+#define RTC_HR_REG_ADDR 0x2
+#define RTC_DAY_REG_ADDR 0x3
+#define RTC_DATE_REG_ADDR 0x4
+#define RTC_MON_REG_ADDR 0x5
+#define RTC_YR_REG_ADDR 0x6
+#define RTC_CTL_REG_ADDR 0x0e
+#define RTC_STAT_REG_ADDR 0x0f
+
+/*
+ * RTC control register bits
+ */
+#define RTC_CTL_BIT_A1IE 0x1 /* Alarm 1 interrupt enable */
+#define RTC_CTL_BIT_A2IE 0x2 /* Alarm 2 interrupt enable */
+#define RTC_CTL_BIT_INTCN 0x4 /* Interrupt control */
+#define RTC_CTL_BIT_RS1 0x8 /* Rate select 1 */
+#define RTC_CTL_BIT_RS2 0x10 /* Rate select 2 */
+#define RTC_CTL_BIT_DOSC 0x80 /* Disable Oscillator */
+
+/*
+ * RTC status register bits
+ */
+#define RTC_STAT_BIT_A1F 0x1 /* Alarm 1 flag */
+#define RTC_STAT_BIT_A2F 0x2 /* Alarm 2 flag */
+#define RTC_STAT_BIT_OSF 0x80 /* Oscillator stop flag */
+
+
+static uchar rtc_read (uchar reg);
+static void rtc_write (uchar reg, uchar val);
+static uchar bin2bcd (unsigned int n);
+static unsigned bcd2bin (uchar c);
+
+
+/*
+ * Get the current time from the RTC
+ */
+void rtc_get (struct rtc_time *tmp)
+{
+ uchar sec, min, hour, mday, wday, mon_cent, year, control, status;
+
+ control = rtc_read (RTC_CTL_REG_ADDR);
+ status = rtc_read (RTC_STAT_REG_ADDR);
+ sec = rtc_read (RTC_SEC_REG_ADDR);
+ min = rtc_read (RTC_MIN_REG_ADDR);
+ hour = rtc_read (RTC_HR_REG_ADDR);
+ wday = rtc_read (RTC_DAY_REG_ADDR);
+ mday = rtc_read (RTC_DATE_REG_ADDR);
+ mon_cent = rtc_read (RTC_MON_REG_ADDR);
+ year = rtc_read (RTC_YR_REG_ADDR);
+
+ DEBUGR ("Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
+ "hr: %02x min: %02x sec: %02x control: %02x status: %02x\n",
+ year, mon_cent, mday, wday, hour, min, sec, control, status);
+
+ if (status & RTC_STAT_BIT_OSF) {
+ printf ("### Warning: RTC oscillator has stopped\n");
+ /* clear the OSF flag */
+ rtc_write (RTC_STAT_REG_ADDR,
+ rtc_read (RTC_STAT_REG_ADDR) & ~RTC_STAT_BIT_OSF);
+ }
+
+ tmp->tm_sec = bcd2bin (sec & 0x7F);
+ tmp->tm_min = bcd2bin (min & 0x7F);
+ tmp->tm_hour = bcd2bin (hour & 0x3F);
+ tmp->tm_mday = bcd2bin (mday & 0x3F);
+ tmp->tm_mon = bcd2bin (mon_cent & 0x1F);
+ tmp->tm_year = bcd2bin (year) + ((mon_cent & 0x80) ? 2000 : 1900);
+ tmp->tm_wday = bcd2bin ((wday - 1) & 0x07);
+ tmp->tm_yday = 0;
+ tmp->tm_isdst= 0;
+
+ DEBUGR ("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);
+}
+
+
+/*
+ * Set the RTC
+ */
+void rtc_set (struct rtc_time *tmp)
+{
+ uchar century;
+
+ DEBUGR ("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);
+
+ rtc_write (RTC_YR_REG_ADDR, bin2bcd (tmp->tm_year % 100));
+
+ century = (tmp->tm_year >= 2000) ? 0x80 : 0;
+ rtc_write (RTC_MON_REG_ADDR, bin2bcd (tmp->tm_mon) | century);
+
+ rtc_write (RTC_DAY_REG_ADDR, bin2bcd (tmp->tm_wday + 1));
+ rtc_write (RTC_DATE_REG_ADDR, bin2bcd (tmp->tm_mday));
+ rtc_write (RTC_HR_REG_ADDR, bin2bcd (tmp->tm_hour));
+ rtc_write (RTC_MIN_REG_ADDR, bin2bcd (tmp->tm_min));
+ rtc_write (RTC_SEC_REG_ADDR, bin2bcd (tmp->tm_sec));
+}
+
+
+/*
+ * Reset the RTC. We also enable the oscillator output on the
+ * SQW/INTB* pin and program it for 32,768 Hz output. Note that
+ * according to the datasheet, turning on the square wave output
+ * increases the current drain on the backup battery from about
+ * 600 nA to 2uA.
+ */
+void rtc_reset (void)
+{
+ rtc_write (RTC_CTL_REG_ADDR, RTC_CTL_BIT_RS1 | RTC_CTL_BIT_RS2);
+}
+
+
+/*
+ * Helper functions
+ */
+
+static
+uchar rtc_read (uchar reg)
+{
+ return (i2c_reg_read (CFG_I2C_RTC_ADDR, reg));
+}
+
+
+static void rtc_write (uchar reg, uchar val)
+{
+ i2c_reg_write (CFG_I2C_RTC_ADDR, reg, val);
+}
+
+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));
+}
+
+#endif
diff --git a/drivers/rtc/ds1374.c b/drivers/rtc/ds1374.c
new file mode 100644
index 0000000..e773dd9
--- /dev/null
+++ b/drivers/rtc/ds1374.c
@@ -0,0 +1,253 @@
+/*
+ * (C) Copyright 2001, 2002, 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Keith Outwater, keith_outwater@mvis.com`
+ * Steven Scholz, steven.scholz@imc-berlin.de
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support (no alarms) for Dallas Semiconductor (now Maxim)
+ * DS1374 Real Time Clock (RTC).
+ *
+ * based on ds1337.c
+ */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+#include <i2c.h>
+
+#if (defined(CONFIG_RTC_DS1374)) && defined(CONFIG_CMD_DATE)
+
+/*---------------------------------------------------------------------*/
+#undef DEBUG_RTC
+#define DEBUG_RTC
+
+#ifdef DEBUG_RTC
+#define DEBUGR(fmt,args...) printf(fmt ,##args)
+#else
+#define DEBUGR(fmt,args...)
+#endif
+/*---------------------------------------------------------------------*/
+
+#ifndef CFG_I2C_RTC_ADDR
+# define CFG_I2C_RTC_ADDR 0x68
+#endif
+
+#if defined(CONFIG_RTC_DS1374) && (CFG_I2C_SPEED > 400000)
+# error The DS1374 is specified up to 400kHz in fast mode!
+#endif
+
+/*
+ * RTC register addresses
+ */
+#define RTC_TOD_CNT_BYTE0_ADDR 0x00 /* TimeOfDay */
+#define RTC_TOD_CNT_BYTE1_ADDR 0x01
+#define RTC_TOD_CNT_BYTE2_ADDR 0x02
+#define RTC_TOD_CNT_BYTE3_ADDR 0x03
+
+#define RTC_WD_ALM_CNT_BYTE0_ADDR 0x04
+#define RTC_WD_ALM_CNT_BYTE1_ADDR 0x05
+#define RTC_WD_ALM_CNT_BYTE2_ADDR 0x06
+
+#define RTC_CTL_ADDR 0x07 /* RTC-CoNTrol-register */
+#define RTC_SR_ADDR 0x08 /* RTC-StatusRegister */
+#define RTC_TCS_DS_ADDR 0x09 /* RTC-TrickleChargeSelect DiodeSelect-register */
+
+#define RTC_CTL_BIT_AIE (1<<0) /* Bit 0 - Alarm Interrupt enable */
+#define RTC_CTL_BIT_RS1 (1<<1) /* Bit 1/2 - Rate Select square wave output */
+#define RTC_CTL_BIT_RS2 (1<<2) /* Bit 2/2 - Rate Select square wave output */
+#define RTC_CTL_BIT_WDSTR (1<<3) /* Bit 3 - Watchdog Reset Steering */
+#define RTC_CTL_BIT_BBSQW (1<<4) /* Bit 4 - Battery-Backed Square-Wave */
+#define RTC_CTL_BIT_WD_ALM (1<<5) /* Bit 5 - Watchdoc/Alarm Counter Select */
+#define RTC_CTL_BIT_WACE (1<<6) /* Bit 6 - Watchdog/Alarm Counter Enable WACE*/
+#define RTC_CTL_BIT_EN_OSC (1<<7) /* Bit 7 - Enable Oscilator */
+
+#define RTC_SR_BIT_AF 0x01 /* Bit 0 = Alarm Flag */
+#define RTC_SR_BIT_OSF 0x80 /* Bit 7 - Osc Stop Flag */
+
+typedef unsigned char boolean_t;
+
+#ifndef TRUE
+#define TRUE ((boolean_t)(0==0))
+#endif
+#ifndef FALSE
+#define FALSE (!TRUE)
+#endif
+
+const char RtcTodAddr[] = {
+ RTC_TOD_CNT_BYTE0_ADDR,
+ RTC_TOD_CNT_BYTE1_ADDR,
+ RTC_TOD_CNT_BYTE2_ADDR,
+ RTC_TOD_CNT_BYTE3_ADDR
+};
+
+static uchar rtc_read (uchar reg);
+static void rtc_write (uchar reg, uchar val, boolean_t set);
+static void rtc_write_raw (uchar reg, uchar val);
+
+/*
+ * Get the current time from the RTC
+ */
+void rtc_get (struct rtc_time *tm){
+
+ unsigned long time1, time2;
+ unsigned int limit;
+ unsigned char tmp;
+ unsigned int i;
+
+ /*
+ * Since the reads are being performed one byte at a time,
+ * there is a chance that a carry will occur during the read.
+ * To detect this, 2 reads are performed and compared.
+ */
+ limit = 10;
+ do {
+ i = 4;
+ time1 = 0;
+ while (i--) {
+ tmp = rtc_read(RtcTodAddr[i]);
+ time1 = (time1 << 8) | (tmp & 0xff);
+ }
+
+ i = 4;
+ time2 = 0;
+ while (i--) {
+ tmp = rtc_read(RtcTodAddr[i]);
+ time2 = (time2 << 8) | (tmp & 0xff);
+ }
+ } while ((time1 != time2) && limit--);
+
+ if (time1 != time2) {
+ printf("can't get consistent time from rtc chip\n");
+ }
+
+ DEBUGR ("Get RTC s since 1.1.1970: %d\n", time1);
+
+ to_tm(time1, tm); /* To Gregorian Date */
+
+ if (rtc_read(RTC_SR_ADDR) & RTC_SR_BIT_OSF)
+ printf ("### Warning: RTC oscillator has stopped\n");
+
+ DEBUGR ("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
+ tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+}
+
+/*
+ * Set the RTC
+ */
+void rtc_set (struct rtc_time *tmp){
+
+ unsigned long time;
+ unsigned i;
+
+ DEBUGR ("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);
+
+ if (tmp->tm_year < 1970 || tmp->tm_year > 2069)
+ printf("WARNING: year should be between 1970 and 2069!\n");
+
+ time = mktime(tmp->tm_year, tmp->tm_mon,
+ tmp->tm_mday, tmp->tm_hour,
+ tmp->tm_min, tmp->tm_sec);
+
+ DEBUGR ("Set RTC s since 1.1.1970: %d (0x%02x)\n", time, time);
+
+ /* write to RTC_TOD_CNT_BYTEn_ADDR */
+ for (i = 0; i <= 3; i++) {
+ rtc_write_raw(RtcTodAddr[i], (unsigned char)(time & 0xff));
+ time = time >> 8;
+ }
+
+ /* Start clock */
+ rtc_write(RTC_CTL_ADDR, RTC_CTL_BIT_EN_OSC, FALSE);
+}
+
+/*
+ * Reset the RTC. We setting the date back to 1970-01-01.
+ * We also enable the oscillator output on the SQW/OUT pin and program
+ * it for 32,768 Hz output. Note that according to the datasheet, turning
+ * on the square wave output increases the current drain on the backup
+ * battery to something between 480nA and 800nA.
+ */
+void rtc_reset (void){
+
+ struct rtc_time tmp;
+
+ /* clear status flags */
+ rtc_write (RTC_SR_ADDR, (RTC_SR_BIT_AF|RTC_SR_BIT_OSF), FALSE); /* clearing OSF and AF */
+
+ /* Initialise DS1374 oriented to MPC8349E-ADS */
+ rtc_write (RTC_CTL_ADDR, (RTC_CTL_BIT_EN_OSC
+ |RTC_CTL_BIT_WACE
+ |RTC_CTL_BIT_AIE), FALSE);/* start osc, disable WACE, clear AIE
+ - set to 0 */
+ rtc_write (RTC_CTL_ADDR, (RTC_CTL_BIT_WD_ALM
+ |RTC_CTL_BIT_WDSTR
+ |RTC_CTL_BIT_RS1
+ |RTC_CTL_BIT_RS2
+ |RTC_CTL_BIT_BBSQW), TRUE);/* disable WD/ALM, WDSTR set to INT-pin,
+ set BBSQW and SQW to 32k
+ - set to 1 */
+ tmp.tm_year = 1970;
+ tmp.tm_mon = 1;
+ tmp.tm_mday= 1;
+ tmp.tm_hour = 0;
+ tmp.tm_min = 0;
+ tmp.tm_sec = 0;
+
+ rtc_set(&tmp);
+
+ printf("RTC: %4d-%02d-%02d %2d:%02d:%02d UTC\n",
+ tmp.tm_year, tmp.tm_mon, tmp.tm_mday,
+ tmp.tm_hour, tmp.tm_min, tmp.tm_sec);
+
+ rtc_write(RTC_WD_ALM_CNT_BYTE2_ADDR,0xAC, TRUE);
+ rtc_write(RTC_WD_ALM_CNT_BYTE1_ADDR,0xDE, TRUE);
+ rtc_write(RTC_WD_ALM_CNT_BYTE2_ADDR,0xAD, TRUE);
+}
+
+/*
+ * Helper functions
+ */
+static uchar rtc_read (uchar reg)
+{
+ return (i2c_reg_read (CFG_I2C_RTC_ADDR, reg));
+}
+
+static void rtc_write (uchar reg, uchar val, boolean_t set)
+{
+ if (set == TRUE) {
+ val |= i2c_reg_read (CFG_I2C_RTC_ADDR, reg);
+ i2c_reg_write (CFG_I2C_RTC_ADDR, reg, val);
+ } else {
+ val = i2c_reg_read (CFG_I2C_RTC_ADDR, reg) & ~val;
+ i2c_reg_write (CFG_I2C_RTC_ADDR, reg, val);
+ }
+}
+
+static void rtc_write_raw (uchar reg, uchar val)
+{
+ i2c_reg_write (CFG_I2C_RTC_ADDR, reg, val);
+}
+#endif
diff --git a/drivers/rtc/ds1556.c b/drivers/rtc/ds1556.c
new file mode 100644
index 0000000..4365cfb
--- /dev/null
+++ b/drivers/rtc/ds1556.c
@@ -0,0 +1,206 @@
+/*
+ * (C) Copyright 2002
+ * ARIO Data Networks, Inc. dchiu@ariodata.com
+ *
+ * modified for DS1556:
+ * Frank Panno <fpanno@delphintech.com>, Delphin Technology AG
+ *
+ * Based on MontaVista DS1743 code and U-Boot mc146818 code
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support for the DS1556 RTC
+ */
+
+/*#define RTC_DEBUG */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+
+
+#if defined(CONFIG_RTC_DS1556) && defined(CONFIG_CMD_DATE)
+
+static uchar rtc_read( unsigned int addr );
+static void rtc_write( unsigned int addr, uchar val);
+static uchar bin2bcd (unsigned int n);
+static unsigned bcd2bin(uchar c);
+
+#define RTC_BASE ( CFG_NVRAM_SIZE + CFG_NVRAM_BASE_ADDR )
+
+#define RTC_YEAR ( RTC_BASE + 0xf )
+#define RTC_MONTH ( RTC_BASE + 0xe )
+#define RTC_DAY_OF_MONTH ( RTC_BASE + 0xd )
+#define RTC_DAY_OF_WEEK ( RTC_BASE + 0xc )
+#define RTC_HOURS ( RTC_BASE + 0xb )
+#define RTC_MINUTES ( RTC_BASE + 0xa )
+#define RTC_SECONDS ( RTC_BASE + 0x9 )
+#define RTC_CENTURY ( RTC_BASE + 0x8 )
+
+#define RTC_CONTROLA RTC_CENTURY
+#define RTC_CONTROLB RTC_SECONDS
+#define RTC_CONTROLC RTC_BASE
+
+#define RTC_CA_WRITE 0x80
+#define RTC_CA_READ 0x40
+
+#define RTC_CB_OSC_DISABLE 0x80
+
+#define RTC_CC_BATTERY_FLAG 0x10
+#define RTC_CC_FREQ_TEST 0x40
+
+/* ------------------------------------------------------------------------- */
+
+void rtc_get( struct rtc_time *tmp )
+{
+ uchar sec, min, hour;
+ uchar mday, wday, mon, year;
+
+ int century;
+
+ uchar reg_a;
+
+ reg_a = rtc_read( RTC_CONTROLA );
+ /* lock clock registers for read */
+ rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_READ ));
+
+ sec = rtc_read( RTC_SECONDS );
+ min = rtc_read( RTC_MINUTES );
+ hour = rtc_read( RTC_HOURS );
+ mday = rtc_read( RTC_DAY_OF_MONTH );
+ wday = rtc_read( RTC_DAY_OF_WEEK );
+ mon = rtc_read( RTC_MONTH );
+ year = rtc_read( RTC_YEAR );
+ century = rtc_read( RTC_CENTURY );
+
+ /* unlock clock registers after read */
+ rtc_write( RTC_CONTROLA, ( reg_a & ~RTC_CA_READ ));
+
+#ifdef RTC_DEBUG
+ printf( "Get RTC year: %02x mon/cent: %02x mon: %02x mday: %02x wday: %02x "
+ "hr: %02x min: %02x sec: %02x\n",
+ year, century, mon, mday, wday,
+ hour, min, sec );
+#endif
+ tmp->tm_sec = bcd2bin( sec & 0x7F );
+ tmp->tm_min = bcd2bin( min & 0x7F );
+ tmp->tm_hour = bcd2bin( hour & 0x3F );
+ tmp->tm_mday = bcd2bin( mday & 0x3F );
+ tmp->tm_mon = bcd2bin( mon & 0x1F );
+ tmp->tm_wday = bcd2bin( wday & 0x07 );
+
+ /* glue year from century and year in century */
+ tmp->tm_year = bcd2bin( year ) +
+ ( bcd2bin( century & 0x3F ) * 100 );
+
+ tmp->tm_yday = 0;
+ tmp->tm_isdst= 0;
+#ifdef RTC_DEBUG
+ printf( "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 );
+#endif
+}
+
+void rtc_set( struct rtc_time *tmp )
+{
+ uchar reg_a;
+#ifdef RTC_DEBUG
+ printf( "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);
+#endif
+ /* lock clock registers for write */
+ reg_a = rtc_read( RTC_CONTROLA );
+ rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_WRITE ));
+
+ rtc_write( RTC_MONTH, bin2bcd( tmp->tm_mon ));
+
+ rtc_write( RTC_DAY_OF_WEEK, bin2bcd( tmp->tm_wday ));
+ rtc_write( RTC_DAY_OF_MONTH, bin2bcd( tmp->tm_mday ));
+ rtc_write( RTC_HOURS, bin2bcd( tmp->tm_hour ));
+ rtc_write( RTC_MINUTES, bin2bcd( tmp->tm_min ));
+ rtc_write( RTC_SECONDS, bin2bcd( tmp->tm_sec ));
+
+ /* break year up into century and year in century */
+ rtc_write( RTC_YEAR, bin2bcd( tmp->tm_year % 100 ));
+ rtc_write( RTC_CENTURY, bin2bcd( tmp->tm_year / 100 ));
+
+ /* unlock clock registers after read */
+ rtc_write( RTC_CONTROLA, ( reg_a & ~RTC_CA_WRITE ));
+}
+
+void rtc_reset (void)
+{
+ uchar reg_a, reg_b, reg_c;
+
+ reg_a = rtc_read( RTC_CONTROLA );
+ reg_b = rtc_read( RTC_CONTROLB );
+
+ if ( reg_b & RTC_CB_OSC_DISABLE )
+ {
+ printf( "real-time-clock was stopped. Now starting...\n" );
+ reg_a |= RTC_CA_WRITE;
+ reg_b &= ~RTC_CB_OSC_DISABLE;
+
+ rtc_write( RTC_CONTROLA, reg_a );
+ rtc_write( RTC_CONTROLB, reg_b );
+ }
+
+ /* make sure read/write clock register bits are cleared */
+ reg_a &= ~( RTC_CA_WRITE | RTC_CA_READ );
+ rtc_write( RTC_CONTROLA, reg_a );
+
+ reg_c = rtc_read( RTC_CONTROLC );
+ if (( reg_c & RTC_CC_BATTERY_FLAG ) == 0 )
+ printf( "RTC battery low. Clock setting may not be reliable.\n" );
+}
+
+/* ------------------------------------------------------------------------- */
+
+static uchar rtc_read( unsigned int addr )
+{
+ uchar val = *(volatile unsigned char*)(addr);
+#ifdef RTC_DEBUG
+ printf( "rtc_read: %x:%x\n", addr, val );
+#endif
+ return( val );
+}
+
+static void rtc_write( unsigned int addr, uchar val )
+{
+#ifdef RTC_DEBUG
+ printf( "rtc_write: %x:%x\n", addr, val );
+#endif
+ *(volatile unsigned char*)(addr) = val;
+}
+
+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));
+}
+
+#endif
diff --git a/drivers/rtc/ds164x.c b/drivers/rtc/ds164x.c
new file mode 100644
index 0000000..bff22b9
--- /dev/null
+++ b/drivers/rtc/ds164x.c
@@ -0,0 +1,200 @@
+/*
+ * (C) Copyright 2002
+ * ARIO Data Networks, Inc. dchiu@ariodata.com
+ *
+ * modified for DS164x:
+ * The LEOX team <team@leox.org>, http://www.leox.org
+ *
+ * Based on MontaVista DS1743 code and U-Boot mc146818 code
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support for the DS164x RTC
+ */
+
+/* #define RTC_DEBUG */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+
+
+#if defined(CONFIG_RTC_DS164x) && defined(CONFIG_CMD_DATE)
+
+static uchar rtc_read(unsigned int addr );
+static void rtc_write(unsigned int addr, uchar val);
+static uchar bin2bcd(unsigned int n);
+static unsigned bcd2bin(uchar c);
+
+#define RTC_EPOCH 2000 /* century */
+
+/*
+ * DS164x registers layout
+ */
+#define RTC_BASE ( CFG_NVRAM_BASE_ADDR + CFG_NVRAM_SIZE )
+
+#define RTC_YEAR ( RTC_BASE + 0x07 )
+#define RTC_MONTH ( RTC_BASE + 0x06 )
+#define RTC_DAY_OF_MONTH ( RTC_BASE + 0x05 )
+#define RTC_DAY_OF_WEEK ( RTC_BASE + 0x04 )
+#define RTC_HOURS ( RTC_BASE + 0x03 )
+#define RTC_MINUTES ( RTC_BASE + 0x02 )
+#define RTC_SECONDS ( RTC_BASE + 0x01 )
+#define RTC_CONTROL ( RTC_BASE + 0x00 )
+
+#define RTC_CONTROLA RTC_CONTROL /* W=bit6, R=bit5 */
+#define RTC_CA_WRITE 0x80
+#define RTC_CA_READ 0x40
+#define RTC_CONTROLB RTC_SECONDS /* OSC=bit7 */
+#define RTC_CB_OSC_DISABLE 0x80
+#define RTC_CONTROLC RTC_DAY_OF_WEEK /* FT=bit6 */
+#define RTC_CC_FREQ_TEST 0x40
+
+/* ------------------------------------------------------------------------- */
+
+void rtc_get( struct rtc_time *tmp )
+{
+ uchar sec, min, hour;
+ uchar mday, wday, mon, year;
+
+ uchar reg_a;
+
+ reg_a = rtc_read( RTC_CONTROLA );
+ /* lock clock registers for read */
+ rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_READ ));
+
+ sec = rtc_read( RTC_SECONDS );
+ min = rtc_read( RTC_MINUTES );
+ hour = rtc_read( RTC_HOURS );
+ mday = rtc_read( RTC_DAY_OF_MONTH );
+ wday = rtc_read( RTC_DAY_OF_WEEK );
+ mon = rtc_read( RTC_MONTH );
+ year = rtc_read( RTC_YEAR );
+
+ /* unlock clock registers after read */
+ rtc_write( RTC_CONTROLA, ( reg_a & ~RTC_CA_READ ));
+
+#ifdef RTC_DEBUG
+ printf( "Get RTC year: %02x mon: %02x mday: %02x wday: %02x "
+ "hr: %02x min: %02x sec: %02x\n",
+ year, mon, mday, wday,
+ hour, min, sec );
+#endif
+ tmp->tm_sec = bcd2bin( sec & 0x7F );
+ tmp->tm_min = bcd2bin( min & 0x7F );
+ tmp->tm_hour = bcd2bin( hour & 0x3F );
+ tmp->tm_mday = bcd2bin( mday & 0x3F );
+ tmp->tm_mon = bcd2bin( mon & 0x1F );
+ tmp->tm_wday = bcd2bin( wday & 0x07 );
+
+ /* glue year in century (2000) */
+ tmp->tm_year = bcd2bin( year ) + RTC_EPOCH;
+
+ tmp->tm_yday = 0;
+ tmp->tm_isdst= 0;
+#ifdef RTC_DEBUG
+ printf( "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 );
+#endif
+}
+
+void rtc_set( struct rtc_time *tmp )
+{
+ uchar reg_a;
+
+#ifdef RTC_DEBUG
+ printf( "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);
+#endif
+ /* lock clock registers for write */
+ reg_a = rtc_read( RTC_CONTROLA );
+ rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_WRITE ));
+
+ rtc_write( RTC_MONTH, bin2bcd( tmp->tm_mon ));
+
+ rtc_write( RTC_DAY_OF_WEEK, bin2bcd( tmp->tm_wday ));
+ rtc_write( RTC_DAY_OF_MONTH, bin2bcd( tmp->tm_mday ));
+ rtc_write( RTC_HOURS, bin2bcd( tmp->tm_hour ));
+ rtc_write( RTC_MINUTES, bin2bcd( tmp->tm_min ));
+ rtc_write( RTC_SECONDS, bin2bcd( tmp->tm_sec ));
+
+ /* break year in century */
+ rtc_write( RTC_YEAR, bin2bcd( tmp->tm_year % 100 ));
+
+ /* unlock clock registers after read */
+ rtc_write( RTC_CONTROLA, ( reg_a & ~RTC_CA_WRITE ));
+}
+
+void rtc_reset (void)
+{
+ uchar reg_a, reg_b;
+
+ reg_a = rtc_read( RTC_CONTROLA );
+ reg_b = rtc_read( RTC_CONTROLB );
+
+ if ( reg_b & RTC_CB_OSC_DISABLE )
+ {
+ printf( "real-time-clock was stopped. Now starting...\n" );
+ reg_a |= RTC_CA_WRITE;
+ reg_b &= ~RTC_CB_OSC_DISABLE;
+
+ rtc_write( RTC_CONTROLA, reg_a );
+ rtc_write( RTC_CONTROLB, reg_b );
+ }
+
+ /* make sure read/write clock register bits are cleared */
+ reg_a &= ~( RTC_CA_WRITE | RTC_CA_READ );
+ rtc_write( RTC_CONTROLA, reg_a );
+}
+
+/* ------------------------------------------------------------------------- */
+
+static uchar rtc_read( unsigned int addr )
+{
+ uchar val = *(volatile unsigned char*)(addr);
+
+#ifdef RTC_DEBUG
+ printf( "rtc_read: %x:%x\n", addr, val );
+#endif
+ return( val );
+}
+
+static void rtc_write( unsigned int addr, uchar val )
+{
+#ifdef RTC_DEBUG
+ printf( "rtc_write: %x:%x\n", addr, val );
+#endif
+ *(volatile unsigned char*)(addr) = val;
+}
+
+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));
+}
+
+#endif
diff --git a/drivers/rtc/ds174x.c b/drivers/rtc/ds174x.c
new file mode 100644
index 0000000..5f85a68
--- /dev/null
+++ b/drivers/rtc/ds174x.c
@@ -0,0 +1,202 @@
+/*
+ * (C) Copyright 2001
+ * ARIO Data Networks, Inc. dchiu@ariodata.com
+ *
+ * Based on MontaVista DS1743 code and U-Boot mc146818 code
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support for the DS174x RTC
+ */
+
+/*#define DEBUG*/
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+
+#if defined(CONFIG_RTC_DS174x) && defined(CONFIG_CMD_DATE)
+
+static uchar rtc_read( unsigned int addr );
+static void rtc_write( unsigned int addr, uchar val);
+static uchar bin2bcd (unsigned int n);
+static unsigned bcd2bin(uchar c);
+
+#define RTC_BASE ( CFG_NVRAM_SIZE + CFG_NVRAM_BASE_ADDR )
+
+#define RTC_YEAR ( RTC_BASE + 7 )
+#define RTC_MONTH ( RTC_BASE + 6 )
+#define RTC_DAY_OF_MONTH ( RTC_BASE + 5 )
+#define RTC_DAY_OF_WEEK ( RTC_BASE + 4 )
+#define RTC_HOURS ( RTC_BASE + 3 )
+#define RTC_MINUTES ( RTC_BASE + 2 )
+#define RTC_SECONDS ( RTC_BASE + 1 )
+#define RTC_CENTURY ( RTC_BASE + 0 )
+
+#define RTC_CONTROLA RTC_CENTURY
+#define RTC_CONTROLB RTC_SECONDS
+#define RTC_CONTROLC RTC_DAY_OF_WEEK
+
+#define RTC_CA_WRITE 0x80
+#define RTC_CA_READ 0x40
+
+#define RTC_CB_OSC_DISABLE 0x80
+
+#define RTC_CC_BATTERY_FLAG 0x80
+#define RTC_CC_FREQ_TEST 0x40
+
+/* ------------------------------------------------------------------------- */
+
+void rtc_get( struct rtc_time *tmp )
+{
+ uchar sec, min, hour;
+ uchar mday, wday, mon, year;
+
+ int century;
+
+ uchar reg_a;
+
+ reg_a = rtc_read( RTC_CONTROLA );
+ /* lock clock registers for read */
+ rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_READ ));
+
+ sec = rtc_read( RTC_SECONDS );
+ min = rtc_read( RTC_MINUTES );
+ hour = rtc_read( RTC_HOURS );
+ mday = rtc_read( RTC_DAY_OF_MONTH );
+ wday = rtc_read( RTC_DAY_OF_WEEK );
+ mon = rtc_read( RTC_MONTH );
+ year = rtc_read( RTC_YEAR );
+ century = rtc_read( RTC_CENTURY );
+
+ /* unlock clock registers after read */
+ rtc_write( RTC_CONTROLA, ( reg_a & ~RTC_CA_READ ));
+
+#ifdef RTC_DEBUG
+ printf( "Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
+ "hr: %02x min: %02x sec: %02x\n",
+ year, mon_cent, mday, wday,
+ hour, min, sec );
+#endif
+ tmp->tm_sec = bcd2bin( sec & 0x7F );
+ tmp->tm_min = bcd2bin( min & 0x7F );
+ tmp->tm_hour = bcd2bin( hour & 0x3F );
+ tmp->tm_mday = bcd2bin( mday & 0x3F );
+ tmp->tm_mon = bcd2bin( mon & 0x1F );
+ tmp->tm_wday = bcd2bin( wday & 0x07 );
+
+ /* glue year from century and year in century */
+ tmp->tm_year = bcd2bin( year ) +
+ ( bcd2bin( century & 0x3F ) * 100 );
+
+ tmp->tm_yday = 0;
+ tmp->tm_isdst= 0;
+#ifdef RTC_DEBUG
+ printf( "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 );
+#endif
+}
+
+void rtc_set( struct rtc_time *tmp )
+{
+ uchar reg_a;
+#ifdef RTC_DEBUG
+ printf( "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);
+#endif
+ /* lock clock registers for write */
+ reg_a = rtc_read( RTC_CONTROLA );
+ rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_WRITE ));
+
+ rtc_write( RTC_MONTH, bin2bcd( tmp->tm_mon ));
+
+ rtc_write( RTC_DAY_OF_WEEK, bin2bcd( tmp->tm_wday ));
+ rtc_write( RTC_DAY_OF_MONTH, bin2bcd( tmp->tm_mday ));
+ rtc_write( RTC_HOURS, bin2bcd( tmp->tm_hour ));
+ rtc_write( RTC_MINUTES, bin2bcd( tmp->tm_min ));
+ rtc_write( RTC_SECONDS, bin2bcd( tmp->tm_sec ));
+
+ /* break year up into century and year in century */
+ rtc_write( RTC_YEAR, bin2bcd( tmp->tm_year % 100 ));
+ rtc_write( RTC_CENTURY, bin2bcd( tmp->tm_year / 100 ));
+
+ /* unlock clock registers after read */
+ rtc_write( RTC_CONTROLA, ( reg_a & ~RTC_CA_WRITE ));
+}
+
+void rtc_reset (void)
+{
+ uchar reg_a, reg_b, reg_c;
+
+ reg_a = rtc_read( RTC_CONTROLA );
+ reg_b = rtc_read( RTC_CONTROLB );
+
+ if ( reg_b & RTC_CB_OSC_DISABLE )
+ {
+ printf( "real-time-clock was stopped. Now starting...\n" );
+ reg_a |= RTC_CA_WRITE;
+ reg_b &= ~RTC_CB_OSC_DISABLE;
+
+ rtc_write( RTC_CONTROLA, reg_a );
+ rtc_write( RTC_CONTROLB, reg_b );
+ }
+
+ /* make sure read/write clock register bits are cleared */
+ reg_a &= ~( RTC_CA_WRITE | RTC_CA_READ );
+ rtc_write( RTC_CONTROLA, reg_a );
+
+ reg_c = rtc_read( RTC_CONTROLC );
+ if (( reg_c & RTC_CC_BATTERY_FLAG ) == 0 )
+ printf( "RTC battery low. Clock setting may not be reliable.\n" );
+}
+
+/* ------------------------------------------------------------------------- */
+
+static uchar rtc_read( unsigned int addr )
+{
+ uchar val = in8( addr );
+#ifdef RTC_DEBUG
+ printf( "rtc_read: %x:%x\n", addr, val );
+#endif
+ return( val );
+}
+
+static void rtc_write( unsigned int addr, uchar val )
+{
+#ifdef RTC_DEBUG
+ printf( "rtc_write: %x:%x\n", addr, val );
+#endif
+ out8( addr, val );
+}
+
+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));
+}
+
+#endif
diff --git a/drivers/rtc/ds3231.c b/drivers/rtc/ds3231.c
new file mode 100644
index 0000000..fe11b86
--- /dev/null
+++ b/drivers/rtc/ds3231.c
@@ -0,0 +1,193 @@
+/*
+ * (C) Copyright 2006
+ * Markus Klotzbuecher, mk@denx.de
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support (no alarms) for Dallas Semiconductor (now Maxim)
+ * Extremly Accurate DS3231 Real Time Clock (RTC).
+ *
+ * copied from ds1337.c
+ */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+#include <i2c.h>
+
+#if defined(CONFIG_RTC_DS3231) && defined(CONFIG_CMD_DATE)
+
+/*---------------------------------------------------------------------*/
+#undef DEBUG_RTC
+
+#ifdef DEBUG_RTC
+#define DEBUGR(fmt,args...) printf(fmt ,##args)
+#else
+#define DEBUGR(fmt,args...)
+#endif
+/*---------------------------------------------------------------------*/
+
+/*
+ * RTC register addresses
+ */
+#define RTC_SEC_REG_ADDR 0x0
+#define RTC_MIN_REG_ADDR 0x1
+#define RTC_HR_REG_ADDR 0x2
+#define RTC_DAY_REG_ADDR 0x3
+#define RTC_DATE_REG_ADDR 0x4
+#define RTC_MON_REG_ADDR 0x5
+#define RTC_YR_REG_ADDR 0x6
+#define RTC_CTL_REG_ADDR 0x0e
+#define RTC_STAT_REG_ADDR 0x0f
+
+
+/*
+ * RTC control register bits
+ */
+#define RTC_CTL_BIT_A1IE 0x1 /* Alarm 1 interrupt enable */
+#define RTC_CTL_BIT_A2IE 0x2 /* Alarm 2 interrupt enable */
+#define RTC_CTL_BIT_INTCN 0x4 /* Interrupt control */
+#define RTC_CTL_BIT_RS1 0x8 /* Rate select 1 */
+#define RTC_CTL_BIT_RS2 0x10 /* Rate select 2 */
+#define RTC_CTL_BIT_DOSC 0x80 /* Disable Oscillator */
+
+/*
+ * RTC status register bits
+ */
+#define RTC_STAT_BIT_A1F 0x1 /* Alarm 1 flag */
+#define RTC_STAT_BIT_A2F 0x2 /* Alarm 2 flag */
+#define RTC_STAT_BIT_OSF 0x80 /* Oscillator stop flag */
+
+
+static uchar rtc_read (uchar reg);
+static void rtc_write (uchar reg, uchar val);
+static uchar bin2bcd (unsigned int n);
+static unsigned bcd2bin (uchar c);
+
+
+/*
+ * Get the current time from the RTC
+ */
+void rtc_get (struct rtc_time *tmp)
+{
+ uchar sec, min, hour, mday, wday, mon_cent, year, control, status;
+
+ control = rtc_read (RTC_CTL_REG_ADDR);
+ status = rtc_read (RTC_STAT_REG_ADDR);
+ sec = rtc_read (RTC_SEC_REG_ADDR);
+ min = rtc_read (RTC_MIN_REG_ADDR);
+ hour = rtc_read (RTC_HR_REG_ADDR);
+ wday = rtc_read (RTC_DAY_REG_ADDR);
+ mday = rtc_read (RTC_DATE_REG_ADDR);
+ mon_cent = rtc_read (RTC_MON_REG_ADDR);
+ year = rtc_read (RTC_YR_REG_ADDR);
+
+ DEBUGR ("Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
+ "hr: %02x min: %02x sec: %02x control: %02x status: %02x\n",
+ year, mon_cent, mday, wday, hour, min, sec, control, status);
+
+ if (status & RTC_STAT_BIT_OSF) {
+ printf ("### Warning: RTC oscillator has stopped\n");
+ /* clear the OSF flag */
+ rtc_write (RTC_STAT_REG_ADDR,
+ rtc_read (RTC_STAT_REG_ADDR) & ~RTC_STAT_BIT_OSF);
+ }
+
+ tmp->tm_sec = bcd2bin (sec & 0x7F);
+ tmp->tm_min = bcd2bin (min & 0x7F);
+ tmp->tm_hour = bcd2bin (hour & 0x3F);
+ tmp->tm_mday = bcd2bin (mday & 0x3F);
+ tmp->tm_mon = bcd2bin (mon_cent & 0x1F);
+ tmp->tm_year = bcd2bin (year) + ((mon_cent & 0x80) ? 2000 : 1900);
+ tmp->tm_wday = bcd2bin ((wday - 1) & 0x07);
+ tmp->tm_yday = 0;
+ tmp->tm_isdst= 0;
+
+ DEBUGR ("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);
+}
+
+
+/*
+ * Set the RTC
+ */
+void rtc_set (struct rtc_time *tmp)
+{
+ uchar century;
+
+ DEBUGR ("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);
+
+ rtc_write (RTC_YR_REG_ADDR, bin2bcd (tmp->tm_year % 100));
+
+ century = (tmp->tm_year >= 2000) ? 0x80 : 0;
+ rtc_write (RTC_MON_REG_ADDR, bin2bcd (tmp->tm_mon) | century);
+
+ rtc_write (RTC_DAY_REG_ADDR, bin2bcd (tmp->tm_wday + 1));
+ rtc_write (RTC_DATE_REG_ADDR, bin2bcd (tmp->tm_mday));
+ rtc_write (RTC_HR_REG_ADDR, bin2bcd (tmp->tm_hour));
+ rtc_write (RTC_MIN_REG_ADDR, bin2bcd (tmp->tm_min));
+ rtc_write (RTC_SEC_REG_ADDR, bin2bcd (tmp->tm_sec));
+}
+
+
+/*
+ * Reset the RTC. We also enable the oscillator output on the
+ * SQW/INTB* pin and program it for 32,768 Hz output. Note that
+ * according to the datasheet, turning on the square wave output
+ * increases the current drain on the backup battery from about
+ * 600 nA to 2uA.
+ */
+void rtc_reset (void)
+{
+ rtc_write (RTC_CTL_REG_ADDR, RTC_CTL_BIT_RS1 | RTC_CTL_BIT_RS2);
+}
+
+
+/*
+ * Helper functions
+ */
+
+static
+uchar rtc_read (uchar reg)
+{
+ return (i2c_reg_read (CFG_I2C_RTC_ADDR, reg));
+}
+
+
+static void rtc_write (uchar reg, uchar val)
+{
+ i2c_reg_write (CFG_I2C_RTC_ADDR, reg, val);
+}
+
+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));
+}
+
+#endif
diff --git a/drivers/rtc/m41t11.c b/drivers/rtc/m41t11.c
new file mode 100644
index 0000000..81da33a
--- /dev/null
+++ b/drivers/rtc/m41t11.c
@@ -0,0 +1,202 @@
+/*
+ * (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?
+ */
+
+/* #define DEBUG 1 */
+
+#include <common.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) && defined(CONFIG_CMD_DATE)
+
+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, &cent, 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, &cent, 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, &cent, 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
diff --git a/drivers/rtc/m41t60.c b/drivers/rtc/m41t60.c
new file mode 100644
index 0000000..7c80143
--- /dev/null
+++ b/drivers/rtc/m41t60.c
@@ -0,0 +1,261 @@
+/*
+ * (C) Copyright 2007
+ * Larry Johnson, lrj@acm.org
+ *
+ * based on rtc/m41t11.c which is ...
+ *
+ * (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
+ */
+
+/*
+ * STMicroelectronics M41T60 serial access real-time clock
+ */
+
+/* #define DEBUG 1 */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+#include <i2c.h>
+
+#if defined(CONFIG_RTC_M41T60) && defined(CFG_I2C_RTC_ADDR) && \
+ defined(CONFIG_CMD_DATE)
+
+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));
+}
+
+/*
+ * Convert between century and "century bits" (CB1 and CB0). These routines
+ * assume years are in the range 1900 - 2299.
+ */
+
+static unsigned char year2cb(unsigned const year)
+{
+ if (year < 1900 || year >= 2300)
+ printf("M41T60 RTC: year %d out of range\n", year);
+
+ return (year / 100) & 0x3;
+}
+
+static unsigned cb2year(unsigned const cb)
+{
+ return 1900 + 100 * ((cb + 1) & 0x3);
+}
+
+/*
+ * 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 0x0
+#define RTC_MIN 0x1
+#define RTC_HOUR 0x2
+#define RTC_DAY 0x3
+#define RTC_DATE 0x4
+#define RTC_MONTH 0x5
+#define RTC_YEAR 0x6
+
+#define RTC_REG_CNT 7
+
+#define RTC_CTRL 0x7
+
+#if defined(DEBUG)
+static void rtc_dump(char const *const label)
+{
+ uchar data[8];
+
+ if (i2c_read(CFG_I2C_RTC_ADDR, 0, 1, data, sizeof(data))) {
+ printf("I2C read failed in rtc_dump()\n");
+ return;
+ }
+ printf("RTC dump %s: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n",
+ label, data[0], data[1], data[2], data[3],
+ data[4], data[5], data[6], data[7]);
+}
+#else
+#define rtc_dump(label)
+#endif
+
+static uchar *rtc_validate(void)
+{
+ /*
+ * This routine uses the OUT bit and the validity of the time values to
+ * determine whether there has been an initial power-up since the last
+ * time the routine was run. It assumes that the OUT bit is not being
+ * used for any other purpose.
+ */
+ static const uchar daysInMonth[0x13] = {
+ 0x00, 0x31, 0x29, 0x31, 0x30, 0x31, 0x30, 0x31,
+ 0x31, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x31, 0x30, 0x31
+ };
+ static uchar data[8];
+ uchar min, date, month, years;
+
+ rtc_dump("begin validate");
+ if (i2c_read(CFG_I2C_RTC_ADDR, 0, 1, data, sizeof(data))) {
+ printf("I2C read failed in rtc_validate()\n");
+ return 0;
+ }
+ /*
+ * If the OUT bit is "1", there has been a loss of power, so stop the
+ * oscillator so it can be "kick-started" as per data sheet.
+ */
+ if (0x00 != (data[RTC_CTRL] & 0x80)) {
+ printf("M41T60 RTC clock lost power.\n");
+ data[RTC_SEC] = 0x80;
+ if (i2c_write(CFG_I2C_RTC_ADDR, RTC_SEC, 1, data, 1)) {
+ printf("I2C write failed in rtc_validate()\n");
+ return 0;
+ }
+ }
+ /*
+ * If the oscillator is stopped or the date is invalid, then reset the
+ * OUT bit to "0", reset the date registers, and start the oscillator.
+ */
+ min = data[RTC_MIN] & 0x7F;
+ date = data[RTC_DATE];
+ month = data[RTC_MONTH] & 0x3F;
+ years = data[RTC_YEAR];
+ if (0x59 < data[RTC_SEC] || 0x09 < (data[RTC_SEC] & 0x0F) ||
+ 0x59 < min || 0x09 < (min & 0x0F) ||
+ 0x23 < data[RTC_HOUR] || 0x09 < (data[RTC_HOUR] & 0x0F) ||
+ 0x07 < data[RTC_DAY] || 0x00 == data[RTC_DAY] ||
+ 0x12 < month ||
+ 0x99 < years || 0x09 < (years & 0x0F) ||
+ daysInMonth[month] < date || 0x09 < (date & 0x0F) || 0x00 == date ||
+ (0x29 == date && 0x02 == month &&
+ ((0x00 != (years & 0x03)) ||
+ (0x00 == years && 0x00 != (data[RTC_MONTH] & 0xC0))))) {
+ printf("Resetting M41T60 RTC clock.\n");
+ /*
+ * Set to 00:00:00 1900-01-01 (Monday)
+ */
+ data[RTC_SEC] = 0x00;
+ data[RTC_MIN] &= 0x80; /* preserve OFIE bit */
+ data[RTC_HOUR] = 0x00;
+ data[RTC_DAY] = 0x02;
+ data[RTC_DATE] = 0x01;
+ data[RTC_MONTH] = 0xC1;
+ data[RTC_YEAR] = 0x00;
+ data[RTC_CTRL] &= 0x7F; /* reset OUT bit */
+
+ if (i2c_write(CFG_I2C_RTC_ADDR, 0, 1, data, sizeof(data))) {
+ printf("I2C write failed in rtc_validate()\n");
+ return 0;
+ }
+ }
+ return data;
+}
+
+void rtc_get(struct rtc_time *tmp)
+{
+ uchar const *const data = rtc_validate();
+
+ if (!data)
+ return;
+
+ tmp->tm_sec = bcd2bin(data[RTC_SEC] & 0x7F);
+ tmp->tm_min = bcd2bin(data[RTC_MIN] & 0x7F);
+ tmp->tm_hour = bcd2bin(data[RTC_HOUR] & 0x3F);
+ tmp->tm_mday = bcd2bin(data[RTC_DATE] & 0x3F);
+ tmp->tm_mon = bcd2bin(data[RTC_MONTH] & 0x1F);
+ tmp->tm_year = cb2year(data[RTC_MONTH] >> 6) + bcd2bin(data[RTC_YEAR]);
+ tmp->tm_wday = bcd2bin(data[RTC_DAY] & 0x07) - 1;
+ 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 *const data = rtc_validate();
+
+ if (!data)
+ return;
+
+ 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] = (data[RTC_SEC] & 0x80) | (bin2bcd(tmp->tm_sec) & 0x7F);
+ data[RTC_MIN] = (data[RTC_MIN] & 0X80) | (bin2bcd(tmp->tm_min) & 0X7F);
+ data[RTC_HOUR] = bin2bcd(tmp->tm_hour) & 0x3F;
+ data[RTC_DATE] = bin2bcd(tmp->tm_mday) & 0x3F;
+ data[RTC_MONTH] = bin2bcd(tmp->tm_mon) & 0x1F;
+ data[RTC_YEAR] = bin2bcd(tmp->tm_year % 100);
+ data[RTC_MONTH] |= year2cb(tmp->tm_year) << 6;
+ data[RTC_DAY] = bin2bcd(tmp->tm_wday + 1) & 0x07;
+ if (i2c_write(CFG_I2C_RTC_ADDR, 0, 1, data, RTC_REG_CNT)) {
+ printf("I2C write failed in rtc_set()\n");
+ return;
+ }
+}
+
+void rtc_reset(void)
+{
+ uchar *const data = rtc_validate();
+ char const *const s = getenv("rtccal");
+
+ if (!data)
+ return;
+
+ rtc_dump("begin reset");
+ /*
+ * If environmental variable "rtccal" is present, it must be a hex value
+ * between 0x00 and 0x3F, inclusive. The five least-significan bits
+ * represent the calibration magnitude, and the sixth bit the sign bit.
+ * If these do not match the contents of the hardware register, that
+ * register is updated. The value 0x00 imples no correction. Consult
+ * the M41T60 documentation for further details.
+ */
+ if (s) {
+ unsigned long const l = simple_strtoul(s, 0, 16);
+
+ if (l <= 0x3F) {
+ if ((data[RTC_CTRL] & 0x3F) != l) {
+ printf("Setting RTC calibration to 0x%02X\n",
+ l);
+ data[RTC_CTRL] &= 0xC0;
+ data[RTC_CTRL] |= (uchar) l;
+ }
+ } else
+ printf("environment parameter \"rtccal\" not valid: "
+ "ignoring\n");
+ }
+ /*
+ * Turn off frequency test.
+ */
+ data[RTC_CTRL] &= 0xBF;
+ if (i2c_write(CFG_I2C_RTC_ADDR, RTC_CTRL, 1, data + RTC_CTRL, 1)) {
+ printf("I2C write failed in rtc_reset()\n");
+ return;
+ }
+ rtc_dump("end reset");
+}
+#endif /* CONFIG_RTC_M41T60 && CFG_I2C_RTC_ADDR && CONFIG_CMD_DATE */
diff --git a/drivers/rtc/m48t35ax.c b/drivers/rtc/m48t35ax.c
new file mode 100644
index 0000000..0a0ffa8
--- /dev/null
+++ b/drivers/rtc/m48t35ax.c
@@ -0,0 +1,166 @@
+/*
+ * (C) Copyright 2001
+ * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support for ST Electronics M48T35Ax RTC
+ */
+
+/*#define DEBUG */
+
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+#include <config.h>
+
+#if defined(CONFIG_RTC_M48T35A) && defined(CONFIG_CMD_DATE)
+
+static uchar rtc_read (uchar reg);
+static void rtc_write (uchar reg, uchar val);
+static uchar bin2bcd (unsigned int n);
+static unsigned bcd2bin(uchar c);
+
+/* ------------------------------------------------------------------------- */
+
+void rtc_get (struct rtc_time *tmp)
+{
+ uchar sec, min, hour, cent_day, date, month, year;
+ uchar ccr; /* Clock control register */
+
+ /* Lock RTC for read using clock control register */
+ ccr = rtc_read(0);
+ ccr = ccr | 0x40;
+ rtc_write(0, ccr);
+
+ sec = rtc_read (0x1);
+ min = rtc_read (0x2);
+ hour = rtc_read (0x3);
+ cent_day= rtc_read (0x4);
+ date = rtc_read (0x5);
+ month = rtc_read (0x6);
+ year = rtc_read (0x7);
+
+ /* UNLock RTC */
+ ccr = rtc_read(0);
+ ccr = ccr & 0xBF;
+ rtc_write(0, ccr);
+
+ debug ( "Get RTC year: %02x month: %02x date: %02x cent_day: %02x "
+ "hr: %02x min: %02x sec: %02x\n",
+ year, month, date, cent_day,
+ hour, min, sec );
+
+ tmp->tm_sec = bcd2bin (sec & 0x7F);
+ tmp->tm_min = bcd2bin (min & 0x7F);
+ tmp->tm_hour = bcd2bin (hour & 0x3F);
+ tmp->tm_mday = bcd2bin (date & 0x3F);
+ tmp->tm_mon = bcd2bin (month & 0x1F);
+ tmp->tm_year = bcd2bin (year) + ((cent_day & 0x10) ? 2000 : 1900);
+ tmp->tm_wday = bcd2bin (cent_day & 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 ccr; /* Clock control register */
+ uchar century;
+
+ 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);
+
+ /* Lock RTC for write using clock control register */
+ ccr = rtc_read(0);
+ ccr = ccr | 0x80;
+ rtc_write(0, ccr);
+
+ rtc_write (0x07, bin2bcd(tmp->tm_year % 100));
+ rtc_write (0x06, bin2bcd(tmp->tm_mon));
+ rtc_write (0x05, bin2bcd(tmp->tm_mday));
+
+ century = ((tmp->tm_year >= 2000) ? 0x10 : 0) | 0x20;
+ rtc_write (0x04, bin2bcd(tmp->tm_wday) | century);
+
+ rtc_write (0x03, bin2bcd(tmp->tm_hour));
+ rtc_write (0x02, bin2bcd(tmp->tm_min ));
+ rtc_write (0x01, bin2bcd(tmp->tm_sec ));
+
+ /* UNLock RTC */
+ ccr = rtc_read(0);
+ ccr = ccr & 0x7F;
+ rtc_write(0, ccr);
+}
+
+void rtc_reset (void)
+{
+ uchar val;
+
+ /* Clear all clock control registers */
+ rtc_write (0x0, 0x80); /* No Read Lock or calibration */
+
+ /* Clear stop bit */
+ val = rtc_read (0x1);
+ val &= 0x7f;
+ rtc_write(0x1, val);
+
+ /* Enable century / disable frequency test */
+ val = rtc_read (0x4);
+ val = (val & 0xBF) | 0x20;
+ rtc_write(0x4, val);
+
+ /* Clear write lock */
+ rtc_write(0x0, 0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+static uchar rtc_read (uchar reg)
+{
+ uchar val;
+ val = *(unsigned char *)
+ ((CFG_NVRAM_BASE_ADDR + CFG_NVRAM_SIZE - 8) + reg);
+ return val;
+}
+
+static void rtc_write (uchar reg, uchar val)
+{
+ *(unsigned char *)
+ ((CFG_NVRAM_BASE_ADDR + CFG_NVRAM_SIZE - 8) + reg) = val;
+}
+
+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));
+}
+
+#endif
diff --git a/drivers/rtc/max6900.c b/drivers/rtc/max6900.c
new file mode 100644
index 0000000..c75a8e0
--- /dev/null
+++ b/drivers/rtc/max6900.c
@@ -0,0 +1,131 @@
+/*
+ * (C) Copyright 2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support for MAXIM MAX6900 RTC
+ */
+
+/* #define DEBUG */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+#include <i2c.h>
+
+#if defined(CONFIG_RTC_MAX6900) && defined(CONFIG_CMD_DATE)
+
+#ifndef CFG_I2C_RTC_ADDR
+#define CFG_I2C_RTC_ADDR 0x50
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+static uchar rtc_read (uchar reg)
+{
+ return (i2c_reg_read (CFG_I2C_RTC_ADDR, reg));
+}
+
+static void rtc_write (uchar reg, uchar val)
+{
+ i2c_reg_write (CFG_I2C_RTC_ADDR, reg, val);
+ udelay(2500);
+}
+
+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));
+}
+
+/* ------------------------------------------------------------------------- */
+
+void rtc_get (struct rtc_time *tmp)
+{
+ uchar sec, min, hour, mday, wday, mon, cent, year;
+ int retry = 1;
+
+ do {
+ sec = rtc_read (0x80);
+ min = rtc_read (0x82);
+ hour = rtc_read (0x84);
+ mday = rtc_read (0x86);
+ mon = rtc_read (0x88);
+ wday = rtc_read (0x8a);
+ year = rtc_read (0x8c);
+ cent = rtc_read (0x92);
+ /*
+ * Check for seconds rollover
+ */
+ if ((sec != 59) || (rtc_read(0x80) == sec)){
+ retry = 0;
+ }
+ } while (retry);
+
+ debug ( "Get RTC year: %02x mon: %02x cent: %02x mday: %02x wday: %02x "
+ "hr: %02x min: %02x sec: %02x\n",
+ year, mon, cent, mday, wday,
+ hour, min, sec );
+
+ tmp->tm_sec = bcd2bin (sec & 0x7F);
+ tmp->tm_min = bcd2bin (min & 0x7F);
+ tmp->tm_hour = bcd2bin (hour & 0x3F);
+ tmp->tm_mday = bcd2bin (mday & 0x3F);
+ tmp->tm_mon = bcd2bin (mon & 0x1F);
+ tmp->tm_year = bcd2bin (year) + bcd2bin(cent) * 100;
+ tmp->tm_wday = bcd2bin (wday & 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)
+{
+
+ 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);
+
+ rtc_write (0x9E, 0x00);
+ rtc_write (0x80, 0); /* Clear seconds to ensure no rollover */
+ rtc_write (0x92, bin2bcd(tmp->tm_year / 100));
+ rtc_write (0x8c, bin2bcd(tmp->tm_year % 100));
+ rtc_write (0x8a, bin2bcd(tmp->tm_wday));
+ rtc_write (0x88, bin2bcd(tmp->tm_mon));
+ rtc_write (0x86, bin2bcd(tmp->tm_mday));
+ rtc_write (0x84, bin2bcd(tmp->tm_hour));
+ rtc_write (0x82, bin2bcd(tmp->tm_min ));
+ rtc_write (0x80, bin2bcd(tmp->tm_sec ));
+}
+
+void rtc_reset (void)
+{
+}
+
+#endif
diff --git a/drivers/rtc/mc146818.c b/drivers/rtc/mc146818.c
new file mode 100644
index 0000000..ab377ed
--- /dev/null
+++ b/drivers/rtc/mc146818.c
@@ -0,0 +1,178 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter MPL AG Switzerland. d.peter@mpl.ch
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support for the MC146818 (PIXX4) RTC
+ */
+
+/*#define DEBUG*/
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+
+#if defined(CONFIG_RTC_MC146818) && defined(CONFIG_CMD_DATE)
+
+static uchar rtc_read (uchar reg);
+static void rtc_write (uchar reg, uchar val);
+static uchar bin2bcd (unsigned int n);
+static unsigned bcd2bin(uchar c);
+
+#define RTC_PORT_MC146818 CFG_ISA_IO_BASE_ADDRESS + 0x70
+#define RTC_SECONDS 0x00
+#define RTC_SECONDS_ALARM 0x01
+#define RTC_MINUTES 0x02
+#define RTC_MINUTES_ALARM 0x03
+#define RTC_HOURS 0x04
+#define RTC_HOURS_ALARM 0x05
+#define RTC_DAY_OF_WEEK 0x06
+#define RTC_DATE_OF_MONTH 0x07
+#define RTC_MONTH 0x08
+#define RTC_YEAR 0x09
+#define RTC_CONFIG_A 0x0A
+#define RTC_CONFIG_B 0x0B
+#define RTC_CONFIG_C 0x0C
+#define RTC_CONFIG_D 0x0D
+
+
+/* ------------------------------------------------------------------------- */
+
+void rtc_get (struct rtc_time *tmp)
+{
+ uchar sec, min, hour, mday, wday, mon, year;
+ /* here check if rtc can be accessed */
+ while((rtc_read(RTC_CONFIG_A)&0x80)==0x80);
+ sec = rtc_read (RTC_SECONDS);
+ min = rtc_read (RTC_MINUTES);
+ hour = rtc_read (RTC_HOURS);
+ mday = rtc_read (RTC_DATE_OF_MONTH);
+ wday = rtc_read (RTC_DAY_OF_WEEK);
+ mon = rtc_read (RTC_MONTH);
+ year = rtc_read (RTC_YEAR);
+#ifdef CONFIG_AMIGAONEG3SE
+ wday -= 1; /* VIA 686 stores Sunday = 1, Monday = 2, ... */
+#endif
+#ifdef RTC_DEBUG
+ printf ( "Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
+ "hr: %02x min: %02x sec: %02x\n",
+ year, mon, mday, wday,
+ hour, min, sec );
+ printf ( "Alarms: month: %02x hour: %02x min: %02x sec: %02x\n",
+ rtc_read (RTC_CONFIG_D) & 0x3F,
+ rtc_read (RTC_HOURS_ALARM),
+ rtc_read (RTC_MINUTES_ALARM),
+ rtc_read (RTC_SECONDS_ALARM) );
+#endif
+ tmp->tm_sec = bcd2bin (sec & 0x7F);
+ tmp->tm_min = bcd2bin (min & 0x7F);
+ tmp->tm_hour = bcd2bin (hour & 0x3F);
+ tmp->tm_mday = bcd2bin (mday & 0x3F);
+ tmp->tm_mon = bcd2bin (mon & 0x1F);
+ tmp->tm_year = bcd2bin (year);
+ tmp->tm_wday = bcd2bin (wday & 0x07);
+ if(tmp->tm_year<70)
+ tmp->tm_year+=2000;
+ else
+ tmp->tm_year+=1900;
+ tmp->tm_yday = 0;
+ tmp->tm_isdst= 0;
+#ifdef RTC_DEBUG
+ printf ( "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);
+#endif
+}
+
+void rtc_set (struct rtc_time *tmp)
+{
+#ifdef RTC_DEBUG
+ printf ( "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);
+#endif
+ rtc_write(RTC_CONFIG_B,0x82); /* disables the RTC to update the regs */
+
+ rtc_write (RTC_YEAR, bin2bcd(tmp->tm_year % 100));
+ rtc_write (RTC_MONTH, bin2bcd(tmp->tm_mon));
+#ifdef CONFIG_AMIGAONEG3SE
+ rtc_write (RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday)+1);
+#else
+ rtc_write (RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday));
+#endif
+ rtc_write (RTC_DATE_OF_MONTH, bin2bcd(tmp->tm_mday));
+ rtc_write (RTC_HOURS, bin2bcd(tmp->tm_hour));
+ rtc_write (RTC_MINUTES, bin2bcd(tmp->tm_min ));
+ rtc_write (RTC_SECONDS, bin2bcd(tmp->tm_sec ));
+ rtc_write(RTC_CONFIG_B,0x02); /* enables the RTC to update the regs */
+
+}
+
+void rtc_reset (void)
+{
+ rtc_write(RTC_CONFIG_B,0x82); /* disables the RTC to update the regs */
+ rtc_write(RTC_CONFIG_A,0x20); /* Normal OP */
+ rtc_write(RTC_CONFIG_B,0x00);
+ rtc_write(RTC_CONFIG_B,0x00);
+ rtc_write(RTC_CONFIG_B,0x02); /* enables the RTC to update the regs */
+}
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CFG_RTC_REG_BASE_ADDR
+/*
+ * use direct memory access
+ */
+static uchar rtc_read (uchar reg)
+{
+ return(in8(CFG_RTC_REG_BASE_ADDR+reg));
+}
+
+static void rtc_write (uchar reg, uchar val)
+{
+ out8(CFG_RTC_REG_BASE_ADDR+reg, val);
+}
+#else
+static uchar rtc_read (uchar reg)
+{
+ out8(RTC_PORT_MC146818,reg);
+ return(in8(RTC_PORT_MC146818+1));
+}
+
+static void rtc_write (uchar reg, uchar val)
+{
+ out8(RTC_PORT_MC146818,reg);
+ out8(RTC_PORT_MC146818+1,val);
+}
+#endif
+
+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));
+}
+
+#endif
diff --git a/drivers/rtc/mcfrtc.c b/drivers/rtc/mcfrtc.c
new file mode 100644
index 0000000..27386e5
--- /dev/null
+++ b/drivers/rtc/mcfrtc.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_MCFRTC) && defined(CONFIG_CMD_DATE)
+
+#include <command.h>
+#include <rtc.h>
+#include <asm/immap.h>
+#include <asm/rtc.h>
+
+#undef RTC_DEBUG
+
+#ifndef CFG_MCFRTC_BASE
+#error RTC_BASE is not defined!
+#endif
+
+#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
+#define STARTOFTIME 1970
+
+void rtc_get(struct rtc_time *tmp)
+{
+ volatile rtc_t *rtc = (rtc_t *) (CFG_MCFRTC_BASE);
+
+ int rtc_days, rtc_hrs, rtc_mins;
+ int tim;
+
+ rtc_days = rtc->days;
+ rtc_hrs = rtc->hourmin >> 8;
+ rtc_mins = RTC_HOURMIN_MINUTES(rtc->hourmin);
+
+ tim = (rtc_days * 24) + rtc_hrs;
+ tim = (tim * 60) + rtc_mins;
+ tim = (tim * 60) + rtc->seconds;
+
+ to_tm(tim, tmp);
+
+ tmp->tm_yday = 0;
+ tmp->tm_isdst = 0;
+
+#ifdef RTC_DEBUG
+ printf("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);
+#endif
+}
+
+void rtc_set(struct rtc_time *tmp)
+{
+ volatile rtc_t *rtc = (rtc_t *) (CFG_MCFRTC_BASE);
+
+ static int month_days[12] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ int days, i, months;
+
+ if (tmp->tm_year > 2037) {
+ printf("Unable to handle. Exceeding integer limitation!\n");
+ tmp->tm_year = 2027;
+ }
+#ifdef RTC_DEBUG
+ printf("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);
+#endif
+
+ /* calculate days by years */
+ for (i = STARTOFTIME, days = 0; i < tmp->tm_year; i++) {
+ days += 365 + isleap(i);
+ }
+
+ /* calculate days by months */
+ months = tmp->tm_mon - 1;
+ for (i = 0; i < months; i++) {
+ days += month_days[i];
+
+ if (i == 1)
+ days += isleap(i);
+ }
+
+ days += tmp->tm_mday - 1;
+
+ rtc->days = days;
+ rtc->hourmin = (tmp->tm_hour << 8) | tmp->tm_min;
+ rtc->seconds = tmp->tm_sec;
+}
+
+void rtc_reset(void)
+{
+ volatile rtc_t *rtc = (rtc_t *) (CFG_MCFRTC_BASE);
+
+ if ((rtc->cr & RTC_CR_EN) == 0) {
+ printf("real-time-clock was stopped. Now starting...\n");
+ rtc->cr |= RTC_CR_EN;
+ }
+
+ rtc->cr |= RTC_CR_SWR;
+}
+
+#endif /* CONFIG_MCFRTC && CONFIG_CMD_DATE */
diff --git a/drivers/rtc/mk48t59.c b/drivers/rtc/mk48t59.c
new file mode 100644
index 0000000..bacdb5b
--- /dev/null
+++ b/drivers/rtc/mk48t59.c
@@ -0,0 +1,237 @@
+/*
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support for the MK48T59 RTC
+ */
+
+#undef RTC_DEBUG
+
+#include <common.h>
+#include <command.h>
+#include <config.h>
+#include <rtc.h>
+#include <mk48t59.h>
+
+#if defined(CONFIG_RTC_MK48T59)
+
+#if defined(CONFIG_BAB7xx)
+
+static uchar rtc_read (short reg)
+{
+ out8(RTC_PORT_ADDR0, reg & 0xFF);
+ out8(RTC_PORT_ADDR1, (reg>>8) & 0xFF);
+ return in8(RTC_PORT_DATA);
+}
+
+static void rtc_write (short reg, uchar val)
+{
+ out8(RTC_PORT_ADDR0, reg & 0xFF);
+ out8(RTC_PORT_ADDR1, (reg>>8) & 0xFF);
+ out8(RTC_PORT_DATA, val);
+}
+
+#elif defined(CONFIG_PCIPPC2)
+
+#include "../board/pcippc2/pcippc2.h"
+
+static uchar rtc_read (short reg)
+{
+ return in8(RTC(reg));
+}
+
+static void rtc_write (short reg, uchar val)
+{
+ out8(RTC(reg),val);
+}
+
+#elif defined(CONFIG_AMIGAONEG3SE)
+
+#include "../board/MAI/AmigaOneG3SE/via686.h"
+#include "../board/MAI/AmigaOneG3SE/memio.h"
+
+
+static uchar rtc_read (short reg)
+{
+ out_byte(CMOS_ADDR, (uint8)reg);
+ return in_byte(CMOS_DATA);
+}
+
+static void rtc_write (short reg, uchar val)
+{
+ out_byte(CMOS_ADDR, (uint8)reg);
+ out_byte(CMOS_DATA, (uint8)val);
+}
+
+#elif defined(CONFIG_EVAL5200)
+
+static uchar rtc_read (short reg)
+{
+ return in8(RTC(reg));
+}
+
+static void rtc_write (short reg, uchar val)
+{
+ out8(RTC(reg),val);
+}
+
+#else
+# error Board specific rtc access functions should be supplied
+#endif
+
+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));
+}
+
+/* ------------------------------------------------------------------------- */
+
+void *nvram_read(void *dest, const short src, size_t count)
+{
+ uchar *d = (uchar *) dest;
+ short s = src;
+
+ while (count--)
+ *d++ = rtc_read(s++);
+
+ return dest;
+}
+
+void nvram_write(short dest, const void *src, size_t count)
+{
+ short d = dest;
+ uchar *s = (uchar *) src;
+
+ while (count--)
+ rtc_write(d++, *s++);
+}
+
+#if defined(CONFIG_CMD_DATE)
+
+/* ------------------------------------------------------------------------- */
+
+void rtc_get (struct rtc_time *tmp)
+{
+ uchar save_ctrl_a;
+ uchar sec, min, hour, mday, wday, mon, year;
+
+ /* Simple: freeze the clock, read it and allow updates again */
+ save_ctrl_a = rtc_read(RTC_CONTROLA);
+
+ /* Set the register to read the value. */
+ save_ctrl_a |= RTC_CA_READ;
+ rtc_write(RTC_CONTROLA, save_ctrl_a);
+
+ sec = rtc_read (RTC_SECONDS);
+ min = rtc_read (RTC_MINUTES);
+ hour = rtc_read (RTC_HOURS);
+ mday = rtc_read (RTC_DAY_OF_MONTH);
+ wday = rtc_read (RTC_DAY_OF_WEEK);
+ mon = rtc_read (RTC_MONTH);
+ year = rtc_read (RTC_YEAR);
+
+ /* re-enable update */
+ save_ctrl_a &= ~RTC_CA_READ;
+ rtc_write(RTC_CONTROLA, save_ctrl_a);
+
+#ifdef RTC_DEBUG
+ printf ( "Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
+ "hr: %02x min: %02x sec: %02x\n",
+ year, mon, mday, wday,
+ hour, min, sec );
+#endif
+ tmp->tm_sec = bcd2bin (sec & 0x7F);
+ tmp->tm_min = bcd2bin (min & 0x7F);
+ tmp->tm_hour = bcd2bin (hour & 0x3F);
+ tmp->tm_mday = bcd2bin (mday & 0x3F);
+ tmp->tm_mon = bcd2bin (mon & 0x1F);
+ tmp->tm_year = bcd2bin (year);
+ tmp->tm_wday = bcd2bin (wday & 0x07);
+ if(tmp->tm_year<70)
+ tmp->tm_year+=2000;
+ else
+ tmp->tm_year+=1900;
+ tmp->tm_yday = 0;
+ tmp->tm_isdst= 0;
+#ifdef RTC_DEBUG
+ printf ( "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);
+#endif
+}
+
+void rtc_set (struct rtc_time *tmp)
+{
+ uchar save_ctrl_a;
+
+#ifdef RTC_DEBUG
+ printf ( "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);
+#endif
+ save_ctrl_a = rtc_read(RTC_CONTROLA);
+
+ save_ctrl_a |= RTC_CA_WRITE;
+ rtc_write(RTC_CONTROLA, save_ctrl_a); /* disables the RTC to update the regs */
+
+ rtc_write (RTC_YEAR, bin2bcd(tmp->tm_year % 100));
+ rtc_write (RTC_MONTH, bin2bcd(tmp->tm_mon));
+
+ rtc_write (RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday));
+ rtc_write (RTC_DAY_OF_MONTH, bin2bcd(tmp->tm_mday));
+ rtc_write (RTC_HOURS, bin2bcd(tmp->tm_hour));
+ rtc_write (RTC_MINUTES, bin2bcd(tmp->tm_min ));
+ rtc_write (RTC_SECONDS, bin2bcd(tmp->tm_sec ));
+
+ save_ctrl_a &= ~RTC_CA_WRITE;
+ rtc_write(RTC_CONTROLA, save_ctrl_a); /* enables the RTC to update the regs */
+}
+
+void rtc_reset (void)
+{
+ uchar control_b;
+
+ /*
+ * Start oscillator here.
+ */
+ control_b = rtc_read(RTC_CONTROLB);
+
+ control_b &= ~RTC_CB_STOP;
+ rtc_write(RTC_CONTROLB, control_b);
+}
+
+void rtc_set_watchdog(short multi, short res)
+{
+ uchar wd_value;
+
+ wd_value = RTC_WDS | ((multi & 0x1F) << 2) | (res & 0x3);
+ rtc_write(RTC_WATCHDOG, wd_value);
+}
+
+#endif
+#endif /* CONFIG_RTC_MK48T59 */
diff --git a/drivers/rtc/mpc5xxx.c b/drivers/rtc/mpc5xxx.c
new file mode 100644
index 0000000..216386a
--- /dev/null
+++ b/drivers/rtc/mpc5xxx.c
@@ -0,0 +1,140 @@
+/*
+ * (C) Copyright 2004
+ * Reinhard Meyer, EMK Elektronik GmbH
+ * r.meyer@emk-elektronik.de
+ * www.emk-elektronik.de
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*****************************************************************************
+ * Date & Time support for internal RTC of MPC52xx
+ *****************************************************************************/
+/*#define DEBUG*/
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+
+#if defined(CONFIG_RTC_MPC5200) && defined(CONFIG_CMD_DATE)
+
+/*****************************************************************************
+ * this structure should be defined in mpc5200.h ...
+ *****************************************************************************/
+typedef struct rtc5200 {
+ volatile ulong tsr; /* MBAR+0x800: time set register */
+ volatile ulong dsr; /* MBAR+0x804: data set register */
+ volatile ulong nysr; /* MBAR+0x808: new year and stopwatch register */
+ volatile ulong aier; /* MBAR+0x80C: alarm and interrupt enable register */
+ volatile ulong ctr; /* MBAR+0x810: current time register */
+ volatile ulong cdr; /* MBAR+0x814: current data register */
+ volatile ulong asir; /* MBAR+0x818: alarm and stopwatch interupt register */
+ volatile ulong piber; /* MBAR+0x81C: periodic interrupt and bus error register */
+ volatile ulong trdr; /* MBAR+0x820: test register/divides register */
+} RTC5200;
+
+#define RTC_SET 0x02000000
+#define RTC_PAUSE 0x01000000
+
+/*****************************************************************************
+ * get time
+ *****************************************************************************/
+void rtc_get (struct rtc_time *tmp)
+{
+ RTC5200 *rtc = (RTC5200 *) (CFG_MBAR+0x800);
+ ulong time, date, time2;
+
+ /* read twice to avoid getting a funny time when the second is just changing */
+ do {
+ time = rtc->ctr;
+ date = rtc->cdr;
+ time2 = rtc->ctr;
+ } while (time != time2);
+
+ tmp->tm_year = date & 0xfff;
+ tmp->tm_mon = (date >> 24) & 0xf;
+ tmp->tm_mday = (date >> 16) & 0x1f;
+ tmp->tm_wday = (date >> 21) & 7;
+ /* sunday is 7 in 5200 but 0 in rtc_time */
+ if (tmp->tm_wday == 7)
+ tmp->tm_wday = 0;
+ tmp->tm_hour = (time >> 16) & 0x1f;
+ tmp->tm_min = (time >> 8) & 0x3f;
+ tmp->tm_sec = time & 0x3f;
+
+ 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);
+}
+
+/*****************************************************************************
+ * set time
+ *****************************************************************************/
+void rtc_set (struct rtc_time *tmp)
+{
+ RTC5200 *rtc = (RTC5200 *) (CFG_MBAR+0x800);
+ ulong time, date, year;
+
+ 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);
+
+ time = (tmp->tm_hour << 16) | (tmp->tm_min << 8) | tmp->tm_sec;
+ date = (tmp->tm_mon << 16) | tmp->tm_mday;
+ if (tmp->tm_wday == 0)
+ date |= (7 << 8);
+ else
+ date |= (tmp->tm_wday << 8);
+ year = tmp->tm_year;
+
+ /* mask unwanted bits that might show up when rtc_time is corrupt */
+ time &= 0x001f3f3f;
+ date &= 0x001f071f;
+ year &= 0x00000fff;
+
+ /* pause and set the RTC */
+ rtc->nysr = year;
+ rtc->dsr = date | RTC_PAUSE;
+ udelay (1000);
+ rtc->dsr = date | RTC_PAUSE | RTC_SET;
+ udelay (1000);
+ rtc->dsr = date | RTC_PAUSE;
+ udelay (1000);
+ rtc->dsr = date;
+ udelay (1000);
+
+ rtc->tsr = time | RTC_PAUSE;
+ udelay (1000);
+ rtc->tsr = time | RTC_PAUSE | RTC_SET;
+ udelay (1000);
+ rtc->tsr = time | RTC_PAUSE;
+ udelay (1000);
+ rtc->tsr = time;
+ udelay (1000);
+}
+
+/*****************************************************************************
+ * reset rtc circuit
+ *****************************************************************************/
+void rtc_reset (void)
+{
+ return; /* nothing to do */
+}
+
+#endif
diff --git a/drivers/rtc/mpc8xx.c b/drivers/rtc/mpc8xx.c
new file mode 100644
index 0000000..8d10c0e
--- /dev/null
+++ b/drivers/rtc/mpc8xx.c
@@ -0,0 +1,73 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support for internal RTC of MPC8xx
+ */
+
+/*#define DEBUG*/
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+
+#if defined(CONFIG_RTC_MPC8xx) && defined(CONFIG_CMD_DATE)
+
+/* ------------------------------------------------------------------------- */
+
+void rtc_get (struct rtc_time *tmp)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ ulong tim;
+
+ tim = immr->im_sit.sit_rtc;
+
+ to_tm (tim, tmp);
+
+ 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)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ ulong tim;
+
+ 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);
+
+ tim = mktime (tmp->tm_year, tmp->tm_mon, tmp->tm_mday,
+ tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+
+ immr->im_sitk.sitk_rtck = KAPWR_KEY;
+ immr->im_sit.sit_rtc = tim;
+}
+
+void rtc_reset (void)
+{
+ return; /* nothing to do */
+}
+
+#endif
diff --git a/drivers/rtc/pcf8563.c b/drivers/rtc/pcf8563.c
new file mode 100644
index 0000000..2d73d5d
--- /dev/null
+++ b/drivers/rtc/pcf8563.c
@@ -0,0 +1,144 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support for Philips PCF8563 RTC
+ */
+
+/* #define DEBUG */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+#include <i2c.h>
+
+#if defined(CONFIG_RTC_PCF8563) && defined(CONFIG_CMD_DATE)
+
+static uchar rtc_read (uchar reg);
+static void rtc_write (uchar reg, uchar val);
+static uchar bin2bcd (unsigned int n);
+static unsigned bcd2bin(uchar c);
+
+/* ------------------------------------------------------------------------- */
+
+void rtc_get (struct rtc_time *tmp)
+{
+ uchar sec, min, hour, mday, wday, mon_cent, year;
+
+ sec = rtc_read (0x02);
+ min = rtc_read (0x03);
+ hour = rtc_read (0x04);
+ mday = rtc_read (0x05);
+ wday = rtc_read (0x06);
+ mon_cent= rtc_read (0x07);
+ year = rtc_read (0x08);
+
+ debug ( "Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
+ "hr: %02x min: %02x sec: %02x\n",
+ year, mon_cent, mday, wday,
+ hour, min, sec );
+ debug ( "Alarms: wday: %02x day: %02x hour: %02x min: %02x\n",
+ rtc_read (0x0C),
+ rtc_read (0x0B),
+ rtc_read (0x0A),
+ rtc_read (0x09) );
+
+ if (sec & 0x80) {
+ puts ("### Warning: RTC Low Voltage - date/time not reliable\n");
+ }
+
+ tmp->tm_sec = bcd2bin (sec & 0x7F);
+ tmp->tm_min = bcd2bin (min & 0x7F);
+ tmp->tm_hour = bcd2bin (hour & 0x3F);
+ tmp->tm_mday = bcd2bin (mday & 0x3F);
+ tmp->tm_mon = bcd2bin (mon_cent & 0x1F);
+ tmp->tm_year = bcd2bin (year) + ((mon_cent & 0x80) ? 2000 : 1900);
+ tmp->tm_wday = bcd2bin (wday & 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 century;
+
+ 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);
+
+ rtc_write (0x08, bin2bcd(tmp->tm_year % 100));
+
+ century = (tmp->tm_year >= 2000) ? 0x80 : 0;
+ rtc_write (0x07, bin2bcd(tmp->tm_mon) | century);
+
+ rtc_write (0x06, bin2bcd(tmp->tm_wday));
+ rtc_write (0x05, bin2bcd(tmp->tm_mday));
+ rtc_write (0x04, bin2bcd(tmp->tm_hour));
+ rtc_write (0x03, bin2bcd(tmp->tm_min ));
+ rtc_write (0x02, bin2bcd(tmp->tm_sec ));
+}
+
+void rtc_reset (void)
+{
+ /* clear all control & status registers */
+ rtc_write (0x00, 0x00);
+ rtc_write (0x01, 0x00);
+ rtc_write (0x0D, 0x00);
+
+ /* clear Voltage Low bit */
+ rtc_write (0x02, rtc_read (0x02) & 0x7F);
+
+ /* reset all alarms */
+ rtc_write (0x09, 0x00);
+ rtc_write (0x0A, 0x00);
+ rtc_write (0x0B, 0x00);
+ rtc_write (0x0C, 0x00);
+}
+
+/* ------------------------------------------------------------------------- */
+
+static uchar rtc_read (uchar reg)
+{
+ return (i2c_reg_read (CFG_I2C_RTC_ADDR, reg));
+}
+
+static void rtc_write (uchar reg, uchar val)
+{
+ i2c_reg_write (CFG_I2C_RTC_ADDR, reg, val);
+}
+
+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));
+}
+
+#endif
diff --git a/drivers/rtc/rs5c372.c b/drivers/rtc/rs5c372.c
new file mode 100644
index 0000000..3d1346e
--- /dev/null
+++ b/drivers/rtc/rs5c372.c
@@ -0,0 +1,302 @@
+/*
+ * rs5c372.c
+ *
+ * Device driver for Ricoh's Real Time Controller RS5C372A.
+ *
+ * Copyright (C) 2004 Gary Jennejohn garyj@denx.de
+ *
+ * Based in part in ds1307.c -
+ * (C) Copyright 2001, 2002, 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Keith Outwater, keith_outwater@mvis.com`
+ * Steven Scholz, steven.scholz@imc-berlin.de
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+#include <i2c.h>
+
+#if defined(CONFIG_RTC_RS5C372A) && defined(CONFIG_CMD_DATE)
+/*
+ * Reads are always done starting with register 15, which requires some
+ * jumping-through-hoops to access the data correctly.
+ *
+ * Writes are always done starting with register 0.
+ */
+
+#define DEBUG 0
+
+#if DEBUG
+static unsigned int rtc_debug = DEBUG;
+#else
+#define rtc_debug 0 /* gcc will remove all the debug code for us */
+#endif
+
+#ifndef CFG_I2C_RTC_ADDR
+#define CFG_I2C_RTC_ADDR 0x32
+#endif
+
+#define RS5C372_RAM_SIZE 0x10
+#define RATE_32000HZ 0x80 /* Rate Select 32.000KHz */
+#define RATE_32768HZ 0x00 /* Rate Select 32.768KHz */
+
+#define STATUS_XPT 0x10 /* data invalid because voltage was 0 */
+
+#define USE_24HOUR_MODE 0x20
+#define TWELVE_HOUR_MODE(n) ((((n) >> 5) & 1) == 0)
+#define HOURS_AP(n) (((n) >> 5) & 1)
+#define HOURS_12(n) bcd2bin((n) & 0x1F)
+#define HOURS_24(n) bcd2bin((n) & 0x3F)
+
+
+static uchar bin2bcd (unsigned int n);
+static unsigned bcd2bin (uchar c);
+
+static int setup_done = 0;
+
+static int
+rs5c372_readram(unsigned char *buf, int len)
+{
+ int ret;
+
+ ret = i2c_read(CFG_I2C_RTC_ADDR, 0, 0, buf, len);
+ if (ret != 0) {
+ printf("%s: failed to read\n", __FUNCTION__);
+ return ret;
+ }
+
+ if (buf[0] & STATUS_XPT)
+ printf("### Warning: RTC lost power\n");
+
+ return ret;
+}
+
+static void
+rs5c372_enable(void)
+{
+ unsigned char buf[RS5C372_RAM_SIZE + 1];
+ int ret;
+
+ /* note that this returns reg. 15 in buf[1] */
+ ret = rs5c372_readram(&buf[1], RS5C372_RAM_SIZE);
+ if (ret != 0) {
+ printf("%s: failed\n", __FUNCTION__);
+ return;
+ }
+
+ buf[0] = 0;
+ /* we want to start writing at register 0 so we have to copy the */
+ /* register contents up one slot */
+ for (ret = 2; ret < 9; ret++)
+ buf[ret - 1] = buf[ret];
+ /* registers 0 to 6 (time values) are not touched */
+ buf[8] = RATE_32768HZ; /* reg. 7 */
+ buf[9] = 0; /* reg. 8 */
+ buf[10] = 0; /* reg. 9 */
+ buf[11] = 0; /* reg. 10 */
+ buf[12] = 0; /* reg. 11 */
+ buf[13] = 0; /* reg. 12 */
+ buf[14] = 0; /* reg. 13 */
+ buf[15] = 0; /* reg. 14 */
+ buf[16] = USE_24HOUR_MODE; /* reg. 15 */
+ ret = i2c_write(CFG_I2C_RTC_ADDR, 0, 0, buf, RS5C372_RAM_SIZE+1);
+ if (ret != 0) {
+ printf("%s: failed\n", __FUNCTION__);
+ return;
+ }
+ setup_done = 1;
+
+ return;
+}
+
+static void
+rs5c372_convert_to_time(struct rtc_time *dt, unsigned char *buf)
+{
+ /* buf[0] is register 15 */
+ dt->tm_sec = bcd2bin(buf[1]);
+ dt->tm_min = bcd2bin(buf[2]);
+
+ if (TWELVE_HOUR_MODE(buf[0])) {
+ dt->tm_hour = HOURS_12(buf[3]);
+ if (HOURS_AP(buf[3])) /* PM */
+ dt->tm_hour += 12;
+ } else /* 24-hour-mode */
+ dt->tm_hour = HOURS_24(buf[3]);
+
+ dt->tm_mday = bcd2bin(buf[5]);
+ dt->tm_mon = bcd2bin(buf[6]);
+ dt->tm_year = bcd2bin(buf[7]);
+ if (dt->tm_year >= 70)
+ dt->tm_year += 1900;
+ else
+ dt->tm_year += 2000;
+ /* 0 is Sunday */
+ dt->tm_wday = bcd2bin(buf[4] & 0x07);
+ dt->tm_yday = 0;
+ dt->tm_isdst= 0;
+
+ if(rtc_debug > 2) {
+ printf("rs5c372_convert_to_time: year = %d\n", dt->tm_year);
+ printf("rs5c372_convert_to_time: mon = %d\n", dt->tm_mon);
+ printf("rs5c372_convert_to_time: mday = %d\n", dt->tm_mday);
+ printf("rs5c372_convert_to_time: hour = %d\n", dt->tm_hour);
+ printf("rs5c372_convert_to_time: min = %d\n", dt->tm_min);
+ printf("rs5c372_convert_to_time: sec = %d\n", dt->tm_sec);
+ }
+}
+
+/*
+ * Get the current time from the RTC
+ */
+void
+rtc_get (struct rtc_time *tmp)
+{
+ unsigned char buf[RS5C372_RAM_SIZE];
+ int ret;
+
+ if (!setup_done)
+ rs5c372_enable();
+
+ if (!setup_done)
+ return;
+
+ memset(buf, 0, sizeof(buf));
+
+ /* note that this returns reg. 15 in buf[0] */
+ ret = rs5c372_readram(buf, RS5C372_RAM_SIZE);
+ if (ret != 0) {
+ printf("%s: failed\n", __FUNCTION__);
+ return;
+ }
+
+ rs5c372_convert_to_time(tmp, buf);
+
+ return;
+}
+
+/*
+ * Set the RTC
+ */
+void
+rtc_set (struct rtc_time *tmp)
+{
+ unsigned char buf[8], reg15;
+ int ret;
+
+ if (!setup_done)
+ rs5c372_enable();
+
+ if (!setup_done)
+ return;
+
+ if(rtc_debug > 2) {
+ printf("rtc_set: tm_year = %d\n", tmp->tm_year);
+ printf("rtc_set: tm_mon = %d\n", tmp->tm_mon);
+ printf("rtc_set: tm_mday = %d\n", tmp->tm_mday);
+ printf("rtc_set: tm_hour = %d\n", tmp->tm_hour);
+ printf("rtc_set: tm_min = %d\n", tmp->tm_min);
+ printf("rtc_set: tm_sec = %d\n", tmp->tm_sec);
+ }
+
+ memset(buf, 0, sizeof(buf));
+
+ /* only read register 15 */
+ ret = i2c_read(CFG_I2C_RTC_ADDR, 0, 0, buf, 1);
+
+ if (ret == 0) {
+ /* need to save register 15 */
+ reg15 = buf[0];
+ buf[0] = 0; /* register address on RS5C372 */
+ buf[1] = bin2bcd(tmp->tm_sec);
+ buf[2] = bin2bcd(tmp->tm_min);
+ /* need to handle 12 hour mode */
+ if (TWELVE_HOUR_MODE(reg15)) {
+ if (tmp->tm_hour >= 12) { /* PM */
+ /* 12 PM is a special case */
+ if (tmp->tm_hour == 12)
+ buf[3] = bin2bcd(tmp->tm_hour);
+ else
+ buf[3] = bin2bcd(tmp->tm_hour - 12);
+ buf[3] |= 0x20;
+ }
+ } else {
+ buf[3] = bin2bcd(tmp->tm_hour);
+ }
+
+ buf[4] = bin2bcd(tmp->tm_wday);
+ buf[5] = bin2bcd(tmp->tm_mday);
+ buf[6] = bin2bcd(tmp->tm_mon);
+ if (tmp->tm_year < 1970 || tmp->tm_year > 2069)
+ printf("WARNING: year should be between 1970 and 2069!\n");
+ buf[7] = bin2bcd(tmp->tm_year % 100);
+
+ ret = i2c_write(CFG_I2C_RTC_ADDR, 0, 0, buf, 8);
+ if (ret != 0)
+ printf("rs5c372_set_datetime(), i2c_master_send() returned %d\n",ret);
+ }
+
+ return;
+}
+
+/*
+ * Reset the RTC. We set the date back to 1970-01-01.
+ */
+void
+rtc_reset (void)
+{
+ struct rtc_time tmp;
+
+ if (!setup_done)
+ rs5c372_enable();
+
+ if (!setup_done)
+ return;
+
+ tmp.tm_year = 1970;
+ tmp.tm_mon = 1;
+ /* Jan. 1, 1970 was a Thursday */
+ tmp.tm_wday= 4;
+ tmp.tm_mday= 1;
+ tmp.tm_hour = 0;
+ tmp.tm_min = 0;
+ tmp.tm_sec = 0;
+
+ rtc_set(&tmp);
+
+ printf ("RTC: %4d-%02d-%02d %2d:%02d:%02d UTC\n",
+ tmp.tm_year, tmp.tm_mon, tmp.tm_mday,
+ tmp.tm_hour, tmp.tm_min, tmp.tm_sec);
+
+ return;
+}
+
+static unsigned int
+bcd2bin (unsigned char n)
+{
+ return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
+}
+
+static unsigned char
+bin2bcd (unsigned int n)
+{
+ return (((n / 10) << 4) | (n % 10));
+}
+#endif
diff --git a/drivers/rtc/rx8025.c b/drivers/rtc/rx8025.c
new file mode 100644
index 0000000..6c94ae1
--- /dev/null
+++ b/drivers/rtc/rx8025.c
@@ -0,0 +1,227 @@
+/*
+ * (C) Copyright 2007
+ * Matthias Fuchs, esd gmbh, matthias.fuchs@esd-electronics.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Epson RX8025 RTC driver.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+#include <i2c.h>
+
+#if defined(CONFIG_RTC_RX8025) && defined(CONFIG_CMD_DATE)
+
+/*---------------------------------------------------------------------*/
+#undef DEBUG_RTC
+
+#ifdef DEBUG_RTC
+#define DEBUGR(fmt,args...) printf(fmt ,##args)
+#else
+#define DEBUGR(fmt,args...)
+#endif
+/*---------------------------------------------------------------------*/
+
+#ifndef CFG_I2C_RTC_ADDR
+# define CFG_I2C_RTC_ADDR 0x32
+#endif
+
+/*
+ * RTC register addresses
+ */
+#define RTC_SEC_REG_ADDR 0x00
+#define RTC_MIN_REG_ADDR 0x01
+#define RTC_HR_REG_ADDR 0x02
+#define RTC_DAY_REG_ADDR 0x03
+#define RTC_DATE_REG_ADDR 0x04
+#define RTC_MON_REG_ADDR 0x05
+#define RTC_YR_REG_ADDR 0x06
+
+#define RTC_CTL1_REG_ADDR 0x0e
+#define RTC_CTL2_REG_ADDR 0x0f
+
+/*
+ * Control register 1 bits
+ */
+#define RTC_CTL1_BIT_2412 0x20
+
+/*
+ * Control register 2 bits
+ */
+#define RTC_CTL2_BIT_PON 0x10
+#define RTC_CTL2_BIT_VDET 0x40
+#define RTC_CTL2_BIT_XST 0x20
+#define RTC_CTL2_BIT_VDSL 0x80
+
+/*
+ * Note: the RX8025 I2C RTC requires register
+ * reads and write to consist of a single bus
+ * cycle. It is not allowed to write the register
+ * address in a first cycle that is terminated by
+ * a STOP condition. The chips needs a 'restart'
+ * sequence (start sequence without a prior stop).
+ * This driver has been written for a 4xx board.
+ * U-Boot's 4xx i2c driver is currently not capable
+ * to generate such cycles to some work arounds
+ * are used.
+ */
+
+/* static uchar rtc_read (uchar reg); */
+#define rtc_read(reg) buf[((reg) + 1) & 0xf]
+
+static void rtc_write (uchar reg, uchar val);
+static uchar bin2bcd (unsigned int n);
+static unsigned bcd2bin (uchar c);
+
+/*
+ * Get the current time from the RTC
+ */
+void rtc_get (struct rtc_time *tmp)
+{
+ uchar sec, min, hour, mday, wday, mon, year, ctl2;
+ uchar buf[16];
+
+ if (i2c_read(CFG_I2C_RTC_ADDR, 0, 0, buf, 16))
+ printf("Error reading from RTC\n");
+
+ sec = rtc_read(RTC_SEC_REG_ADDR);
+ min = rtc_read(RTC_MIN_REG_ADDR);
+ hour = rtc_read(RTC_HR_REG_ADDR);
+ wday = rtc_read(RTC_DAY_REG_ADDR);
+ mday = rtc_read(RTC_DATE_REG_ADDR);
+ mon = rtc_read(RTC_MON_REG_ADDR);
+ year = rtc_read(RTC_YR_REG_ADDR);
+
+ DEBUGR ("Get RTC year: %02x mon: %02x mday: %02x wday: %02x "
+ "hr: %02x min: %02x sec: %02x\n",
+ year, mon, mday, wday, hour, min, sec);
+
+ /* dump status */
+ ctl2 = rtc_read(RTC_CTL2_REG_ADDR);
+ if (ctl2 & RTC_CTL2_BIT_PON)
+ printf("RTC: power-on detected\n");
+
+ if (ctl2 & RTC_CTL2_BIT_VDET)
+ printf("RTC: voltage drop detected\n");
+
+ if (!(ctl2 & RTC_CTL2_BIT_XST))
+ printf("RTC: oscillator stop detected\n");
+
+ tmp->tm_sec = bcd2bin (sec & 0x7F);
+ tmp->tm_min = bcd2bin (min & 0x7F);
+ tmp->tm_hour = bcd2bin (hour & 0x3F);
+ tmp->tm_mday = bcd2bin (mday & 0x3F);
+ tmp->tm_mon = bcd2bin (mon & 0x1F);
+ tmp->tm_year = bcd2bin (year) + ( bcd2bin (year) >= 70 ? 1900 : 2000);
+ tmp->tm_wday = bcd2bin (wday & 0x07);
+ tmp->tm_yday = 0;
+ tmp->tm_isdst= 0;
+
+ DEBUGR ("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);
+}
+
+
+/*
+ * Set the RTC
+ */
+void rtc_set (struct rtc_time *tmp)
+{
+ DEBUGR ("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);
+
+ if (tmp->tm_year < 1970 || tmp->tm_year > 2069)
+ printf("WARNING: year should be between 1970 and 2069!\n");
+
+ rtc_write (RTC_YR_REG_ADDR, bin2bcd (tmp->tm_year % 100));
+ rtc_write (RTC_MON_REG_ADDR, bin2bcd (tmp->tm_mon));
+ rtc_write (RTC_DAY_REG_ADDR, bin2bcd (tmp->tm_wday));
+ rtc_write (RTC_DATE_REG_ADDR, bin2bcd (tmp->tm_mday));
+ rtc_write (RTC_HR_REG_ADDR, bin2bcd (tmp->tm_hour));
+ rtc_write (RTC_MIN_REG_ADDR, bin2bcd (tmp->tm_min));
+ rtc_write (RTC_SEC_REG_ADDR, bin2bcd (tmp->tm_sec));
+
+ rtc_write (RTC_CTL1_REG_ADDR, RTC_CTL1_BIT_2412);
+}
+
+
+/*
+ * Reset the RTC. We setting the date back to 1970-01-01.
+ */
+void rtc_reset (void)
+{
+ struct rtc_time tmp;
+ uchar buf[16];
+ uchar ctl2;
+
+ if (i2c_read(CFG_I2C_RTC_ADDR, 0, 0, buf, 16))
+ printf("Error reading from RTC\n");
+
+ ctl2 = rtc_read(RTC_CTL2_REG_ADDR);
+ ctl2 &= ~(RTC_CTL2_BIT_PON | RTC_CTL2_BIT_VDET);
+ ctl2 |= RTC_CTL2_BIT_XST | RTC_CTL2_BIT_VDSL;
+ rtc_write (RTC_CTL2_REG_ADDR, ctl2);
+
+ tmp.tm_year = 1970;
+ tmp.tm_mon = 1;
+ tmp.tm_mday= 1;
+ tmp.tm_hour = 0;
+ tmp.tm_min = 0;
+ tmp.tm_sec = 0;
+
+ rtc_set(&tmp);
+
+ printf ( "RTC: %4d-%02d-%02d %2d:%02d:%02d UTC\n",
+ tmp.tm_year, tmp.tm_mon, tmp.tm_mday,
+ tmp.tm_hour, tmp.tm_min, tmp.tm_sec);
+
+ return;
+}
+
+
+/*
+ * Helper functions
+ */
+static void rtc_write (uchar reg, uchar val)
+{
+ uchar buf[2];
+ buf[0] = reg << 4;
+ buf[1] = val;
+ if (i2c_write(CFG_I2C_RTC_ADDR, 0, 0, buf, 2) != 0)
+ printf("Error writing to RTC\n");
+
+}
+
+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));
+}
+
+#endif /* CONFIG_RTC_RX8025 && (CFG_COMMANDS & CFG_CMD_DATE) */
diff --git a/drivers/rtc/s3c24x0_rtc.c b/drivers/rtc/s3c24x0_rtc.c
new file mode 100644
index 0000000..7f8b4fa
--- /dev/null
+++ b/drivers/rtc/s3c24x0_rtc.c
@@ -0,0 +1,178 @@
+/*
+ * (C) Copyright 2003
+ * David Müller ELSOFT AG Switzerland. d.mueller@elsoft.ch
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support for the built-in Samsung S3C24X0 RTC
+ */
+
+#include <common.h>
+#include <command.h>
+
+#if defined(CONFIG_RTC_S3C24X0) && (defined(CONFIG_CMD_DATE))
+
+#if defined(CONFIG_S3C2400)
+#include <s3c2400.h>
+#elif defined(CONFIG_S3C2410)
+#include <s3c2410.h>
+#endif
+
+#include <rtc.h>
+
+/*#define DEBUG*/
+
+typedef enum {
+ RTC_ENABLE,
+ RTC_DISABLE
+} RTC_ACCESS;
+
+
+static inline void SetRTC_Access(RTC_ACCESS a)
+{
+ S3C24X0_RTC * const rtc = S3C24X0_GetBase_RTC();
+ switch (a) {
+ case RTC_ENABLE:
+ rtc->RTCCON |= 0x01; break;
+
+ case RTC_DISABLE:
+ rtc->RTCCON &= ~0x01; break;
+ }
+}
+
+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));
+}
+
+/* ------------------------------------------------------------------------- */
+
+void rtc_get (struct rtc_time *tmp)
+{
+ S3C24X0_RTC * const rtc = S3C24X0_GetBase_RTC();
+ uchar sec, min, hour, mday, wday, mon, year;
+ uchar a_sec,a_min, a_hour, a_date, a_mon, a_year, a_armed;
+
+ /* enable access to RTC registers */
+ SetRTC_Access(RTC_ENABLE);
+
+ /* read RTC registers */
+ do {
+ sec = rtc->BCDSEC;
+ min = rtc->BCDMIN;
+ hour = rtc->BCDHOUR;
+ mday = rtc->BCDDATE;
+ wday = rtc->BCDDAY;
+ mon = rtc->BCDMON;
+ year = rtc->BCDYEAR;
+ } while (sec != rtc->BCDSEC);
+
+ /* read ALARM registers */
+ a_sec = rtc->ALMSEC;
+ a_min = rtc->ALMMIN;
+ a_hour = rtc->ALMHOUR;
+ a_date = rtc->ALMDATE;
+ a_mon = rtc->ALMMON;
+ a_year = rtc->ALMYEAR;
+ a_armed = rtc->RTCALM;
+
+ /* disable access to RTC registers */
+ SetRTC_Access(RTC_DISABLE);
+
+#ifdef RTC_DEBUG
+ printf ( "Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
+ "hr: %02x min: %02x sec: %02x\n",
+ year, mon, mday, wday,
+ hour, min, sec);
+ printf ( "Alarms: %02x: year: %02x month: %02x date: %02x hour: %02x min: %02x sec: %02x\n",
+ a_armed,
+ a_year, a_mon, a_date,
+ a_hour, a_min, a_sec);
+#endif
+
+ tmp->tm_sec = bcd2bin(sec & 0x7F);
+ tmp->tm_min = bcd2bin(min & 0x7F);
+ tmp->tm_hour = bcd2bin(hour & 0x3F);
+ tmp->tm_mday = bcd2bin(mday & 0x3F);
+ tmp->tm_mon = bcd2bin(mon & 0x1F);
+ tmp->tm_year = bcd2bin(year);
+ tmp->tm_wday = bcd2bin(wday & 0x07);
+ if(tmp->tm_year<70)
+ tmp->tm_year+=2000;
+ else
+ tmp->tm_year+=1900;
+ tmp->tm_yday = 0;
+ tmp->tm_isdst= 0;
+#ifdef RTC_DEBUG
+ printf ( "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);
+#endif
+}
+
+void rtc_set (struct rtc_time *tmp)
+{
+ S3C24X0_RTC * const rtc = S3C24X0_GetBase_RTC();
+ uchar sec, min, hour, mday, wday, mon, year;
+
+#ifdef RTC_DEBUG
+ printf ( "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);
+#endif
+ year = bin2bcd(tmp->tm_year % 100);
+ mon = bin2bcd(tmp->tm_mon);
+ wday = bin2bcd(tmp->tm_wday);
+ mday = bin2bcd(tmp->tm_mday);
+ hour = bin2bcd(tmp->tm_hour);
+ min = bin2bcd(tmp->tm_min);
+ sec = bin2bcd(tmp->tm_sec);
+
+ /* enable access to RTC registers */
+ SetRTC_Access(RTC_ENABLE);
+
+ /* write RTC registers */
+ rtc->BCDSEC = sec;
+ rtc->BCDMIN = min;
+ rtc->BCDHOUR = hour;
+ rtc->BCDDATE = mday;
+ rtc->BCDDAY = wday;
+ rtc->BCDMON = mon;
+ rtc->BCDYEAR = year;
+
+ /* disable access to RTC registers */
+ SetRTC_Access(RTC_DISABLE);
+}
+
+void rtc_reset (void)
+{
+ S3C24X0_RTC * const rtc = S3C24X0_GetBase_RTC();
+
+ rtc->RTCCON = (rtc->RTCCON & ~0x06) | 0x08;
+ rtc->RTCCON &= ~(0x08|0x01);
+}
+
+#endif
diff --git a/drivers/rtc/x1205.c b/drivers/rtc/x1205.c
new file mode 100644
index 0000000..319f051
--- /dev/null
+++ b/drivers/rtc/x1205.c
@@ -0,0 +1,178 @@
+/*
+ * (C) Copyright 2007
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * based on a the Linux rtc-x1207.c driver which is:
+ * Copyright 2004 Karen Spearel
+ * Copyright 2005 Alessandro Zummo
+ *
+ * Information and datasheet:
+ * http://www.intersil.com/cda/deviceinfo/0,1477,X1205,00.html
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Date & Time support for Xicor/Intersil X1205 RTC
+ */
+
+/* #define DEBUG */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+#include <i2c.h>
+#include <bcd.h>
+
+#if defined(CONFIG_RTC_X1205) && defined(CONFIG_CMD_DATE)
+
+#define CCR_SEC 0
+#define CCR_MIN 1
+#define CCR_HOUR 2
+#define CCR_MDAY 3
+#define CCR_MONTH 4
+#define CCR_YEAR 5
+#define CCR_WDAY 6
+#define CCR_Y2K 7
+
+#define X1205_REG_SR 0x3F /* status register */
+#define X1205_REG_Y2K 0x37
+#define X1205_REG_DW 0x36
+#define X1205_REG_YR 0x35
+#define X1205_REG_MO 0x34
+#define X1205_REG_DT 0x33
+#define X1205_REG_HR 0x32
+#define X1205_REG_MN 0x31
+#define X1205_REG_SC 0x30
+#define X1205_REG_DTR 0x13
+#define X1205_REG_ATR 0x12
+#define X1205_REG_INT 0x11
+#define X1205_REG_0 0x10
+#define X1205_REG_Y2K1 0x0F
+#define X1205_REG_DWA1 0x0E
+#define X1205_REG_YRA1 0x0D
+#define X1205_REG_MOA1 0x0C
+#define X1205_REG_DTA1 0x0B
+#define X1205_REG_HRA1 0x0A
+#define X1205_REG_MNA1 0x09
+#define X1205_REG_SCA1 0x08
+#define X1205_REG_Y2K0 0x07
+#define X1205_REG_DWA0 0x06
+#define X1205_REG_YRA0 0x05
+#define X1205_REG_MOA0 0x04
+#define X1205_REG_DTA0 0x03
+#define X1205_REG_HRA0 0x02
+#define X1205_REG_MNA0 0x01
+#define X1205_REG_SCA0 0x00
+
+#define X1205_CCR_BASE 0x30 /* Base address of CCR */
+#define X1205_ALM0_BASE 0x00 /* Base address of ALARM0 */
+
+#define X1205_SR_RTCF 0x01 /* Clock failure */
+#define X1205_SR_WEL 0x02 /* Write Enable Latch */
+#define X1205_SR_RWEL 0x04 /* Register Write Enable */
+
+#define X1205_DTR_DTR0 0x01
+#define X1205_DTR_DTR1 0x02
+#define X1205_DTR_DTR2 0x04
+
+#define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */
+
+static void rtc_write(int reg, u8 val)
+{
+ i2c_write(CFG_I2C_RTC_ADDR, reg, 2, &val, 1);
+}
+
+/*
+ * In the routines that deal directly with the x1205 hardware, we use
+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch
+ * Epoch is initialized as 2000. Time is set to UTC.
+ */
+void rtc_get(struct rtc_time *tm)
+{
+ u8 buf[8];
+
+ i2c_read(CFG_I2C_RTC_ADDR, X1205_CCR_BASE, 2, buf, 8);
+
+ debug("%s: raw read data - sec=%02x, min=%02x, hr=%02x, "
+ "mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n",
+ __FUNCTION__,
+ buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5], buf[6], buf[7]);
+
+ tm->tm_sec = BCD2BIN(buf[CCR_SEC]);
+ tm->tm_min = BCD2BIN(buf[CCR_MIN]);
+ tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
+ tm->tm_mday = BCD2BIN(buf[CCR_MDAY]);
+ tm->tm_mon = BCD2BIN(buf[CCR_MONTH]); /* mon is 0-11 */
+ tm->tm_year = BCD2BIN(buf[CCR_YEAR])
+ + (BCD2BIN(buf[CCR_Y2K]) * 100);
+ tm->tm_wday = buf[CCR_WDAY];
+
+ debug("%s: tm is secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__,
+ tm->tm_sec, tm->tm_min, tm->tm_hour,
+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+}
+
+void rtc_set(struct rtc_time *tm)
+{
+ int i;
+ u8 buf[8];
+
+ debug("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
+ tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ buf[CCR_SEC] = BIN2BCD(tm->tm_sec);
+ buf[CCR_MIN] = BIN2BCD(tm->tm_min);
+
+ /* set hour and 24hr bit */
+ buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL;
+
+ buf[CCR_MDAY] = BIN2BCD(tm->tm_mday);
+
+ /* month, 1 - 12 */
+ buf[CCR_MONTH] = BIN2BCD(tm->tm_mon);
+
+ /* year, since the rtc epoch*/
+ buf[CCR_YEAR] = BIN2BCD(tm->tm_year % 100);
+ buf[CCR_WDAY] = tm->tm_wday & 0x07;
+ buf[CCR_Y2K] = BIN2BCD(tm->tm_year / 100);
+
+ /* this sequence is required to unlock the chip */
+ rtc_write(X1205_REG_SR, X1205_SR_WEL);
+ rtc_write(X1205_REG_SR, X1205_SR_WEL | X1205_SR_RWEL);
+
+ /* write register's data */
+ for (i = 0; i < 8; i++)
+ rtc_write(X1205_CCR_BASE + i, buf[i]);
+
+ rtc_write(X1205_REG_SR, 0);
+}
+
+void rtc_reset(void)
+{
+ /*
+ * Nothing to do
+ */
+}
+
+#endif
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 93c68dd..ee2b780 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -25,8 +25,20 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libserial.a
-COBJS := mcfuart.o
-
+COBJS-y += atmel_usart.o
+COBJS-y += mcfuart.o
+COBJS-y += ns9750_serial.o
+COBJS-y += ns16550.o
+COBJS-y += s3c4510b_uart.o
+COBJS-y += serial.o
+COBJS-y += serial_max3100.o
+COBJS-y += serial_pl010.o
+COBJS-y += serial_pl011.o
+COBJS-y += serial_xuartlite.o
+COBJS-y += serial_sh.o
+COBJS-y += usbtty.o
+
+COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
diff --git a/drivers/atmel_usart.c b/drivers/serial/atmel_usart.c
index f35b997..f35b997 100644
--- a/drivers/atmel_usart.c
+++ b/drivers/serial/atmel_usart.c
diff --git a/drivers/atmel_usart.h b/drivers/serial/atmel_usart.h
index af3773a..af3773a 100644
--- a/drivers/atmel_usart.h
+++ b/drivers/serial/atmel_usart.h
diff --git a/drivers/ns16550.c b/drivers/serial/ns16550.c
index 2429464..2429464 100644
--- a/drivers/ns16550.c
+++ b/drivers/serial/ns16550.c
diff --git a/drivers/ns9750_serial.c b/drivers/serial/ns9750_serial.c
index 02c0d39..02c0d39 100644
--- a/drivers/ns9750_serial.c
+++ b/drivers/serial/ns9750_serial.c
diff --git a/drivers/s3c4510b_uart.c b/drivers/serial/s3c4510b_uart.c
index ddcd591..ddcd591 100644
--- a/drivers/s3c4510b_uart.c
+++ b/drivers/serial/s3c4510b_uart.c
diff --git a/drivers/s3c4510b_uart.h b/drivers/serial/s3c4510b_uart.h
index b06c76d..b06c76d 100644
--- a/drivers/s3c4510b_uart.h
+++ b/drivers/serial/s3c4510b_uart.h
diff --git a/drivers/serial.c b/drivers/serial/serial.c
index 76425d8..76425d8 100644
--- a/drivers/serial.c
+++ b/drivers/serial/serial.c
diff --git a/drivers/serial_max3100.c b/drivers/serial/serial_max3100.c
index 35c5596..35c5596 100644
--- a/drivers/serial_max3100.c
+++ b/drivers/serial/serial_max3100.c
diff --git a/drivers/serial_pl010.c b/drivers/serial/serial_pl010.c
index 417b6ae..417b6ae 100644
--- a/drivers/serial_pl010.c
+++ b/drivers/serial/serial_pl010.c
diff --git a/drivers/serial_pl011.c b/drivers/serial/serial_pl011.c
index 4d35fe5..4d35fe5 100644
--- a/drivers/serial_pl011.c
+++ b/drivers/serial/serial_pl011.c
diff --git a/drivers/serial_pl011.h b/drivers/serial/serial_pl011.h
index 5f20fdd..5f20fdd 100644
--- a/drivers/serial_pl011.h
+++ b/drivers/serial/serial_pl011.h
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c
new file mode 100644
index 0000000..ee44ba2
--- /dev/null
+++ b/drivers/serial/serial_sh.c
@@ -0,0 +1,177 @@
+/*
+ * SuperH SCIF device driver.
+ * Copyright (c) 2007 Nobuhiro Iwamatsu
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+
+#ifdef CFG_SCIF_CONSOLE
+
+#if defined (CONFIG_CONS_SCIF0)
+#define SCIF_BASE SCIF0_BASE
+#elif defined (CONFIG_CONS_SCIF1)
+#define SCIF_BASE SCIF1_BASE
+#else
+#error "Default SCIF doesn't set....."
+#endif
+
+#define SCSMR (vu_short *)(SCIF_BASE + 0x0)
+#define SCBRR (vu_char *)(SCIF_BASE + 0x4)
+#define SCSCR (vu_short *)(SCIF_BASE + 0x8)
+#define SCFTDR (vu_char *)(SCIF_BASE + 0xC)
+#define SCFSR (vu_short *)(SCIF_BASE + 0x10)
+#define SCFRDR (vu_char *)(SCIF_BASE + 0x14)
+#define SCFCR (vu_short *)(SCIF_BASE + 0x18)
+#define SCFDR (vu_short *)(SCIF_BASE + 0x1C)
+#if defined(CONFIG_SH4A)
+#define SCRFDR (vu_short *)(SCIF_BASE + 0x20)
+#define SCSPTR (vu_short *)(SCIF_BASE + 0x24)
+#define SCLSR (vu_short *)(SCIF_BASE + 0x28)
+#define SCRER (vu_short *)(SCIF_BASE + 0x2C)
+#elif defined (CONFIG_SH4)
+#define SCSPTR (vu_short *)(SCIF_BASE + 0x20)
+#define SCLSR (vu_short *)(SCIF_BASE + 0x24)
+#elif defined (CONFIG_SH3)
+#define SCLSR (vu_short *)(SCIF_BASE + 0x24)
+#endif
+
+#define SCR_RE (1 << 4)
+#define SCR_TE (1 << 5)
+#define FCR_RFRST (1 << 1) /* RFCL */
+#define FCR_TFRST (1 << 2) /* TFCL */
+#define FSR_DR (1 << 0)
+#define FSR_RDF (1 << 1)
+#define FSR_FER (1 << 3)
+#define FSR_BRK (1 << 4)
+#define FSR_FER (1 << 3)
+#define FSR_TEND (1 << 6)
+#define FSR_ER (1 << 7)
+
+/*----------------------------------------------------------------------*/
+
+void serial_setbrg (void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ int divisor = gd->baudrate * 32;
+
+ *SCBRR = (CONFIG_SYS_CLK_FREQ + (divisor / 2)) /
+ (gd->baudrate * 32) - 1;
+}
+
+int serial_init (void)
+{
+ *SCSCR = (SCR_RE | SCR_TE);
+ *SCSMR = 0 ;
+ *SCSMR = 0;
+ *SCFCR = (FCR_RFRST | FCR_TFRST);
+ *SCFCR;
+ *SCFCR = 0;
+
+ serial_setbrg();
+ return 0;
+}
+
+static int serial_tx_fifo_level (void)
+{
+ return (*SCFDR >> 8) & 0x1F;
+}
+
+static int serial_rx_fifo_level (void)
+{
+ return (*SCFDR >> 0) & 0x1F;
+}
+
+void serial_raw_putc (const char c)
+{
+ unsigned int fsr_bits_to_clear;
+
+ while (1) {
+ if (*SCFSR & FSR_TEND) { /* Tx fifo is empty */
+ fsr_bits_to_clear = FSR_TEND;
+ break;
+ }
+ }
+
+ *SCFTDR = c;
+ if (fsr_bits_to_clear != 0)
+ *SCFSR &= ~fsr_bits_to_clear;
+}
+
+void serial_putc (const char c)
+{
+ if (c == '\n')
+ serial_raw_putc ('\r');
+ serial_raw_putc (c);
+}
+
+void serial_puts (const char *s)
+{
+ char c;
+ while ((c = *s++) != 0)
+ serial_putc (c);
+}
+
+int serial_tstc (void)
+{
+ return serial_rx_fifo_level() ? 1 : 0;
+}
+
+#define FSR_ERR_CLEAR 0x0063
+#define RDRF_CLEAR 0x00fc
+#define LSR_ORER 1
+void handle_error( void ){
+
+ (void)*SCFSR ;
+ *SCFSR = FSR_ERR_CLEAR ;
+ (void)*SCLSR ;
+ *SCLSR = 0x00 ;
+}
+
+int serial_getc_check( void ){
+ unsigned short status;
+
+ status = *SCFSR ;
+
+ if (status & (FSR_FER | FSR_FER | FSR_ER | FSR_BRK))
+ handle_error();
+ if( *SCLSR & LSR_ORER )
+ handle_error();
+ return (status & ( FSR_DR | FSR_RDF ));
+}
+
+int serial_getc (void)
+{
+ unsigned short status ;
+ char ch;
+ while(!serial_getc_check());
+
+ ch = *SCFRDR;
+ status = *SCFSR ;
+
+ *SCFSR = RDRF_CLEAR ;
+
+ if (status & (FSR_FER | FSR_FER | FSR_ER | FSR_BRK))
+ handle_error();
+
+ if( *SCLSR & LSR_ORER )
+ handle_error();
+
+ return ch ;
+}
+
+#endif /* CFG_SCIF_CONSOLE */
diff --git a/drivers/serial_xuartlite.c b/drivers/serial/serial_xuartlite.c
index d678ab6..d678ab6 100644
--- a/drivers/serial_xuartlite.c
+++ b/drivers/serial/serial_xuartlite.c
diff --git a/drivers/usbtty.c b/drivers/serial/usbtty.c
index a3b5013..a3b5013 100644
--- a/drivers/usbtty.c
+++ b/drivers/serial/usbtty.c
diff --git a/drivers/usbtty.h b/drivers/serial/usbtty.h
index 8154e30..8154e30 100644
--- a/drivers/usbtty.h
+++ b/drivers/serial/usbtty.h
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
new file mode 100644
index 0000000..f8ea167
--- /dev/null
+++ b/drivers/usb/Makefile
@@ -0,0 +1,52 @@
+#
+# (C) Copyright 2000-2007
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB := $(obj)libusb.a
+
+COBJS-y += isp116x-hcd.o
+COBJS-y += sl811_usb.o
+COBJS-y += usb_ohci.o
+COBJS-y += usbdcore.o
+COBJS-y += usbdcore_ep0.o
+COBJS-y += usbdcore_mpc8xx.o
+COBJS-y += usbdcore_omap1510.o
+
+COBJS := $(COBJS-y)
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/isp116x-hcd.c b/drivers/usb/isp116x-hcd.c
index b21af10..b21af10 100644
--- a/drivers/isp116x-hcd.c
+++ b/drivers/usb/isp116x-hcd.c
diff --git a/drivers/isp116x.h b/drivers/usb/isp116x.h
index a3ce3b5..a3ce3b5 100644
--- a/drivers/isp116x.h
+++ b/drivers/usb/isp116x.h
diff --git a/drivers/sl811.h b/drivers/usb/sl811.h
index c1f9f01..c1f9f01 100644
--- a/drivers/sl811.h
+++ b/drivers/usb/sl811.h
diff --git a/drivers/sl811_usb.c b/drivers/usb/sl811_usb.c
index b0cdf0b..c1f8427 100644
--- a/drivers/sl811_usb.c
+++ b/drivers/usb/sl811_usb.c
@@ -41,7 +41,7 @@
#include <usb.h>
#include "sl811.h"
-#include "../board/kup/common/kup.h"
+#include "../../board/kup/common/kup.h"
#ifdef __PPC__
# define EIEIO __asm__ volatile ("eieio")
diff --git a/drivers/usb_ohci.c b/drivers/usb/usb_ohci.c
index 7ddcab6..cfa384e 100644
--- a/drivers/usb_ohci.c
+++ b/drivers/usb/usb_ohci.c
@@ -59,6 +59,10 @@
#include <usb.h>
#include "usb_ohci.h"
+#ifdef CONFIG_AT91RM9200
+#include <asm/arch/hardware.h> /* needed for AT91_USB_HOST_BASE */
+#endif
+
#if defined(CONFIG_ARM920T) || \
defined(CONFIG_S3C2400) || \
defined(CONFIG_S3C2410) || \
diff --git a/drivers/usb_ohci.h b/drivers/usb/usb_ohci.h
index 380cb4c..380cb4c 100644
--- a/drivers/usb_ohci.h
+++ b/drivers/usb/usb_ohci.h
diff --git a/drivers/usbdcore.c b/drivers/usb/usbdcore.c
index 308c7ce..308c7ce 100644
--- a/drivers/usbdcore.c
+++ b/drivers/usb/usbdcore.c
diff --git a/drivers/usbdcore_ep0.c b/drivers/usb/usbdcore_ep0.c
index 1e44f32..1e44f32 100644
--- a/drivers/usbdcore_ep0.c
+++ b/drivers/usb/usbdcore_ep0.c
diff --git a/drivers/usbdcore_mpc8xx.c b/drivers/usb/usbdcore_mpc8xx.c
index d4c4096..d4c4096 100644
--- a/drivers/usbdcore_mpc8xx.c
+++ b/drivers/usb/usbdcore_mpc8xx.c
diff --git a/drivers/usbdcore_omap1510.c b/drivers/usb/usbdcore_omap1510.c
index 84bb936..84bb936 100644
--- a/drivers/usbdcore_omap1510.c
+++ b/drivers/usb/usbdcore_omap1510.c
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
new file mode 100644
index 0000000..36611ec
--- /dev/null
+++ b/drivers/video/Makefile
@@ -0,0 +1,53 @@
+#
+# (C) Copyright 2000-2007
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB := $(obj)libvideo.a
+
+COBJS-y += ati_radeon_fb.o
+COBJS-y += cfb_console.o
+COBJS-y += ct69000.o
+COBJS-y += sed13806.o
+COBJS-y += sed156x.o
+COBJS-y += sm501.o
+COBJS-y += smiLynxEM.o
+COBJS-y += videomodes.o
+
+COBJS := $(COBJS-y)
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/ati_ids.h b/drivers/video/ati_ids.h
index 3e72a7d..3e72a7d 100644
--- a/drivers/ati_ids.h
+++ b/drivers/video/ati_ids.h
diff --git a/drivers/ati_radeon_fb.c b/drivers/video/ati_radeon_fb.c
index c174f37..0bdaa1c 100644
--- a/drivers/ati_radeon_fb.c
+++ b/drivers/video/ati_radeon_fb.c
@@ -300,7 +300,7 @@ typedef struct {
u32 val;
} reg_val;
-
+#if 0 /* unused ? -> scheduled for removal */
/* these common regs are cleared before mode setting so they do not
* interfere with anything
*/
@@ -316,11 +316,10 @@ static reg_val common_regs[] = {
{ CAP0_TRIG_CNTL, 0 },
{ CAP1_TRIG_CNTL, 0 },
};
-
+#endif /* 0 */
void radeon_setmode(void)
{
- int i;
struct radeon_regs *mode = malloc(sizeof(struct radeon_regs));
mode->crtc_gen_cntl = 0x03000200;
@@ -351,6 +350,9 @@ void radeon_setmode(void)
radeon_write_pll_regs(rinfo, mode);
}
+#include "../bios_emulator/include/biosemu.h"
+extern int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo ** pVGAInfo, int cleanUp);
+
int radeon_probe(struct radeonfb_info *rinfo)
{
pci_dev_t pdev;
diff --git a/drivers/ati_radeon_fb.h b/drivers/video/ati_radeon_fb.h
index b5c4b8b..b5c4b8b 100644
--- a/drivers/ati_radeon_fb.h
+++ b/drivers/video/ati_radeon_fb.h
diff --git a/drivers/cfb_console.c b/drivers/video/cfb_console.c
index bcf8771..bcf8771 100644
--- a/drivers/cfb_console.c
+++ b/drivers/video/cfb_console.c
diff --git a/drivers/ct69000.c b/drivers/video/ct69000.c
index 29d82e4..29d82e4 100644
--- a/drivers/ct69000.c
+++ b/drivers/video/ct69000.c
diff --git a/drivers/sed13806.c b/drivers/video/sed13806.c
index 6996ca8..6996ca8 100644
--- a/drivers/sed13806.c
+++ b/drivers/video/sed13806.c
diff --git a/drivers/sed156x.c b/drivers/video/sed156x.c
index e9d5ed4..e9d5ed4 100644
--- a/drivers/sed156x.c
+++ b/drivers/video/sed156x.c
diff --git a/drivers/sm501.c b/drivers/video/sm501.c
index 23db02c..23db02c 100644
--- a/drivers/sm501.c
+++ b/drivers/video/sm501.c
diff --git a/drivers/smiLynxEM.c b/drivers/video/smiLynxEM.c
index 20f9beb..20f9beb 100644
--- a/drivers/smiLynxEM.c
+++ b/drivers/video/smiLynxEM.c
diff --git a/drivers/videomodes.c b/drivers/video/videomodes.c
index c81e5bc..c81e5bc 100644
--- a/drivers/videomodes.c
+++ b/drivers/video/videomodes.c
diff --git a/drivers/videomodes.h b/drivers/video/videomodes.h
index e2dffe7..e2dffe7 100644
--- a/drivers/videomodes.h
+++ b/drivers/video/videomodes.h