Patchwork [U-Boot,v4] Consolidate bootcount code into drivers/bootcount

login
register
mail settings
Submitter Stefan Roese
Date Aug. 13, 2012, 11:56 a.m.
Message ID <1344858963-5390-1-git-send-email-sr@denx.de>
Download mbox | patch
Permalink /patch/176918/
State Superseded
Headers show

Comments

Stefan Roese - Aug. 13, 2012, 11:56 a.m.
This patch moves all bootcount implementations into a common
directory: drivers/bootcount. The generic bootcount driver
is now usable not only by powerpc platforms, but others as well.

Signed-off-by: Stefan Roese <sr@denx.de>
Cc: Heiko Schocher <hs@denx.de>
Cc: Valentin Longchamp <valentin.longchamp@keymile.com>
Cc: Christian Riesch <christian.riesch@omicron.at>
Cc: Manfred Rudigier <manfred.rudigier@omicron.at>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Reinhard Meyer <reinhard.meyer@emk-elektronik.de>
Tested-by: Valentin Longchamp <valentin.longchamp@keymile.com>
Tested-by: Christian Riesch <christian.riesch@omicron.at>
Acked-by: Rob Herring <rob.herring@calxeda.com>
---
v4:
- Rebased against TOT
- Addressed Mike's comments

v3:
- Moved le-/be-accessors into header so that they now can be
  used by all bootcount drivers.
- Changed CONFIG_BOOTCOUNT_LE to CONFIG_SYS_BOOTCOUNT_LE
- Enabled CONFIG_SYS_BOOTCOUNT_LE in highbank
- Enabled CONFIG_SYS_BOOTCOUNT_SINGLEWORD in highbank

v2:
- Added CONFIG_BOOTCOUNT_LE to bootcount_davinci.c and enabled it
  in calimain.h to select little-endian accessors.

 Makefile                                           |  1 +
 arch/arm/cpu/arm926ejs/at91/cpu.c                  | 26 --------
 arch/arm/cpu/armv7/highbank/Makefile               |  2 +-
 arch/arm/cpu/armv7/highbank/bootcount.c            | 36 -----------
 arch/arm/cpu/ixp/cpu.c                             | 22 -------
 arch/powerpc/lib/Makefile                          |  1 -
 board/enbw/enbw_cmc/enbw_cmc.c                     | 29 ---------
 board/keymile/km_arm/km_arm.c                      | 51 ---------------
 board/omicron/calimain/calimain.c                  | 29 ---------
 drivers/bootcount/Makefile                         | 45 ++++++++++++++
 .../powerpc/lib => drivers/bootcount}/bootcount.c  | 25 ++++----
 drivers/bootcount/bootcount_at91.c                 | 43 +++++++++++++
 .../bootcount/bootcount_blackfin.c                 |  0
 drivers/bootcount/bootcount_davinci.c              | 49 +++++++++++++++
 drivers/bootcount/bootcount_ram.c                  | 72 ++++++++++++++++++++++
 include/bootcount.h                                | 51 +++++++++++++++
 include/configs/calimain.h                         |  1 +
 include/configs/enbw_cmc.h                         |  1 +
 include/configs/highbank.h                         |  2 +
 include/configs/km/km_arm.h                        |  2 +
 20 files changed, 282 insertions(+), 206 deletions(-)
 delete mode 100644 arch/arm/cpu/armv7/highbank/bootcount.c
 create mode 100644 drivers/bootcount/Makefile
 rename {arch/powerpc/lib => drivers/bootcount}/bootcount.c (82%)
 create mode 100644 drivers/bootcount/bootcount_at91.c
 rename arch/blackfin/cpu/bootcount.c => drivers/bootcount/bootcount_blackfin.c (100%)
 create mode 100644 drivers/bootcount/bootcount_davinci.c
 create mode 100644 drivers/bootcount/bootcount_ram.c
 create mode 100644 include/bootcount.h
Christian Riesch - Aug. 13, 2012, 4:05 p.m.
Hi Stefan,

On Monday, August 13, 2012, Stefan Roese wrote:

> This patch moves all bootcount implementations into a common
> directory: drivers/bootcount. The generic bootcount driver
> is now usable not only by powerpc platforms, but others as well.
>
> Signed-off-by: Stefan Roese <sr@denx.de <javascript:;>>
> Cc: Heiko Schocher <hs@denx.de <javascript:;>>
> Cc: Valentin Longchamp <valentin.longchamp@keymile.com <javascript:;>>
> Cc: Christian Riesch <christian.riesch@omicron.at <javascript:;>>
> Cc: Manfred Rudigier <manfred.rudigier@omicron.at <javascript:;>>
> Cc: Mike Frysinger <vapier@gentoo.org <javascript:;>>
> Cc: Rob Herring <rob.herring@calxeda.com <javascript:;>>
> Cc: Reinhard Meyer <reinhard.meyer@emk-elektronik.de <javascript:;>>
> Tested-by: Valentin Longchamp <valentin.longchamp@keymile.com<javascript:;>
> >
> Tested-by: Christian Riesch <christian.riesch@omicron.at <javascript:;>>


I tested v2 and v3 of this patch, but not v4. I can do this on Friday when
I am back from my vacation.
Regards, Christian


> Acked-by: Rob Herring <rob.herring@calxeda.com <javascript:;>>
> ---
> v4:
> - Rebased against TOT
> - Addressed Mike's comments
>
> v3:
> - Moved le-/be-accessors into header so that they now can be
>   used by all bootcount drivers.
> - Changed CONFIG_BOOTCOUNT_LE to CONFIG_SYS_BOOTCOUNT_LE
> - Enabled CONFIG_SYS_BOOTCOUNT_LE in highbank
> - Enabled CONFIG_SYS_BOOTCOUNT_SINGLEWORD in highbank
>
> v2:
> - Added CONFIG_BOOTCOUNT_LE to bootcount_davinci.c and enabled it
>   in calimain.h to select little-endian accessors.
>
>  Makefile                                           |  1 +
>  arch/arm/cpu/arm926ejs/at91/cpu.c                  | 26 --------
>  arch/arm/cpu/armv7/highbank/Makefile               |  2 +-
>  arch/arm/cpu/armv7/highbank/bootcount.c            | 36 -----------
>  arch/arm/cpu/ixp/cpu.c                             | 22 -------
>  arch/powerpc/lib/Makefile                          |  1 -
>  board/enbw/enbw_cmc/enbw_cmc.c                     | 29 ---------
>  board/keymile/km_arm/km_arm.c                      | 51 ---------------
>  board/omicron/calimain/calimain.c                  | 29 ---------
>  drivers/bootcount/Makefile                         | 45 ++++++++++++++
>  .../powerpc/lib => drivers/bootcount}/bootcount.c  | 25 ++++----
>  drivers/bootcount/bootcount_at91.c                 | 43 +++++++++++++
>  .../bootcount/bootcount_blackfin.c                 |  0
>  drivers/bootcount/bootcount_davinci.c              | 49 +++++++++++++++
>  drivers/bootcount/bootcount_ram.c                  | 72
> ++++++++++++++++++++++
>  include/bootcount.h                                | 51 +++++++++++++++
>  include/configs/calimain.h                         |  1 +
>  include/configs/enbw_cmc.h                         |  1 +
>  include/configs/highbank.h                         |  2 +
>  include/configs/km/km_arm.h                        |  2 +
>  20 files changed, 282 insertions(+), 206 deletions(-)
>  delete mode 100644 arch/arm/cpu/armv7/highbank/bootcount.c
>  create mode 100644 drivers/bootcount/Makefile
>  rename {arch/powerpc/lib => drivers/bootcount}/bootcount.c (82%)
>  create mode 100644 drivers/bootcount/bootcount_at91.c
>  rename arch/blackfin/cpu/bootcount.c =>
> drivers/bootcount/bootcount_blackfin.c (100%)
>  create mode 100644 drivers/bootcount/bootcount_davinci.c
>  create mode 100644 drivers/bootcount/bootcount_ram.c
>  create mode 100644 include/bootcount.h
>
> diff --git a/Makefile b/Makefile
> index 5ce5cc3..2b662b4 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -249,6 +249,7 @@ LIBS-y += net/libnet.o
>  LIBS-y += disk/libdisk.o
>  LIBS-y += drivers/bios_emulator/libatibiosemu.o
>  LIBS-y += drivers/block/libblock.o
> +LIBS-$(CONFIG_BOOTCOUNT_LIMIT) += drivers/bootcount/libbootcount.o
>  LIBS-y += drivers/dma/libdma.o
>  LIBS-y += drivers/fpga/libfpga.o
>  LIBS-y += drivers/gpio/libgpio.o
> diff --git a/arch/arm/cpu/arm926ejs/at91/cpu.c
> b/arch/arm/cpu/arm926ejs/at91/cpu.c
> index c47fb31..5cf4fad 100644
> --- a/arch/arm/cpu/arm926ejs/at91/cpu.c
> +++ b/arch/arm/cpu/arm926ejs/at91/cpu.c
> @@ -71,29 +71,3 @@ int print_cpuinfo(void)
>         return 0;
>  }
>  #endif
> -
> -#ifdef CONFIG_BOOTCOUNT_LIMIT
> -/*
> - * We combine the BOOTCOUNT_MAGIC and bootcount in one 32-bit register.
> - * This is done so we need to use only one of the four GPBR registers.
> - */
> -void bootcount_store (ulong a)
> -{
> -       at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR;
> -
> -       writel((BOOTCOUNT_MAGIC & 0xffff0000) | (a & 0x0000ffff),
> -               &gpbr->reg[AT91_GPBR_INDEX_BOOTCOUNT]);
> -}
> -
> -ulong bootcount_load (void)
> -{
> -       at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR;
> -
> -       ulong val = readl(&gpbr->reg[AT91_GPBR_INDEX_BOOTCOUNT]);
> -       if ((val & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000))
> -               return 0;
> -       else
> -               return val & 0x0000ffff;
> -}
> -
> -#endif /* CONFIG_BOOTCOUNT_LIMIT */
> diff --git a/arch/arm/cpu/armv7/highbank/Makefile
> b/arch/arm/cpu/armv7/highbank/Makefile
> index 917c3a3..76faeb0 100644
> --- a/arch/arm/cpu/armv7/highbank/Makefile
> +++ b/arch/arm/cpu/armv7/highbank/Makefile
> @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk
>
>  LIB    = $(obj)lib$(SOC).o
>
> -COBJS  := timer.o bootcount.o
> +COBJS  := timer.o
>  SOBJS  :=
>
>  SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
> diff --git a/arch/arm/cpu/armv7/highbank/bootcount.c
> b/arch/arm/cpu/armv7/highbank/bootcount.c
> deleted file mode 100644
> index 9ca0656..0000000
> --- a/arch/arm/cpu/armv7/highbank/bootcount.c
> +++ /dev/null
> @@ -1,36 +0,0 @@
> -/*
> - * Copyright 2011 Calxeda, Inc.
> - *
> - * 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 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, see <http://www.gnu.org/licenses/>.
> - */
> -
> -#include <common.h>
> -#include <asm/io.h>
> -
> -#ifdef CONFIG_BOOTCOUNT_LIMIT
> -void bootcount_store(ulong a)
> -{
> -       writel((BOOTCOUNT_MAGIC & 0xffff0000) | a,
> CONFIG_SYS_BOOTCOUNT_ADDR);
> -}
> -
> -ulong bootcount_load(void)
> -{
> -       u32 tmp = readl(CONFIG_SYS_BOOTCOUNT_ADDR);
> -
> -       if ((tmp & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000))
> -               return 0;
> -       else
> -               return tmp & 0x0000ffff;
> -}
> -#endif
> diff --git a/arch/arm/cpu/ixp/cpu.c b/arch/arm/cpu/ixp/cpu.c
> index 942845d..f1864d6 100644
> --- a/arch/arm/cpu/ixp/cpu.c
> +++ b/arch/arm/cpu/ixp/cpu.c
> @@ -107,28 +107,6 @@ void pci_init(void)
>  }
>  */
>
> -#ifdef CONFIG_BOOTCOUNT_LIMIT
> -
> -void bootcount_store (ulong a)
> -{
> -       volatile ulong *save_addr = (volatile ulong
> *)(CONFIG_SYS_BOOTCOUNT_ADDR);
> -
> -       save_addr[0] = a;
> -       save_addr[1] = BOOTCOUNT_MAGIC;
> -}
> -
> -ulong bootcount_load (void)
> -{
> -       volatile ulong *save_addr = (volatile ulong
> *)(CONFIG_SYS_BOOTCOUNT_ADDR);
> -
> -       if (save_addr[1] != BOOTCOUNT_MAGIC)
> -               return 0;
> -       else
> -               return save_addr[0];
> -}
> -
> -#endif /* CONFIG_BOOTCOUNT_LIMIT */
> -
>  int cpu_eth_init(bd_t *bis)
>  {
>  #ifdef CONFIG_IXP4XX_NPE
> diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
> index cdd62a2..965f9ea 100644
> --- a/arch/powerpc/lib/Makefile
> +++ b/arch/powerpc/lib/Makefile
> @@ -46,7 +46,6 @@ SOBJS-y       += reloc.o
>  COBJS-$(CONFIG_BAT_RW) += bat_rw.o
>  COBJS-y        += board.o
>  COBJS-y        += bootm.o
> -COBJS-$(CONFIG_BOOTCOUNT_LIMIT) += bootcount.o
>  COBJS-y        += cache.o
>  COBJS-y        += extable.o
>  COBJS-y        += interrupts.o
> diff --git a/board/enbw/enbw_cmc/enbw_cmc.c
> b/board/enbw/enbw_cmc/enbw_cmc.c
> index 0874e9c..67d5d4d 100644
> --- a/board/enbw/enbw_cmc/enbw_cmc.c
> +++ b/board/enbw/enbw_cmc/enbw_cmc.c
> @@ -778,35 +778,6 @@ void arch_memory_failure_handle(void)
>  }
>  #endif
>
> -#if defined(CONFIG_BOOTCOUNT_LIMIT)
> -void bootcount_store(ulong a)
> -{
> -       struct davinci_rtc *reg =
> -               (struct davinci_rtc *)CONFIG_SYS_BOOTCOUNT_ADDR;
> -
> -       /*
> -        * write RTC kick register to enable write
> -        * for RTC Scratch registers. Scratch0 and 1 are
> -        * used for bootcount values.
> -        */
> -       writel(RTC_KICK0R_WE, &reg->kick0r);
> -       writel(RTC_KICK1R_WE, &reg->kick1r);
> -       out_be32(&reg->scratch0, a);
> -       out_be32(&reg->scratch1, BOOTCOUNT_MAGIC);
> -}
> -
> -ulong bootcount_load(void)
> -{
> -       struct davinci_rtc *reg =
> -               (struct davinci_rtc *)CONFIG_SYS_BOOTCOUNT_ADDR;
> -
> -       if (in_be32(&reg->scratch1) != BOOTCOUNT_MAGIC)
> -               return 0;
> -       else
> -               return in_be32(&reg->scratch0);
> -}
> -#endif
> -
>  ulong post_word_load(void)
>  {
>         struct davinci_rtc *reg =
> diff --git a/board/keymile/km_arm/km_arm.c b/board/keymile/km_arm/km_arm.c
> index 2b2ca39..930c80e 100644
> --- a/board/keymile/km_arm/km_arm.c
> +++ b/board/keymile/km_arm/km_arm.c
> @@ -408,57 +408,6 @@ int hush_init_var(void)
>  }
>  #endif
>
> -#if defined(CONFIG_BOOTCOUNT_LIMIT)
> -const ulong patterns[]      = {        0x00000000,
> -                               0xFFFFFFFF,
> -                               0xFF00FF00,
> -                               0x0F0F0F0F,
> -                               0xF0F0F0F0};
> -const ulong NBR_OF_PATTERNS = ARRAY_SIZE(patterns);
> -const ulong OFFS_PATTERN    = 3;
> -const ulong REPEAT_PATTERN  = 1000;
> -
> -void bootcount_store(ulong a)
> -{
> -       ulong *save_addr;
> -       ulong size = 0;
> -       int i;
> -
> -       for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
> -               size += gd->bd->bi_dram[i].size;
> -       save_addr = (ulong *)(size - BOOTCOUNT_ADDR);
> -       writel(a, save_addr);
> -       writel(BOOTCOUNT_MAGIC, &save_addr[1]);
> -
> -       for (i = 0; i < REPEAT_PATTERN; i++)
> -               writel(patterns[i % NBR_OF_PATTERNS],
> -                       &save_addr[i+OFFS_PATTERN]);
> -
> -}
> -
> -ulong bootcount_load(void)
> -{
> -       ulong *save_addr;
> -       ulong size = 0;
> -       ulong counter = 0;
> -       int i, tmp;
> -
> -       for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
> -               size += gd->bd->bi_dram[i].size;
> -       save_addr = (ulong *)(size - BOOTCOUNT_ADDR);
> -
> -       counter = readl(&save_addr[0]);
> -
> -       /* Is the counter reliable, check in the big pattern for bit
> errors */
> -       for (i = 0; (i < REPEAT_PATTERN) && (counter != 0); i++) {
> -               tmp = readl(&save_addr[i+OFFS_PATTERN]);
> -               if (tmp != patterns[i % NBR_OF_PATTERNS])
> -                       counter = 0;
> -       }
> -       return counter;
> -}
> -#endif
> -
>  #if defined(CONFIG_SOFT_I2C)
>  void set_sda(int state)
>  {
> diff --git a/board/omicron/calimain/calimain.c
> b/board/omicron/calimain/calimain.c
> index 54415ce..1060a1f 100644
> --- a/board/omicron/calimain/calimain.c
> +++ b/board/omicron/calimain/calimain.c
> @@ -157,32 +157,3 @@ void hw_watchdog_reset(void)
>         davinci_hw_watchdog_reset();
>  }
>  #endif
> -
> -#if defined(CONFIG_BOOTCOUNT_LIMIT)
> -void bootcount_store(ulong a)
> -{
> -       struct davinci_rtc *reg =
> -               (struct davinci_rtc *)CONFIG_SYS_BOOTCOUNT_ADDR;
> -
> -       /*
> -        * write RTC kick register to enable write
> -        * for RTC Scratch registers. Scratch0 and 1 are
> -        * used for bootcount values.
> -        */
> -       writel(RTC_KICK0R_WE, &reg->kick0r);
> -       writel(RTC_KICK1R_WE, &reg->kick1r);
> -       writel(a, &reg->scratch0);
> -       writel(BOOTCOUNT_MAGIC, &reg->scratch1);
> -}
> -
> -ulong bootcount_load(void)
> -{
> -       struct davinci_rtc *reg =
> -               (struct davinci_rtc *)CONFIG_SYS_BOOTCOUNT_ADDR;
> -
> -       if (readl(&reg->scratch1) != BOOTCOUNT_MAGIC)
> -               return 0;
> -       else
> -               return readl(&reg->scratch0);
> -}
> -#endif
> diff --git a/drivers/bootcount/Makefile b/drivers/bootcount/Makefile
> new file mode 100644
> index 0000000..a8d0ac7
> --- /dev/null
> +++ b/drivers/bootcount/Makefile
> @@ -0,0 +1,45 @@
> +#
> +# 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)libbootcount.o
> +
> +COBJS-y                                += bootcount.o
> +COBJS-$(CONFIG_AT91SAM9XE)     += bootcount_at91.o
> +COBJS-$(CONFIG_BLACKFIN)       += bootcount_blackfin.o
> +COBJS-$(CONFIG_SOC_DA8XX)      += bootcount_davinci.o
> +COBJS-$(CONFIG_BOOTCOUNT_RAM)  += bootcount_ram.o
> +
> +COBJS  := $(COBJS-y)
> +SRCS   := $(COBJS:.o=.c)
> +OBJS   := $(addprefix $(obj),$(COBJS))
> +
> +$(LIB):        $(obj).depend $(OBJS)
> +       $(call cmd_link_o_target, $(OBJS))
> +
> +#########################################################################
> +
> +# defines $(obj).depend target
> +include $(SRCTREE)/rules.mk
> +
> +sinclude $(obj).depend
> +
> +########################################################################
> diff --git a/arch/powerpc/lib/bootcount.c b/drivers/bootcount/bootcount.c
> similarity index 82%
> rename from arch/powerpc/lib/bootcount.c
> rename to drivers/bootcount/bootcount.c
> index f9ce539..80eb717 100644
> --- a/arch/powerpc/lib/bootcount.c
> +++ b/drivers/bootcount/bootcount.c
> @@ -1,5 +1,5 @@
>  /*
> - * (C) Copyright 2010
> + * (C) Copyright 2010-2012
>   * Stefan Roese, DENX Software Engineering, sr@denx.de <javascript:;>.
>   *
>   * See file CREDITS for list of people who contributed to this
> @@ -21,8 +21,8 @@
>   * MA 02111-1307 USA
>   */
>
> -#include <common.h>
> -#include <asm/io.h>
> +#include <bootcount.h>
> +#include <linux/compiler.h>
>
>  /*
>   * Only override CONFIG_SYS_BOOTCOUNT_ADDR if not already defined. This
> @@ -65,33 +65,36 @@
>
>  #endif /* !defined(CONFIG_SYS_BOOTCOUNT_ADDR) */
>
> -void bootcount_store(ulong a)
> +/* Now implement the generic default functions */
> +#if defined(CONFIG_SYS_BOOTCOUNT_ADDR)
> +__weak void bootcount_store(ulong a)
>  {
>         void *reg = (void *)CONFIG_SYS_BOOTCOUNT_ADDR;
>
>  #if defined(CONFIG_SYS_BOOTCOUNT_SINGLEWORD)
> -       out_be32(reg, (BOOTCOUNT_MAGIC & 0xffff0000) | a);
> +       raw_bootcount_store(reg, (BOOTCOUNT_MAGIC & 0xffff0000) | a);
>  #else
> -       out_be32(reg, a);
> -       out_be32(reg + 4, BOOTCOUNT_MAGIC);
> +       raw_bootcount_store(reg, a);
> +       raw_bootcount_store(reg + 4, BOOTCOUNT_MAGIC);
>  #endif
>  }
>
> -ulong bootcount_load(void)
> +__weak ulong bootcount_load(void)
>  {
>         void *reg = (void *)CONFIG_SYS_BOOTCOUNT_ADDR;
>
>  #if defined(CONFIG_SYS_BOOTCOUNT_SINGLEWORD)
> -       u32 tmp = in_be32(reg);
> +       u32 tmp = raw_bootcount_load(reg);
>
>         if ((tmp & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000))
>                 return 0;
>         else
>                 return (tmp & 0x0000ffff);
>  #else
> -       if (in_be32(reg + 4) != BOOTCOUNT_MAGIC)
> +       if (raw_bootcount_load(reg + 4) != BOOTCOUNT_MAGIC)
>                 return 0;
>         else
> -               return in_be32(reg);
> +               return raw_bootcount_load(reg);
>  #endif
>  }
> +#endif
> diff --git a/drivers/bootcount/bootcount_at91.c
> b/drivers/bootcount/bootcount_at91.c
> new file mode 100644
> index 0000000..7cfe14d
> --- /dev/null
> +++ b/drivers/bootcount/bootcount_at91.c
> @@ -0,0 +1,43 @@
> +/*
> + * 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.
> + *
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <asm/arch/hardware.h>
> +#include <asm/arch/at91_gpbr.h>
> +
> +/*
> + * We combine the BOOTCOUNT_MAGIC and bootcount in one 32-bit register.
> + * This is done so we need to use only one of the four GPBR registers.
> + */
> +void bootcount_store(ulong a)
> +{
> +       at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR;
> +
> +       writel((BOOTCOUNT_MAGIC & 0xffff0000) | (a & 0x0000ffff),
> +               &gpbr->reg[AT91_GPBR_INDEX_BOOTCOUNT]);
> +}
> +
> +ulong bootcount_load(void)
> +{
> +       at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR;
> +
> +       ulong val = readl(&gpbr->reg[AT91_GPBR_INDEX_BOOTCOUNT]);
> +       if ((val & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000))
> +               return 0;
> +       else
> +               return val & 0x0000ffff;
> +}
> diff --git a/arch/blackfin/cpu/bootcount.c
> b/drivers/bootcount/bootcount_blackfin.c
> similarity index 100%
> rename from arch/blackfin/cpu/bootcount.c
> rename to drivers/bootcount/bootcount_blackfin.c
> diff --git a/drivers/bootcount/bootcount_davinci.c
> b/drivers/bootcount/bootcount_davinci.c
> new file mode 100644
> index 0000000..1cd9436
> --- /dev/null
> +++ b/drivers/bootcount/bootcount_davinci.c
> @@ -0,0 +1,49 @@
> +/*
> + * (C) Copyright 2011
> + * Heiko Schocher, DENX Software Engineering, hs@denx.de <javascript:;>.
> + *
> + * 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.
> + *
> + */
> +
> +#include <bootcount.h>
> +#include <asm/arch/da850_lowlevel.h>
> +#include <asm/arch/davinci_misc.h>
> +
> +void bootcount_store(ulong a)
> +{
> +       struct davinci_rtc *reg =
> +               (struct davinci_rtc *)CONFIG_SYS_BOOTCOUNT_ADDR;
> +
> +       /*
> +        * write RTC kick register to enable write
> +        * for RTC Scratch registers. Scratch0 and 1 are
> +        * used for bootcount values.
> +        */
> +       writel(RTC_KICK0R_WE, &reg->kick0r);
> +       writel(RTC_KICK1R_WE, &reg->kick1r);
> +       raw_bootcount_store(&reg->scratch0, a);
> +       raw_bootcount_store(&reg->scratch1, BOOTCOUNT_MAGIC);
> +}
> +
> +ulong bootcount_load(void)
> +{
> +       struct davinci_rtc *reg =
> +               (struct davinci_rtc *)CONFIG_SYS_BOOTCOUNT_ADDR;
> +
> +       if (raw_bootcount_load(&reg->scratch1) != BOOTCOUNT_MAGIC)
> +               return 0;
> +       else
> +               return raw_bootcount_load(&reg->scratch0);
> +}
> diff --git a/drivers/bootcount/bootcount_ram.c
> b/drivers/bootcount/bootcount_ram.c
> new file mode 100644
> index 0000000..8655af7
> --- /dev/null
> +++ b/drivers/bootcount/bootcount_ram.c
> @@ -0,0 +1,72 @@
> +/*
> + * (C) Copyright 2010
> + * Heiko Schocher, DENX Software Engineering, hs@denx.de <javascript:;>.
> + *
> + * 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.
> + *
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +const ulong patterns[]      = {        0x00000000,
> +                               0xFFFFFFFF,
> +                               0xFF00FF00,
> +                               0x0F0F0F0F,
> +                               0xF0F0F0F0};
> +const ulong NBR_OF_PATTERNS = sizeof(patterns) / sizeof(*patterns);
> +const ulong OFFS_PATTERN    = 3;
> +const ulong REPEAT_PATTERN  = 1000;
> +
> +void bootcount_store(ulong a)
> +{
> +       ulong *save_addr;
> +       ulong size = 0;
> +       int i;
> +
> +       for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
> +               size += gd->bd->bi_dram[i].size;
> +       save_addr = (ulong *)(size - BOOTCOUNT_ADDR);
> +       writel(a, save_addr);
> +       writel(BOOTCOUNT_MAGIC, &save_addr[1]);
> +
> +       for (i = 0; i < REPEAT_PATTERN; i++)
> +               writel(patterns[i % NBR_OF_PATTERNS],
> +                       &save_addr[i + OFFS_PATTERN]);
> +
> +}
> +
> +ulong bootcount_load(void)
> +{
> +       ulong *save_addr;
> +       ulong size = 0;
> +       ulong counter = 0;
> +       int i, tmp;
> +
> +       for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
> +               size += gd->bd->bi_dram[i].size;
> +       save_addr = (ulong *)(size - BOOTCOUNT_ADDR);
> +
> +       counter = readl(&save_addr[0]);
> +
> +       /* Is the counter reliable, check in the big pattern for bit
> errors */
> +       for (i = 0; (i < REPEAT_PATTERN) && (counter != 0); i++) {
> +               tmp = readl(&save_addr[i + OFFS_PATTERN]);
> +               if (tmp != patterns[i % NBR_OF_PATTERNS])
> +                       counter = 0;
> +       }
> +       return counter;
> +}
> diff --git a/include/bootcount.h b/include/bootcount.h
> new file mode 100644
> index 0000000..3ec1aec
> --- /dev/null
> +++ b/include/bootcount.h
> @@ -0,0 +1,51 @@
> +/*
> + * (C) Copyright 2012
> + * Stefan Roese, DENX Software Engineering, sr@denx.de <javascript:;>.
> + *
> + * 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.
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <asm/byteorder.h>
> +
> +#if !defined(CONFIG_SYS_BOOTCOUNT_LE) && !defined(CONFIG_SYS_BOOTCOUNT_BE)
> +# if __BYTE_ORDER == __LITTLE_ENDIAN
> +#  define CONFIG_SYS_BOOTCOUNT_LE
> +# else
> +#  define CONFIG_SYS_BOOTCOUNT_BE
> +# endif
> +#endif
> +
> +#ifdef CONFIG_SYS_BOOTCOUNT_LE
> +static inline void raw_bootcount_store(volatile u32 *addr, u32 data)
> +{
> +       out_le32(addr, data);
> +}
> +
> +static inline u32 raw_bootcount_load(volatile u32 *addr)
> +{
> +       return in_le32(addr);
> +}
> +#else
> +static inline void raw_bootcount_store(volatile u32 *addr, u32 data)
> +{
> +       out_be32(addr, data);
> +}
> +
> +static inline u32 raw_bootcount_load(volatile u32 *addr)
> +{
> +       return in_be32(addr);
> +}
> +#endif
> diff --git a/include/configs/calimain.h b/include/configs/calimain.h
> index e31e40b..8141fd7 100644
> --- a/include/configs/calimain.h
> +++ b/include/configs/calimain.h
> @@ -352,6 +352,7 @@
>  #define CONFIG_SYS_INIT_SP_ADDR                (0x8001ff00)
>
>  #define CONFIG_BOOTCOUNT_LIMIT
> +#define CONFIG_SYS_BOOTCOUNT_LE                /* Use little-endian
> accessors */
>  #define CONFIG_SYS_BOOTCOUNT_ADDR      DAVINCI_RTC_BASE
>
>  #ifndef __ASSEMBLY__
> diff --git a/include/configs/enbw_cmc.h b/include/configs/enbw_cmc.h
> index 3fc07e6..b99492c 100644
> --- a/include/configs/enbw_cmc.h
> +++ b/include/configs/enbw_cmc.h
> @@ -458,6 +458,7 @@
>
>  #define CONFIG_BOOTCOUNT_LIMIT
>  #define CONFIG_SYS_BOOTCOUNT_ADDR      DAVINCI_RTC_BASE
> +#define CONFIG_SYS_BOOTCOUNT_BE
>
>  #define CONFIG_SYS_NAND_U_BOOT_DST     0xc0080000
>  #define CONFIG_SYS_NAND_U_BOOT_OFFS    0x60004000
> diff --git a/include/configs/highbank.h b/include/configs/highbank.h
> index 791f3f5..897bc39 100644
> --- a/include/configs/highbank.h
> +++ b/include/configs/highbank.h
> @@ -41,6 +41,8 @@
>  #define CONFIG_BAUDRATE                        38400
>
>  #define CONFIG_BOOTCOUNT_LIMIT
> +#define CONFIG_SYS_BOOTCOUNT_SINGLEWORD
> +#define CONFIG_SYS_BOOTCOUNT_LE                /* Use little-endian
> accessors */
>  #define CONFIG_SYS_BOOTCOUNT_ADDR      0xfff3cf0c
>
>  #define CONFIG_MISC_INIT_R
> diff --git a/include/configs/km/km_arm.h b/include/configs/km/km_arm.h
> index 3aa5ca1..0d5ecd5 100644
> --- a/include/configs/km/km_arm.h
> +++ b/include/configs/km/km_arm.h
> @@ -307,6 +307,8 @@ int get_scl(void);
>  #define CONFIG_KM_RESERVED_PRAM 0x801000
>  /* address for the bootcount (taken from end of RAM) */
>  #define BOOTCOUNT_ADDR          (CONFIG_KM_RESERVED_PRAM)
> +/* Use generic bootcount RAM driver */
> +#define CONFIG_BOOTCOUNT_RAM
>
>  /* enable POST tests */
>  #define CONFIG_POST    (CONFIG_SYS_POST_MEM_REGIONS)
> --
> 1.7.11.3
>
> _______________________________________________
> U-Boot mailing list
> U-Boot@lists.denx.de <javascript:;>
> http://lists.denx.de/mailman/listinfo/u-boot
>
Mike Frysinger - Aug. 13, 2012, 5:33 p.m.
On Monday 13 August 2012 07:56:03 Stefan Roese wrote:
>  rename arch/blackfin/cpu/bootcount.c =>
> drivers/bootcount/bootcount_blackfin.c (100%) create mode 100644

hmm, file was moved, but forgot to update arch/blackfin/cpu/Makefile to no longer 
refer to bootcount.c, so it fails.

once that's fixed, it appears to build fine, and the compiled code looks OK to 
me.  might be able to convert to the common code, but for now, i won't bother 
as it'll require some testing first.
-mike

Patch

diff --git a/Makefile b/Makefile
index 5ce5cc3..2b662b4 100644
--- a/Makefile
+++ b/Makefile
@@ -249,6 +249,7 @@  LIBS-y += net/libnet.o
 LIBS-y += disk/libdisk.o
 LIBS-y += drivers/bios_emulator/libatibiosemu.o
 LIBS-y += drivers/block/libblock.o
+LIBS-$(CONFIG_BOOTCOUNT_LIMIT) += drivers/bootcount/libbootcount.o
 LIBS-y += drivers/dma/libdma.o
 LIBS-y += drivers/fpga/libfpga.o
 LIBS-y += drivers/gpio/libgpio.o
diff --git a/arch/arm/cpu/arm926ejs/at91/cpu.c b/arch/arm/cpu/arm926ejs/at91/cpu.c
index c47fb31..5cf4fad 100644
--- a/arch/arm/cpu/arm926ejs/at91/cpu.c
+++ b/arch/arm/cpu/arm926ejs/at91/cpu.c
@@ -71,29 +71,3 @@  int print_cpuinfo(void)
 	return 0;
 }
 #endif
-
-#ifdef CONFIG_BOOTCOUNT_LIMIT
-/*
- * We combine the BOOTCOUNT_MAGIC and bootcount in one 32-bit register.
- * This is done so we need to use only one of the four GPBR registers.
- */
-void bootcount_store (ulong a)
-{
-	at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR;
-
-	writel((BOOTCOUNT_MAGIC & 0xffff0000) | (a & 0x0000ffff),
-		&gpbr->reg[AT91_GPBR_INDEX_BOOTCOUNT]);
-}
-
-ulong bootcount_load (void)
-{
-	at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR;
-
-	ulong val = readl(&gpbr->reg[AT91_GPBR_INDEX_BOOTCOUNT]);
-	if ((val & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000))
-		return 0;
-	else
-		return val & 0x0000ffff;
-}
-
-#endif /* CONFIG_BOOTCOUNT_LIMIT */
diff --git a/arch/arm/cpu/armv7/highbank/Makefile b/arch/arm/cpu/armv7/highbank/Makefile
index 917c3a3..76faeb0 100644
--- a/arch/arm/cpu/armv7/highbank/Makefile
+++ b/arch/arm/cpu/armv7/highbank/Makefile
@@ -25,7 +25,7 @@  include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(SOC).o
 
-COBJS	:= timer.o bootcount.o
+COBJS	:= timer.o
 SOBJS	:=
 
 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
diff --git a/arch/arm/cpu/armv7/highbank/bootcount.c b/arch/arm/cpu/armv7/highbank/bootcount.c
deleted file mode 100644
index 9ca0656..0000000
--- a/arch/arm/cpu/armv7/highbank/bootcount.c
+++ /dev/null
@@ -1,36 +0,0 @@ 
-/*
- * Copyright 2011 Calxeda, Inc.
- *
- * 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 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include <common.h>
-#include <asm/io.h>
-
-#ifdef CONFIG_BOOTCOUNT_LIMIT
-void bootcount_store(ulong a)
-{
-	writel((BOOTCOUNT_MAGIC & 0xffff0000) | a, CONFIG_SYS_BOOTCOUNT_ADDR);
-}
-
-ulong bootcount_load(void)
-{
-	u32 tmp = readl(CONFIG_SYS_BOOTCOUNT_ADDR);
-
-	if ((tmp & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000))
-		return 0;
-	else
-		return tmp & 0x0000ffff;
-}
-#endif
diff --git a/arch/arm/cpu/ixp/cpu.c b/arch/arm/cpu/ixp/cpu.c
index 942845d..f1864d6 100644
--- a/arch/arm/cpu/ixp/cpu.c
+++ b/arch/arm/cpu/ixp/cpu.c
@@ -107,28 +107,6 @@  void pci_init(void)
 }
 */
 
-#ifdef CONFIG_BOOTCOUNT_LIMIT
-
-void bootcount_store (ulong a)
-{
-	volatile ulong *save_addr = (volatile ulong *)(CONFIG_SYS_BOOTCOUNT_ADDR);
-
-	save_addr[0] = a;
-	save_addr[1] = BOOTCOUNT_MAGIC;
-}
-
-ulong bootcount_load (void)
-{
-	volatile ulong *save_addr = (volatile ulong *)(CONFIG_SYS_BOOTCOUNT_ADDR);
-
-	if (save_addr[1] != BOOTCOUNT_MAGIC)
-		return 0;
-	else
-		return save_addr[0];
-}
-
-#endif /* CONFIG_BOOTCOUNT_LIMIT */
-
 int cpu_eth_init(bd_t *bis)
 {
 #ifdef CONFIG_IXP4XX_NPE
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index cdd62a2..965f9ea 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -46,7 +46,6 @@  SOBJS-y	+= reloc.o
 COBJS-$(CONFIG_BAT_RW) += bat_rw.o
 COBJS-y	+= board.o
 COBJS-y	+= bootm.o
-COBJS-$(CONFIG_BOOTCOUNT_LIMIT) += bootcount.o
 COBJS-y	+= cache.o
 COBJS-y	+= extable.o
 COBJS-y	+= interrupts.o
diff --git a/board/enbw/enbw_cmc/enbw_cmc.c b/board/enbw/enbw_cmc/enbw_cmc.c
index 0874e9c..67d5d4d 100644
--- a/board/enbw/enbw_cmc/enbw_cmc.c
+++ b/board/enbw/enbw_cmc/enbw_cmc.c
@@ -778,35 +778,6 @@  void arch_memory_failure_handle(void)
 }
 #endif
 
-#if defined(CONFIG_BOOTCOUNT_LIMIT)
-void bootcount_store(ulong a)
-{
-	struct davinci_rtc *reg =
-		(struct davinci_rtc *)CONFIG_SYS_BOOTCOUNT_ADDR;
-
-	/*
-	 * write RTC kick register to enable write
-	 * for RTC Scratch registers. Scratch0 and 1 are
-	 * used for bootcount values.
-	 */
-	writel(RTC_KICK0R_WE, &reg->kick0r);
-	writel(RTC_KICK1R_WE, &reg->kick1r);
-	out_be32(&reg->scratch0, a);
-	out_be32(&reg->scratch1, BOOTCOUNT_MAGIC);
-}
-
-ulong bootcount_load(void)
-{
-	struct davinci_rtc *reg =
-		(struct davinci_rtc *)CONFIG_SYS_BOOTCOUNT_ADDR;
-
-	if (in_be32(&reg->scratch1) != BOOTCOUNT_MAGIC)
-		return 0;
-	else
-		return in_be32(&reg->scratch0);
-}
-#endif
-
 ulong post_word_load(void)
 {
 	struct davinci_rtc *reg =
diff --git a/board/keymile/km_arm/km_arm.c b/board/keymile/km_arm/km_arm.c
index 2b2ca39..930c80e 100644
--- a/board/keymile/km_arm/km_arm.c
+++ b/board/keymile/km_arm/km_arm.c
@@ -408,57 +408,6 @@  int hush_init_var(void)
 }
 #endif
 
-#if defined(CONFIG_BOOTCOUNT_LIMIT)
-const ulong patterns[]      = {	0x00000000,
-				0xFFFFFFFF,
-				0xFF00FF00,
-				0x0F0F0F0F,
-				0xF0F0F0F0};
-const ulong NBR_OF_PATTERNS = ARRAY_SIZE(patterns);
-const ulong OFFS_PATTERN    = 3;
-const ulong REPEAT_PATTERN  = 1000;
-
-void bootcount_store(ulong a)
-{
-	ulong *save_addr;
-	ulong size = 0;
-	int i;
-
-	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
-		size += gd->bd->bi_dram[i].size;
-	save_addr = (ulong *)(size - BOOTCOUNT_ADDR);
-	writel(a, save_addr);
-	writel(BOOTCOUNT_MAGIC, &save_addr[1]);
-
-	for (i = 0; i < REPEAT_PATTERN; i++)
-		writel(patterns[i % NBR_OF_PATTERNS],
-			&save_addr[i+OFFS_PATTERN]);
-
-}
-
-ulong bootcount_load(void)
-{
-	ulong *save_addr;
-	ulong size = 0;
-	ulong counter = 0;
-	int i, tmp;
-
-	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
-		size += gd->bd->bi_dram[i].size;
-	save_addr = (ulong *)(size - BOOTCOUNT_ADDR);
-
-	counter = readl(&save_addr[0]);
-
-	/* Is the counter reliable, check in the big pattern for bit errors */
-	for (i = 0; (i < REPEAT_PATTERN) && (counter != 0); i++) {
-		tmp = readl(&save_addr[i+OFFS_PATTERN]);
-		if (tmp != patterns[i % NBR_OF_PATTERNS])
-			counter = 0;
-	}
-	return counter;
-}
-#endif
-
 #if defined(CONFIG_SOFT_I2C)
 void set_sda(int state)
 {
diff --git a/board/omicron/calimain/calimain.c b/board/omicron/calimain/calimain.c
index 54415ce..1060a1f 100644
--- a/board/omicron/calimain/calimain.c
+++ b/board/omicron/calimain/calimain.c
@@ -157,32 +157,3 @@  void hw_watchdog_reset(void)
 	davinci_hw_watchdog_reset();
 }
 #endif
-
-#if defined(CONFIG_BOOTCOUNT_LIMIT)
-void bootcount_store(ulong a)
-{
-	struct davinci_rtc *reg =
-		(struct davinci_rtc *)CONFIG_SYS_BOOTCOUNT_ADDR;
-
-	/*
-	 * write RTC kick register to enable write
-	 * for RTC Scratch registers. Scratch0 and 1 are
-	 * used for bootcount values.
-	 */
-	writel(RTC_KICK0R_WE, &reg->kick0r);
-	writel(RTC_KICK1R_WE, &reg->kick1r);
-	writel(a, &reg->scratch0);
-	writel(BOOTCOUNT_MAGIC, &reg->scratch1);
-}
-
-ulong bootcount_load(void)
-{
-	struct davinci_rtc *reg =
-		(struct davinci_rtc *)CONFIG_SYS_BOOTCOUNT_ADDR;
-
-	if (readl(&reg->scratch1) != BOOTCOUNT_MAGIC)
-		return 0;
-	else
-		return readl(&reg->scratch0);
-}
-#endif
diff --git a/drivers/bootcount/Makefile b/drivers/bootcount/Makefile
new file mode 100644
index 0000000..a8d0ac7
--- /dev/null
+++ b/drivers/bootcount/Makefile
@@ -0,0 +1,45 @@ 
+#
+# 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)libbootcount.o
+
+COBJS-y				+= bootcount.o
+COBJS-$(CONFIG_AT91SAM9XE)	+= bootcount_at91.o
+COBJS-$(CONFIG_BLACKFIN)	+= bootcount_blackfin.o
+COBJS-$(CONFIG_SOC_DA8XX)	+= bootcount_davinci.o
+COBJS-$(CONFIG_BOOTCOUNT_RAM)	+= bootcount_ram.o
+
+COBJS	:= $(COBJS-y)
+SRCS 	:= $(COBJS:.o=.c)
+OBJS 	:= $(addprefix $(obj),$(COBJS))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+########################################################################
diff --git a/arch/powerpc/lib/bootcount.c b/drivers/bootcount/bootcount.c
similarity index 82%
rename from arch/powerpc/lib/bootcount.c
rename to drivers/bootcount/bootcount.c
index f9ce539..80eb717 100644
--- a/arch/powerpc/lib/bootcount.c
+++ b/drivers/bootcount/bootcount.c
@@ -1,5 +1,5 @@ 
 /*
- * (C) Copyright 2010
+ * (C) Copyright 2010-2012
  * Stefan Roese, DENX Software Engineering, sr@denx.de.
  *
  * See file CREDITS for list of people who contributed to this
@@ -21,8 +21,8 @@ 
  * MA 02111-1307 USA
  */
 
-#include <common.h>
-#include <asm/io.h>
+#include <bootcount.h>
+#include <linux/compiler.h>
 
 /*
  * Only override CONFIG_SYS_BOOTCOUNT_ADDR if not already defined. This
@@ -65,33 +65,36 @@ 
 
 #endif /* !defined(CONFIG_SYS_BOOTCOUNT_ADDR) */
 
-void bootcount_store(ulong a)
+/* Now implement the generic default functions */
+#if defined(CONFIG_SYS_BOOTCOUNT_ADDR)
+__weak void bootcount_store(ulong a)
 {
 	void *reg = (void *)CONFIG_SYS_BOOTCOUNT_ADDR;
 
 #if defined(CONFIG_SYS_BOOTCOUNT_SINGLEWORD)
-	out_be32(reg, (BOOTCOUNT_MAGIC & 0xffff0000) | a);
+	raw_bootcount_store(reg, (BOOTCOUNT_MAGIC & 0xffff0000) | a);
 #else
-	out_be32(reg, a);
-	out_be32(reg + 4, BOOTCOUNT_MAGIC);
+	raw_bootcount_store(reg, a);
+	raw_bootcount_store(reg + 4, BOOTCOUNT_MAGIC);
 #endif
 }
 
-ulong bootcount_load(void)
+__weak ulong bootcount_load(void)
 {
 	void *reg = (void *)CONFIG_SYS_BOOTCOUNT_ADDR;
 
 #if defined(CONFIG_SYS_BOOTCOUNT_SINGLEWORD)
-	u32 tmp = in_be32(reg);
+	u32 tmp = raw_bootcount_load(reg);
 
 	if ((tmp & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000))
 		return 0;
 	else
 		return (tmp & 0x0000ffff);
 #else
-	if (in_be32(reg + 4) != BOOTCOUNT_MAGIC)
+	if (raw_bootcount_load(reg + 4) != BOOTCOUNT_MAGIC)
 		return 0;
 	else
-		return in_be32(reg);
+		return raw_bootcount_load(reg);
 #endif
 }
+#endif
diff --git a/drivers/bootcount/bootcount_at91.c b/drivers/bootcount/bootcount_at91.c
new file mode 100644
index 0000000..7cfe14d
--- /dev/null
+++ b/drivers/bootcount/bootcount_at91.c
@@ -0,0 +1,43 @@ 
+/*
+ * 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.
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/at91_gpbr.h>
+
+/*
+ * We combine the BOOTCOUNT_MAGIC and bootcount in one 32-bit register.
+ * This is done so we need to use only one of the four GPBR registers.
+ */
+void bootcount_store(ulong a)
+{
+	at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR;
+
+	writel((BOOTCOUNT_MAGIC & 0xffff0000) | (a & 0x0000ffff),
+		&gpbr->reg[AT91_GPBR_INDEX_BOOTCOUNT]);
+}
+
+ulong bootcount_load(void)
+{
+	at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR;
+
+	ulong val = readl(&gpbr->reg[AT91_GPBR_INDEX_BOOTCOUNT]);
+	if ((val & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000))
+		return 0;
+	else
+		return val & 0x0000ffff;
+}
diff --git a/arch/blackfin/cpu/bootcount.c b/drivers/bootcount/bootcount_blackfin.c
similarity index 100%
rename from arch/blackfin/cpu/bootcount.c
rename to drivers/bootcount/bootcount_blackfin.c
diff --git a/drivers/bootcount/bootcount_davinci.c b/drivers/bootcount/bootcount_davinci.c
new file mode 100644
index 0000000..1cd9436
--- /dev/null
+++ b/drivers/bootcount/bootcount_davinci.c
@@ -0,0 +1,49 @@ 
+/*
+ * (C) Copyright 2011
+ * Heiko Schocher, DENX Software Engineering, hs@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.
+ *
+ */
+
+#include <bootcount.h>
+#include <asm/arch/da850_lowlevel.h>
+#include <asm/arch/davinci_misc.h>
+
+void bootcount_store(ulong a)
+{
+	struct davinci_rtc *reg =
+		(struct davinci_rtc *)CONFIG_SYS_BOOTCOUNT_ADDR;
+
+	/*
+	 * write RTC kick register to enable write
+	 * for RTC Scratch registers. Scratch0 and 1 are
+	 * used for bootcount values.
+	 */
+	writel(RTC_KICK0R_WE, &reg->kick0r);
+	writel(RTC_KICK1R_WE, &reg->kick1r);
+	raw_bootcount_store(&reg->scratch0, a);
+	raw_bootcount_store(&reg->scratch1, BOOTCOUNT_MAGIC);
+}
+
+ulong bootcount_load(void)
+{
+	struct davinci_rtc *reg =
+		(struct davinci_rtc *)CONFIG_SYS_BOOTCOUNT_ADDR;
+
+	if (raw_bootcount_load(&reg->scratch1) != BOOTCOUNT_MAGIC)
+		return 0;
+	else
+		return raw_bootcount_load(&reg->scratch0);
+}
diff --git a/drivers/bootcount/bootcount_ram.c b/drivers/bootcount/bootcount_ram.c
new file mode 100644
index 0000000..8655af7
--- /dev/null
+++ b/drivers/bootcount/bootcount_ram.c
@@ -0,0 +1,72 @@ 
+/*
+ * (C) Copyright 2010
+ * Heiko Schocher, DENX Software Engineering, hs@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.
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+const ulong patterns[]      = {	0x00000000,
+				0xFFFFFFFF,
+				0xFF00FF00,
+				0x0F0F0F0F,
+				0xF0F0F0F0};
+const ulong NBR_OF_PATTERNS = sizeof(patterns) / sizeof(*patterns);
+const ulong OFFS_PATTERN    = 3;
+const ulong REPEAT_PATTERN  = 1000;
+
+void bootcount_store(ulong a)
+{
+	ulong *save_addr;
+	ulong size = 0;
+	int i;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
+		size += gd->bd->bi_dram[i].size;
+	save_addr = (ulong *)(size - BOOTCOUNT_ADDR);
+	writel(a, save_addr);
+	writel(BOOTCOUNT_MAGIC, &save_addr[1]);
+
+	for (i = 0; i < REPEAT_PATTERN; i++)
+		writel(patterns[i % NBR_OF_PATTERNS],
+			&save_addr[i + OFFS_PATTERN]);
+
+}
+
+ulong bootcount_load(void)
+{
+	ulong *save_addr;
+	ulong size = 0;
+	ulong counter = 0;
+	int i, tmp;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
+		size += gd->bd->bi_dram[i].size;
+	save_addr = (ulong *)(size - BOOTCOUNT_ADDR);
+
+	counter = readl(&save_addr[0]);
+
+	/* Is the counter reliable, check in the big pattern for bit errors */
+	for (i = 0; (i < REPEAT_PATTERN) && (counter != 0); i++) {
+		tmp = readl(&save_addr[i + OFFS_PATTERN]);
+		if (tmp != patterns[i % NBR_OF_PATTERNS])
+			counter = 0;
+	}
+	return counter;
+}
diff --git a/include/bootcount.h b/include/bootcount.h
new file mode 100644
index 0000000..3ec1aec
--- /dev/null
+++ b/include/bootcount.h
@@ -0,0 +1,51 @@ 
+/*
+ * (C) Copyright 2012
+ * Stefan Roese, DENX Software Engineering, sr@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.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+#if !defined(CONFIG_SYS_BOOTCOUNT_LE) && !defined(CONFIG_SYS_BOOTCOUNT_BE)
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+#  define CONFIG_SYS_BOOTCOUNT_LE
+# else
+#  define CONFIG_SYS_BOOTCOUNT_BE
+# endif
+#endif
+
+#ifdef CONFIG_SYS_BOOTCOUNT_LE
+static inline void raw_bootcount_store(volatile u32 *addr, u32 data)
+{
+	out_le32(addr, data);
+}
+
+static inline u32 raw_bootcount_load(volatile u32 *addr)
+{
+	return in_le32(addr);
+}
+#else
+static inline void raw_bootcount_store(volatile u32 *addr, u32 data)
+{
+	out_be32(addr, data);
+}
+
+static inline u32 raw_bootcount_load(volatile u32 *addr)
+{
+	return in_be32(addr);
+}
+#endif
diff --git a/include/configs/calimain.h b/include/configs/calimain.h
index e31e40b..8141fd7 100644
--- a/include/configs/calimain.h
+++ b/include/configs/calimain.h
@@ -352,6 +352,7 @@ 
 #define CONFIG_SYS_INIT_SP_ADDR		(0x8001ff00)
 
 #define CONFIG_BOOTCOUNT_LIMIT
+#define CONFIG_SYS_BOOTCOUNT_LE		/* Use little-endian accessors */
 #define CONFIG_SYS_BOOTCOUNT_ADDR	DAVINCI_RTC_BASE
 
 #ifndef __ASSEMBLY__
diff --git a/include/configs/enbw_cmc.h b/include/configs/enbw_cmc.h
index 3fc07e6..b99492c 100644
--- a/include/configs/enbw_cmc.h
+++ b/include/configs/enbw_cmc.h
@@ -458,6 +458,7 @@ 
 
 #define CONFIG_BOOTCOUNT_LIMIT
 #define CONFIG_SYS_BOOTCOUNT_ADDR	DAVINCI_RTC_BASE
+#define CONFIG_SYS_BOOTCOUNT_BE
 
 #define CONFIG_SYS_NAND_U_BOOT_DST	0xc0080000
 #define CONFIG_SYS_NAND_U_BOOT_OFFS	0x60004000
diff --git a/include/configs/highbank.h b/include/configs/highbank.h
index 791f3f5..897bc39 100644
--- a/include/configs/highbank.h
+++ b/include/configs/highbank.h
@@ -41,6 +41,8 @@ 
 #define CONFIG_BAUDRATE			38400
 
 #define CONFIG_BOOTCOUNT_LIMIT
+#define CONFIG_SYS_BOOTCOUNT_SINGLEWORD
+#define CONFIG_SYS_BOOTCOUNT_LE		/* Use little-endian accessors */
 #define CONFIG_SYS_BOOTCOUNT_ADDR	0xfff3cf0c
 
 #define CONFIG_MISC_INIT_R
diff --git a/include/configs/km/km_arm.h b/include/configs/km/km_arm.h
index 3aa5ca1..0d5ecd5 100644
--- a/include/configs/km/km_arm.h
+++ b/include/configs/km/km_arm.h
@@ -307,6 +307,8 @@  int get_scl(void);
 #define CONFIG_KM_RESERVED_PRAM 0x801000
 /* address for the bootcount (taken from end of RAM) */
 #define BOOTCOUNT_ADDR          (CONFIG_KM_RESERVED_PRAM)
+/* Use generic bootcount RAM driver */
+#define CONFIG_BOOTCOUNT_RAM
 
 /* enable POST tests */
 #define CONFIG_POST	(CONFIG_SYS_POST_MEM_REGIONS)