* [U-Boot] [PATCH v4 04/12] SPEAr : smi driver support for SPEAr SoCs
@ 2010-01-13 13:08 Tom
2010-01-14 10:50 ` Vipin Kumar
0 siblings, 1 reply; 4+ messages in thread
From: Tom @ 2010-01-13 13:08 UTC (permalink / raw)
To: u-boot
SPEAr SoCs contain a serial memory interface controller. This
controller is used to interface with spi based memories.
This patch adds the driver for this IP.
Signed-off-by: Vipin <vipin.kumar@st.com>
---
drivers/mtd/Makefile | 1 +
drivers/mtd/spr_smi.c | 529 ++++++++++++++++++++++++++++++++++
include/asm-arm/arch-spear/spr_smi.h | 117 ++++++++
3 files changed, 647 insertions(+), 0 deletions(-)
mode change 100644 => 100755 drivers/mtd/Makefile
create mode 100755 drivers/mtd/spr_smi.c
create mode 100755 include/asm-arm/arch-spear/spr_smi.h
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
old mode 100644
new mode 100755
index 754d648..cbf6f15
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -34,6 +34,7 @@ COBJS-$(CONFIG_FLASH_CFI_MTD) += cfi_mtd.o
COBJS-$(CONFIG_HAS_DATAFLASH) += dataflash.o
COBJS-$(CONFIG_FLASH_CFI_LEGACY) += jedec_flash.o
COBJS-$(CONFIG_MW_EEPROM) += mw_eeprom.o
+COBJS-$(CONFIG_SPEARSMI) += spr_smi.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
diff --git a/drivers/mtd/spr_smi.c b/drivers/mtd/spr_smi.c
new file mode 100755
index 0000000..092e313
--- /dev/null
+++ b/drivers/mtd/spr_smi.c
@@ -0,0 +1,529 @@
+/*
<snip>
+
+#if !defined(CONFIG_SYS_NO_FLASH)
+
+static struct smi_regs *const smicntl =
+ (struct smi_regs * const)CONFIG_SYS_SMI_BASE;
+static ulong bank_base[CONFIG_SYS_MAX_FLASH_BANKS] = CONFIG_SYS_FLASH_ADDR_BASE;
ws
80 chars per line
+flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
+
+#define ST_M25Pxx_ID 0x00002020
+
+static struct flash_dev flash_ids[] = {
+ {0x10, 64 * 1024, 2},
+ {0x11, 128 * 1024, 4},
+ {0x12, 256 * 1024, 4},
+ {0x13, 512 * 1024, 8},
+ {0x14, 1 * 1024 * 1024, 16},
+ {0x15, 2 * 1024 * 1024, 32},
+ {0x16, 4 * 1024 * 1024, 64},
+ {0x17, 8 * 1024 * 1024, 128},
+ {0x18, 16 * 1024 * 1024, 64},
+ {0x00,}
+};
+
Could be accessed like
{
.densisty = xxx,
.size = xxx,
.sector_count = xxx,
}
The 'density' field looks more like an id
+/*
+ * smi_wait_xfer_finish - Wait until TFF is set in status register
+ * @timeout: timeout in milliseconds
+ *
+ * Wait until TFF is set in status register
+ */
+static inline void smi_wait_xfer_finish(int timeout)
+{
Inline ?
Normally inline is for *.h files or maybe if you
want something optimized. With the sleep, this isn't likely.
Please justify or remove.
Apply change globally.
+ while (timeout--) {
+ if (readl(&smicntl->smi_sr) & TFF)
+ break;
+ udelay(1000);
+ }
+}
+
A timeout implies failure.
This function should return status
And the status checked.
+/*
+ * smi_read_id - Read flash id
+ * @info: flash_info structure pointer
+ * @banknum: bank number
+ *
+ * Read the flash id present at bank #banknum
+ */
+static unsigned int smi_read_id(flash_info_t *info, int banknum)
+{
+ unsigned int value;
+
+ writel(readl(&smicntl->smi_cr1) | SW_MODE, &smicntl->smi_cr1);
+ writel(READ_ID, &smicntl->smi_tr);
+ writel((banknum << BANKSEL_SHIFT) | SEND | TX_LEN_1 | RX_LEN_3,
+ &smicntl->smi_cr2);
+ smi_wait_xfer_finish(XFER_FINISH_TOUT);
+
+ value = (readl(&smicntl->smi_rr) & 0x00FFFFFF);
+
+ writel(readl(&smicntl->smi_sr) & ~(TFF), &smicntl->smi_sr);
+ writel(readl(&smicntl->smi_cr1) & ~(SW_MODE), &smicntl->smi_cr1);
+
Some of these '()''s are not strictly needed.
optionally reduce
+ return value;
+}
+
+/*
+ * flash_get_size - Detect the SMI flash by reading the ID.
+ * @base: Base address of the flash area bank #banknum
+ * @banknum: Bank number
+ *
+ * Detect the SMI flash by reading the ID. Initializes the flash_info structure
+ * with size, sector count etc.
+ */
+static ulong flash_get_size(ulong base, int banknum)
+{
+ flash_info_t *info = &flash_info[banknum];
+ struct flash_dev *dev;
+ unsigned int value;
+ unsigned int density;
+ int i;
+
+ value = smi_read_id(info, banknum);
+ density = (value >> 16) & 0xff;
+
+ for (i = 0, dev = &flash_ids[0]; dev->density != 0x0;
+ i++, dev = &flash_ids[i]) {
+ if (dev->density == density) {
+ info->size = dev->size;
+ info->sector_count = dev->sector_count;
+ break;
+ }
+ }
From the flash_ids's struct, it looks like 'density' field is
unique and increasing by 1. You may be able to replay this loop
with somthing like
density -= DENSITY_START
if (density < 0)
bail
else if (density > DESITY_END)
bail
then use desity as an index into the flash_ids array
info->size = flash_ids[density].size
+
+ if (0x0 == dev->density)
+ return 0;
swap operands
+
+ info->flash_id = value & 0xffff;
+ info->start[0] = base;
+
+ return info->size;
+}
+
+/*
+ * smi_read_sr - Read status register of SMI
+ * @bank: bank number
+ *
+ * This routine will get the status register of the flash chip present at the
+ * given bank
+ */
+static int smi_read_sr(int bank)
+{
+ u32 ctrlreg1;
+
+ /* store the CTRL REG1 state */
+ ctrlreg1 = readl(&smicntl->smi_cr1);
+
+ /* Program SMI in HW Mode */
+ writel(readl(&smicntl->smi_cr1) & ~(SW_MODE | WB_MODE),
+ &smicntl->smi_cr1);
+
+ /* Performing a RSR instruction in HW mode */
+ writel((bank << BANKSEL_SHIFT) | RD_STATUS_REG, &smicntl->smi_cr2);
+
+ smi_wait_xfer_finish(XFER_FINISH_TOUT);
+
+ /* Restore the CTRL REG1 state */
+ writel(ctrlreg1, &smicntl->smi_cr1);
+
+ return readl(&smicntl->smi_sr);
readl returns unsigned int
you may have problems with returning this as an int.
+}
+
+/*
+ * smi_wait_till_ready - Wait till last operation is over.
+ * @bank: bank number shifted.
+ * @timeout: timeout in milliseconds.
+ *
+ * This routine checks for WIP(write in progress)bit in Status register(SMSR-b0)
+ * The routine checks for #timeout loops, each at interval of 1 milli-second.
+ * If successful the routine returns 0.
+ */
+static int smi_wait_till_ready(int bank, int timeout)
+{
+ int count;
+ int sr;
+
+ /* One chip guarantees max 5 msec wait here after page writes,
+ but potentially three seconds (!) after page erase. */
+ for (count = 0; count < timeout; count++) {
+
+ sr = smi_read_sr(bank);
+ if (sr < 0)
+ break;
+ else if (!(sr & WIP_BIT))
+ return 0;
+
+ /* Try again after 1m-sec */
+ udelay(1000);
+ }
+ printf("SMI controller is still in wait, timeout=%d\n", timeout);
+ return -EIO;
Always failure ?
+}
+
+/*
+ * smi_write_enable - Enable the flash to do write operation
+ * @bank: bank number
+ *
+ * Set write enable latch with Write Enable command.
+ * Returns negative if error occurred.
Only returns 0.
please fix.
+ */
+static inline int smi_write_enable(int bank)
+{
Inline ?
See inline comments above
+ u32 ctrlreg1;
+ int timeout = WMODE_TOUT;
+
+ /* Store the CTRL REG1 state */
+ ctrlreg1 = readl(&smicntl->smi_cr1);
+
+ /* Program SMI in H/W Mode */
+ writel(readl(&smicntl->smi_cr1) & ~SW_MODE, &smicntl->smi_cr1);
+
+ /* Give the Flash, Write Enable command */
+ writel((bank << BANKSEL_SHIFT) | WE, &smicntl->smi_cr2);
+
+ smi_wait_xfer_finish(XFER_FINISH_TOUT);
+
+ /* Restore the CTRL REG1 state */
+ writel(ctrlreg1, &smicntl->smi_cr1);
+
+ while (timeout--) {
+ if (smi_read_sr(bank) & (1 << (bank + WM_SHIFT)))
+ break;
+ udelay(1000);
+ }
+
+ return 0;
+}
+
+/*
+ * smi_init - SMI initialization routine
+ *
+ * SMI initialization routine. Sets SMI control register1.
+ */
+static void smi_init(void)
+{
+ /* Setting the fast mode values. SMI working@166/4 = 41.5 MHz */
+ writel(HOLD1 | FAST_MODE | BANK_EN | DSEL_TIME | PRESCAL4,
+ &smicntl->smi_cr1);
+}
+
+/*
+ * smi_sector_erase - Erase flash sector
+ * @info: flash_info structure pointer
+ * @sector: sector number
+ *
+ * Set write enable latch with Write Enable command.
+ * Returns negative if error occurred.
+ */
+static int smi_sector_erase(flash_info_t *info, unsigned int sector)
+{
+ int bank;
+ unsigned int sect_add;
+ unsigned int instruction;
+
+ switch (info->start[0]) {
+ case SMIBANK0_BASE:
+ bank = BANK0;
+ break;
+ case SMIBANK1_BASE:
+ bank = BANK1;
+ break;
+ case SMIBANK2_BASE:
+ bank = BANK2;
+ break;
+ case SMIBANK3_BASE:
+ bank = BANK3;
+ break;
+ default:
+ return -1;
+ }
+
+ sect_add = sector * (info->size / info->sector_count);
+ instruction = ((sect_add >> 8) & 0x0000FF00) | SECTOR_ERASE;
+
+ writel(readl(&smicntl->smi_sr) & ~(ERF1 | ERF2), &smicntl->smi_sr);
+
+ if (info->flash_id == ST_M25Pxx_ID) {
+ /* Wait until finished previous write command. */
+ if (smi_wait_till_ready(bank, CONFIG_SYS_FLASH_ERASE_TOUT))
+ return -EBUSY;
+
+ /* Send write enable, before erase commands. */
+ if (smi_write_enable(bank))
+ return -EIO;
+
+ /* Put SMI in SW mode */
+ writel(readl(&smicntl->smi_cr1) | SW_MODE, &smicntl->smi_cr1);
+
+ /* Send Sector Erase command in SW Mode */
+ writel(instruction, &smicntl->smi_tr);
+ writel((bank << BANKSEL_SHIFT) | SEND | TX_LEN_4,
+ &smicntl->smi_cr2);
+ smi_wait_xfer_finish(XFER_FINISH_TOUT);
+
+ if (smi_wait_till_ready(bank, CONFIG_SYS_FLASH_ERASE_TOUT))
+ return -EBUSY;
+
+ /* Put SMI in HW mode */
+ writel(readl(&smicntl->smi_cr1) & ~(SW_MODE),
+ &smicntl->smi_cr1);
+
+ return 0;
+ } else {
+ /* Put SMI in HW mode */
+ writel(readl(&smicntl->smi_cr1) & ~(SW_MODE),
+ &smicntl->smi_cr1);
+ return -EINVAL;
+ }
+}
+
+/*
+ * smi_write - Write to SMI flash
+ * @src_addr: source buffer
+ * @dst_addr: destination buffer
+ * @length: length to write in words
+ * @bank: bank base address
+ *
+ * Write to SMI flash
+ */
+static int smi_write(unsigned int *src_addr, unsigned int *dst_addr,
+ unsigned int length, ulong bank_addr)
+{
+ int banknum;
+ unsigned int WM;
+
+ switch (bank_addr) {
+ case SMIBANK0_BASE:
+ banknum = BANK0;
+ WM = WM0;
+ break;
+ case SMIBANK1_BASE:
+ banknum = BANK1;
+ WM = WM1;
+ break;
+ case SMIBANK2_BASE:
+ banknum = BANK2;
+ WM = WM2;
+ break;
+ case SMIBANK3_BASE:
+ banknum = BANK3;
+ WM = WM3;
+ break;
+ default:
+ return -1;
+ }
+
+ if (smi_wait_till_ready(banknum, CONFIG_SYS_FLASH_WRITE_TOUT))
+ return -EBUSY;
+
+ /* Set SMI in Hardware Mode */
+ writel(readl(&smicntl->smi_cr1) & ~(SW_MODE), &smicntl->smi_cr1);
+
+ if (smi_write_enable(banknum))
+ return -EIO;
+
+ /* Perform the write command */
+ while (length--) {
+ if (((ulong) (dst_addr) % SFLASH_PAGE_SIZE) == 0) {
+ if (smi_wait_till_ready(banknum,
+ CONFIG_SYS_FLASH_WRITE_TOUT))
+ return -EBUSY;
+
+ if (smi_write_enable(banknum))
+ return -EIO;
+ }
+
+ *dst_addr++ = *src_addr++;
+
+ if ((readl(&smicntl->smi_sr) & (ERF1 | ERF2)))
+ return -EIO;
+ }
+
+ if (smi_wait_till_ready(banknum, CONFIG_SYS_FLASH_WRITE_TOUT))
+ return -EBUSY;
+
+ writel(readl(&smicntl->smi_sr) & ~(WCF), &smicntl->smi_sr);
+
+ return 0;
+}
+
+/*
+ * write_buff - Write to SMI flash
+ * @info: flash info structure
+ * @src: source buffer
+ * @dest_addr: destination buffer
+ * @length: length to write in words
+ *
+ * Write to SMI flash
+ */
+int write_buff(flash_info_t *info, uchar *src, ulong dest_addr, ulong length)
+{
+ smi_write((unsigned int *)src, (unsigned int *)dest_addr,
+ (length + 3) / 4, info->start[0]);
smi_write returns status.
This status should be returned to the callee.
+ return 0;
+}
+
+/*
+ * flash_init - SMI flash initialization
+ *
+ * SMI flash initialization
+ */
+unsigned long flash_init(void)
+{
+ unsigned long size = 0;
+ int i, j;
+
+ smi_init();
+
+ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
+ flash_info[i].flash_id = FLASH_UNKNOWN;
+ size += flash_info[i].size = flash_get_size(bank_base[i], i);
+ }
+
+ for (j = 0; j < CONFIG_SYS_MAX_FLASH_BANKS; j++) {
+ for (i = 1; i < flash_info[j].sector_count; i++)
+ flash_info[j].start[i] =
+ flash_info[j].start[i - 1] +
+ flash_info->size / flash_info->sector_count;
+
+ }
+
+ return size;
+}
+
+/*
+ * flash_print_info - Print SMI flash information
+ *
+ * Print SMI flash information
+ */
+void flash_print_info(flash_info_t *info)
+{
+ int i;
+ if (info->flash_id == FLASH_UNKNOWN) {
+ puts("missing or unknown FLASH type\n");
+ return;
+ }
+ printf(" Size: %ld MB in %d Sectors\n",
+ info->size >> 20, info->sector_count);
+
+ puts(" Sector Start Addresses:");
+ for (i = 0; i < info->sector_count; ++i) {
+#ifdef CONFIG_SYS_FLASH_EMPTY_INFO
+ int size;
+ int erased;
+ u32 *flash;
+
+ /*
+ * Check if whole sector is erased
+ */
+ size = (info->size) / (info->sector_count);
+ flash = (u32 *) info->start[i];
+ size = size / sizeof(int);
+
+ while ((size--) && (*flash++ == ~0))
+ ;
+
+ size++;
+ if (size)
+ erased = 0;
+ else
+ erased = 1;
+
+ if ((i % 5) == 0)
+ printf("\n");
+
+ printf(" %08lX%s%s",
+ info->start[i],
+ erased ? " E" : " ", info->protect[i] ? "RO " : " ");
+#else
+ if ((i % 5) == 0)
+ printf("\n ");
+ printf(" %08lX%s",
+ info->start[i], info->protect[i] ? " (RO) " : " ");
+#endif
+ }
+ putc('\n');
+ return;
+}
+
+/*
+ * flash_erase - Erase SMI flash
+ *
+ * Erase SMI flash
+ */
+int flash_erase(flash_info_t *info, int s_first, int s_last)
+{
+ int rcode = 0;
+ int prot = 0;
+ flash_sect_t sect;
+
+ if (info->flash_id == FLASH_UNKNOWN) {
+ puts("Can't erase unknown flash type - aborted\n");
+ return 1;
+ }
+
+ if ((s_first < 0) || (s_first > s_last)) {
+ puts("- no sectors to erase\n");
+ return 1;
+ }
+
+ for (sect = s_first; sect <= s_last; ++sect) {
+ if (info->protect[sect])
+ prot++;
+ }
+ if (prot) {
+ printf("- Warning: %d protected sectors will not be erased!\n",
+ prot);
+ } else {
+ putc('\n');
+ }
+
+ for (sect = s_first; sect <= s_last; sect++) {
+ if (info->protect[sect] == 0) {
+ switch (info->flash_id) {
+ case ST_M25Pxx_ID:
+ if (smi_sector_erase(info, sect))
+ rcode = 1;
+ else
+ putc('.');
+
+ break;
+
+ default:
+ printf("Unkown flash vendor 0x%x\n",
+ (u32) info->flash_id);
+ break;
This check can happen outside of the loop and likely earlier in the function
so you can bail earlier.
+ }
+ }
+ }
+ puts(" done\n");
+ return rcode;
+}
+#endif
diff --git a/include/asm-arm/arch-spear/spr_smi.h
b/include/asm-arm/arch-spear/spr_smi.h
new file mode 100755
index 0000000..a42a874
--- /dev/null
+++ b/include/asm-arm/arch-spear/spr_smi.h
@@ -0,0 +1,117 @@
+/*
+ * (C) Copyright 2009
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar at st.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
+ */
+
+#ifndef SPR_SMI_H
+#define SPR_SMI_H
+
+/* 0xF800.0000 . 0xFBFF.FFFF 64MB SMI (Serial Flash Mem) */
+/* 0xFC00.0000 . 0xFC1F.FFFF 2MB SMI (Serial Flash Reg.) */
+
+#define SMI_BASE CONFIG_SYS_SMI_BASE
ws
some extra spaces in the line above
please use tabs
+
+#define FLASH_START_ADDRESS CONFIG_SYS_FLASH_BASE
+#define FLASH_BANK_SIZE CONFIG_SYS_FLASH_BANK_SIZE
+
+#define SMIBANK0_BASE (FLASH_START_ADDRESS)
+#define SMIBANK1_BASE (SMIBANK0_BASE + FLASH_BANK_SIZE)
+#define SMIBANK2_BASE (SMIBANK1_BASE + FLASH_BANK_SIZE)
+#define SMIBANK3_BASE (SMIBANK2_BASE + FLASH_BANK_SIZE)
ws
some extra spaces in the 4 lines above
please use tabs
+
+#define BANK0 0
+#define BANK1 1
+#define BANK2 2
+#define BANK3 3
+
+struct smi_regs {
+ u32 smi_cr1;
+ u32 smi_cr2;
+ u32 smi_sr;
+ u32 smi_tr;
+ u32 smi_rr;
+};
+
+/* CONTROL REG 1 */
+#define BANK_EN 0x0000000F /* enables all banks */
+#define DSEL_TIME 0x00000060 /* Deselect time 6+1 SMI_CK periods */
+#define PRESCAL5 0x00000500 /* AHB_CK prescaling value */
+#define PRESCALA 0x00000A00 /* AHB_CK prescaling value */
+#define PRESCAL3 0x00000300 /* AHB_CK prescaling value */
+#define PRESCAL4 0x00000400 /* AHB_CK prescaling value */
+#define SW_MODE 0x10000000 /* enables SW Mode */
+#define WB_MODE 0x20000000 /* Write Burst Mode */
+#define FAST_MODE 0x00008000 /* Fast Mode */
+#define HOLD1 0x00010000
ws
Convert spaces to tabs
Similar from the next sections, apply this globally
+
+/* CONTROL REG 2 */
+#define RD_STATUS_REG 0x00000400 /* reads status reg */
+#define WE 0x00000800 /* Write Enable */
+#define BANK0_SEL 0x00000000 /* Select Banck0 */
+#define BANK1_SEL 0x00001000 /* Select Banck1 */
+#define BANK2_SEL 0x00002000 /* Select Banck2 */
+#define BANK3_SEL 0x00003000 /* Select Banck3 */
+#define BANKSEL_SHIFT 12
+#define SEND 0x00000080 /* Send data */
+#define TX_LEN_1 0x00000001 /* data length = 1 byte */
+#define TX_LEN_2 0x00000002 /* data length = 2 byte */
+#define TX_LEN_3 0x00000003 /* data length = 3 byte */
+#define TX_LEN_4 0x00000004 /* data length = 4 byte */
+#define RX_LEN_1 0x00000010 /* data length = 1 byte */
+#define RX_LEN_2 0x00000020 /* data length = 2 byte */
+#define RX_LEN_3 0x00000030 /* data length = 3 byte */
+#define RX_LEN_4 0x00000040 /* data length = 4 byte */
+#define TFIE 0x00000100 /* Transmission Flag Interrupt Enable */
+#define WCIE 0x00000200 /* Write Complete Interrupt Enable */
+
+/* STATUS_REG */
+#define INT_WCF_CLR 0xFFFFFDFF /* clear: WCF clear */
+#define INT_TFF_CLR 0xFFFFFEFF /* clear: TFF clear */
+#define WIP_BIT 0x00000001 /* WIP Bit of SPI SR on SMI SR */
+#define WEL_BIT 0x00000002 /* WEL Bit of SPI SR on SMI SR */
+#define RSR 0x00000005 /* Read Status regiser */
+#define TFF 0x00000100 /* Transfer Finished FLag */
+#define WCF 0x00000200 /* Transfer Finished FLag */
+#define ERF1 0x00000400 /* Error Flag 1 */
+#define ERF2 0x00000800 /* Error Flag 2 */
+#define WM0 0x00001000 /* WM Bank 0 */
+#define WM1 0x00002000 /* WM Bank 1 */
+#define WM2 0x00004000 /* WM Bank 2 */
+#define WM3 0x00008000 /* WM Bank 3 */
+#define WM_SHIFT 12
+
+/* TR REG */
+#define READ_ID 0x0000009F /* Read Identification */
+#define BULK_ERASE 0x000000C7 /* BULK erase */
+#define SECTOR_ERASE 0x000000D8 /* SECTOR erase */
+#define WRITE_ENABLE 0x00000006 /* Wenable command to FLASH */
+
+struct flash_dev {
+ u32 density;
+ ulong size;
+ ushort sector_count;
+};
+
+#define SFLASH_PAGE_SIZE 0x100
+#define XFER_FINISH_TOUT 2
+#define WMODE_TOUT 2
+
A comment on these variables would help.
Tom
^ permalink raw reply related [flat|nested] 4+ messages in thread* [U-Boot] [PATCH v4 04/12] SPEAr : smi driver support for SPEAr SoCs
2010-01-13 13:08 [U-Boot] [PATCH v4 04/12] SPEAr : smi driver support for SPEAr SoCs Tom
@ 2010-01-14 10:50 ` Vipin Kumar
2010-01-14 15:22 ` Tom
0 siblings, 1 reply; 4+ messages in thread
From: Vipin Kumar @ 2010-01-14 10:50 UTC (permalink / raw)
To: u-boot
Hello Tom,
> +
> +#define ST_M25Pxx_ID ? ? ? ? ? 0x00002020
> +
> +static struct flash_dev flash_ids[] = {
> + ? ? ? {0x10, 64 * 1024, 2},
> + ? ? ? {0x11, 128 * 1024, 4},
> + ? ? ? {0x12, 256 * 1024, 4},
> + ? ? ? {0x13, 512 * 1024, 8},
> + ? ? ? {0x14, 1 * 1024 * 1024, 16},
> + ? ? ? {0x15, 2 * 1024 * 1024, 32},
> + ? ? ? {0x16, 4 * 1024 * 1024, 64},
> + ? ? ? {0x17, 8 * 1024 * 1024, 128},
> + ? ? ? {0x18, 16 * 1024 * 1024, 64},
> + ? ? ? {0x00,}
> +};
> +
> Could be accessed like
> {
> ? ? ? ?.densisty = xxx,
> ? ? ? ?.size = xxx,
> ? ? ? ?.sector_count = xxx,
> }
>
This is meant to be a look up table, that's why I think the previous
way is batter.
Actually, I got the inspiration from drivers/mtd/nand/nand_ids.c
Still, I have changed it to look as below
{0x10, 0x10000, 2},
{0x11, 0x20000, 4},
{0x12, 0x40000, 4},
{0x13, 0x80000, 8},
size is changed to hex to stay vertically aligned
Please let me know if this is OK
> + *
> + * Detect the SMI flash by reading the ID. Initializes the flash_info structure
> + * with size, sector count etc.
> + */
> +static ulong flash_get_size(ulong base, int banknum)
> +{
> + ? ? ? flash_info_t *info = &flash_info[banknum];
> + ? ? ? struct flash_dev *dev;
> + ? ? ? unsigned int value;
> + ? ? ? unsigned int density;
> + ? ? ? int i;
> +
> + ? ? ? value = smi_read_id(info, banknum);
> + ? ? ? density = (value >> 16) & 0xff;
> +
> + ? ? ? for (i = 0, dev = &flash_ids[0]; dev->density != 0x0;
> + ? ? ? ? ? ?i++, dev = &flash_ids[i]) {
> + ? ? ? ? ? ? ? if (dev->density == density) {
> + ? ? ? ? ? ? ? ? ? ? ? info->size = dev->size;
> + ? ? ? ? ? ? ? ? ? ? ? info->sector_count = dev->sector_count;
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? }
> + ? ? ? }
> ?From the flash_ids's struct, it looks like 'density' field is
> unique and increasing by 1. ?You may be able to replay this loop
> with somthing like
>
> density -= DENSITY_START
> if (density < 0)
> ? ?bail
> else if (density > DESITY_END)
> ? ?bail
>
> then use desity as an index into the flash_ids array
> info->size = flash_ids[density].size
>
density is one byte of the read id which is read from flash itself
as of now, we are supporting consecutive values but these values
may be rendom in future
Thats why I used a look up table
> +static int smi_wait_till_ready(int bank, int timeout)
> +{
> + ? ? ? int count;
> + ? ? ? int sr;
> +
> + ? ? ? /* One chip guarantees max 5 msec wait here after page writes,
> + ? ? ? ? ?but potentially three seconds (!) after page erase. */
> + ? ? ? for (count = 0; count < timeout; count++) {
> +
> + ? ? ? ? ? ? ? sr = smi_read_sr(bank);
> + ? ? ? ? ? ? ? if (sr < 0)
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? else if (!(sr & WIP_BIT))
> + ? ? ? ? ? ? ? ? ? ? ? return 0;
> +
> + ? ? ? ? ? ? ? /* Try again after 1m-sec */
> + ? ? ? ? ? ? ? udelay(1000);
> + ? ? ? }
> + ? ? ? printf("SMI controller is still in wait, timeout=%d\n", timeout);
> + ? ? ? return -EIO;
>
> Always failure ?
>
There is a return 0 in case WIP_BIT gets reset
else if (!(sr & WIP_BIT))
return 0;
All the other comments are accepted and I would send a patchset v5 soon
Regards
Vipin
^ permalink raw reply [flat|nested] 4+ messages in thread* [U-Boot] [PATCH v4 04/12] SPEAr : smi driver support for SPEAr SoCs
2010-01-14 10:50 ` Vipin Kumar
@ 2010-01-14 15:22 ` Tom
0 siblings, 0 replies; 4+ messages in thread
From: Tom @ 2010-01-14 15:22 UTC (permalink / raw)
To: u-boot
Vipin Kumar wrote:
> Hello Tom,
>
>> +
>> +#define ST_M25Pxx_ID 0x00002020
>> +
>> +static struct flash_dev flash_ids[] = {
>> + {0x10, 64 * 1024, 2},
>> + {0x11, 128 * 1024, 4},
>> + {0x12, 256 * 1024, 4},
>> + {0x13, 512 * 1024, 8},
>> + {0x14, 1 * 1024 * 1024, 16},
>> + {0x15, 2 * 1024 * 1024, 32},
>> + {0x16, 4 * 1024 * 1024, 64},
>> + {0x17, 8 * 1024 * 1024, 128},
>> + {0x18, 16 * 1024 * 1024, 64},
>> + {0x00,}
>> +};
>> +
>> Could be accessed like
>> {
>> .densisty = xxx,
>> .size = xxx,
>> .sector_count = xxx,
>> }
>>
> This is meant to be a look up table, that's why I think the previous
> way is batter.
> Actually, I got the inspiration from drivers/mtd/nand/nand_ids.c
> Still, I have changed it to look as below
> {0x10, 0x10000, 2},
> {0x11, 0x20000, 4},
> {0x12, 0x40000, 4},
> {0x13, 0x80000, 8},
> size is changed to hex to stay vertically aligned
> Please let me know if this is OK
This is fine.
Improved readability a plus!
>
>> + *
>> + * Detect the SMI flash by reading the ID. Initializes the flash_info structure
>> + * with size, sector count etc.
>> + */
>> +static ulong flash_get_size(ulong base, int banknum)
>> +{
>> + flash_info_t *info = &flash_info[banknum];
>> + struct flash_dev *dev;
>> + unsigned int value;
>> + unsigned int density;
>> + int i;
>> +
>> + value = smi_read_id(info, banknum);
>> + density = (value >> 16) & 0xff;
>> +
>> + for (i = 0, dev = &flash_ids[0]; dev->density != 0x0;
>> + i++, dev = &flash_ids[i]) {
>> + if (dev->density == density) {
>> + info->size = dev->size;
>> + info->sector_count = dev->sector_count;
>> + break;
>> + }
>> + }
>> From the flash_ids's struct, it looks like 'density' field is
>> unique and increasing by 1. You may be able to replay this loop
>> with somthing like
>>
>> density -= DENSITY_START
>> if (density < 0)
>> bail
>> else if (density > DESITY_END)
>> bail
>>
>> then use desity as an index into the flash_ids array
>> info->size = flash_ids[density].size
>>
> density is one byte of the read id which is read from flash itself
> as of now, we are supporting consecutive values but these values
> may be rendom in future
> Thats why I used a look up table
Ok.
>
>> +static int smi_wait_till_ready(int bank, int timeout)
>> +{
>> + int count;
>> + int sr;
>> +
>> + /* One chip guarantees max 5 msec wait here after page writes,
>> + but potentially three seconds (!) after page erase. */
>> + for (count = 0; count < timeout; count++) {
>> +
>> + sr = smi_read_sr(bank);
>> + if (sr < 0)
>> + break;
>> + else if (!(sr & WIP_BIT))
>> + return 0;
>> +
>> + /* Try again after 1m-sec */
>> + udelay(1000);
>> + }
>> + printf("SMI controller is still in wait, timeout=%d\n", timeout);
>> + return -EIO;
>>
>> Always failure ?
>>
> There is a return 0 in case WIP_BIT gets reset
> else if (!(sr & WIP_BIT))
> return 0;
>
Sorry missed that
Tom
> All the other comments are accepted and I would send a patchset v5 soon
>
> Regards
> Vipin
^ permalink raw reply [flat|nested] 4+ messages in thread
* [U-Boot] [PATCH v4 00/12] Support for SPEAr SoCs
@ 2010-01-11 11:15 Vipin KUMAR
2010-01-11 11:15 ` [U-Boot] [PATCH v4 01/12] SPEAr : Adding README.spear in doc Vipin KUMAR
0 siblings, 1 reply; 4+ messages in thread
From: Vipin KUMAR @ 2010-01-11 11:15 UTC (permalink / raw)
To: u-boot
This is patch set version 4 for SPEAr SoC support
Modifications:
1. patch set reordered to add SPEAr arch, drivers and then board support
2. checkpatch warnings and errors removed
Vipin (12):
SPEAr : Adding README.spear in doc
SPEAr : Adding basic SPEAr architecture support.
SPEAr : i2c driver support added for SPEAr SoCs
SPEAr : smi driver support for SPEAr SoCs
SPEAr : nand driver support for SPEAr SoCs
SPEAr : usbd driver support for SPEAr SoCs
SPEAr : Support added for SPEAr600 board
SPEAr : Support for HW mac id read/write from i2c mem
SPEAr : Support added for SPEAr300 board
SPEAr : emi controller initialization for CFI driver support
SPEAr : Support added for SPEAr310 board
SPEAr : Support added for SPEAr320 board
MAKEALL | 4 +
Makefile | 6 +
board/spear/common/Makefile | 54 ++
board/spear/common/spr_lowlevel_init.S | 197 +++++
board/spear/common/spr_misc.c | 296 +++++++
board/spear/spear300/Makefile | 51 ++
board/spear/spear300/config.mk | 39 +
board/spear/spear300/spear300.c | 57 ++
board/spear/spear310/Makefile | 51 ++
board/spear/spear310/config.mk | 44 +
board/spear/spear310/spear310.c | 58 ++
board/spear/spear320/Makefile | 51 ++
board/spear/spear320/config.mk | 44 +
board/spear/spear320/spear320.c | 58 ++
board/spear/spear600/Makefile | 51 ++
board/spear/spear600/config.mk | 39 +
board/spear/spear600/spear600.c | 52 ++
cpu/arm926ejs/spear/Makefile | 52 ++
cpu/arm926ejs/spear/reset.c | 53 ++
cpu/arm926ejs/spear/timer.c | 150 ++++
doc/README.spear | 53 ++
drivers/i2c/Makefile | 1 +
drivers/i2c/spr_i2c.c | 330 ++++++++
drivers/mtd/Makefile | 1 +
drivers/mtd/nand/Makefile | 1 +
drivers/mtd/nand/spr_nand.c | 123 +++
drivers/mtd/spr_smi.c | 529 +++++++++++++
drivers/serial/usbtty.h | 2 +
drivers/usb/gadget/Makefile | 1 +
drivers/usb/gadget/spr_udc.c | 1002 ++++++++++++++++++++++++
include/asm-arm/arch-spear/spr_defs.h | 38 +
include/asm-arm/arch-spear/spr_emi.h | 54 ++
include/asm-arm/arch-spear/spr_gpt.h | 83 ++
include/asm-arm/arch-spear/spr_i2c.h | 146 ++++
include/asm-arm/arch-spear/spr_misc.h | 130 +++
include/asm-arm/arch-spear/spr_nand.h | 57 ++
include/asm-arm/arch-spear/spr_smi.h | 117 +++
include/asm-arm/arch-spear/spr_syscntl.h | 38 +
include/asm-arm/arch-spear/spr_xloader_table.h | 67 ++
include/configs/spear.h | 363 +++++++++
include/usb/spr_udc.h | 227 ++++++
41 files changed, 4770 insertions(+), 0 deletions(-)
create mode 100644 board/spear/common/Makefile
create mode 100755 board/spear/common/spr_lowlevel_init.S
create mode 100755 board/spear/common/spr_misc.c
create mode 100755 board/spear/spear300/Makefile
create mode 100755 board/spear/spear300/config.mk
create mode 100755 board/spear/spear300/spear300.c
create mode 100755 board/spear/spear310/Makefile
create mode 100755 board/spear/spear310/config.mk
create mode 100755 board/spear/spear310/spear310.c
create mode 100755 board/spear/spear320/Makefile
create mode 100755 board/spear/spear320/config.mk
create mode 100755 board/spear/spear320/spear320.c
create mode 100755 board/spear/spear600/Makefile
create mode 100755 board/spear/spear600/config.mk
create mode 100755 board/spear/spear600/spear600.c
create mode 100755 cpu/arm926ejs/spear/Makefile
create mode 100755 cpu/arm926ejs/spear/reset.c
create mode 100755 cpu/arm926ejs/spear/timer.c
create mode 100644 doc/README.spear
mode change 100644 => 100755 drivers/i2c/Makefile
create mode 100755 drivers/i2c/spr_i2c.c
mode change 100644 => 100755 drivers/mtd/Makefile
create mode 100755 drivers/mtd/nand/spr_nand.c
create mode 100755 drivers/mtd/spr_smi.c
mode change 100644 => 100755 drivers/serial/usbtty.h
mode change 100644 => 100755 drivers/usb/gadget/Makefile
create mode 100755 drivers/usb/gadget/spr_udc.c
create mode 100644 include/asm-arm/arch-spear/spr_defs.h
create mode 100644 include/asm-arm/arch-spear/spr_emi.h
create mode 100755 include/asm-arm/arch-spear/spr_gpt.h
create mode 100755 include/asm-arm/arch-spear/spr_i2c.h
create mode 100644 include/asm-arm/arch-spear/spr_misc.h
create mode 100644 include/asm-arm/arch-spear/spr_nand.h
create mode 100755 include/asm-arm/arch-spear/spr_smi.h
create mode 100644 include/asm-arm/arch-spear/spr_syscntl.h
create mode 100755 include/asm-arm/arch-spear/spr_xloader_table.h
create mode 100755 include/configs/spear.h
create mode 100755 include/usb/spr_udc.h
^ permalink raw reply [flat|nested] 4+ messages in thread
* [U-Boot] [PATCH v4 01/12] SPEAr : Adding README.spear in doc
2010-01-11 11:15 [U-Boot] [PATCH v4 00/12] Support " Vipin KUMAR
@ 2010-01-11 11:15 ` Vipin KUMAR
2010-01-11 11:15 ` [U-Boot] [PATCH v4 02/12] SPEAr : Adding basic SPEAr architecture support Vipin KUMAR
0 siblings, 1 reply; 4+ messages in thread
From: Vipin KUMAR @ 2010-01-11 11:15 UTC (permalink / raw)
To: u-boot
README.spear contains information about SPEAr architecture and
build options etc
Signed-off-by: Vipin <vipin.kumar@st.com>
---
doc/README.spear | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 53 insertions(+), 0 deletions(-)
create mode 100644 doc/README.spear
diff --git a/doc/README.spear b/doc/README.spear
new file mode 100644
index 0000000..59e9a95
--- /dev/null
+++ b/doc/README.spear
@@ -0,0 +1,53 @@
+
+SPEAr (Structured Processor Enhanced Architecture).
+
+SPEAr600 is also known as SPEArPlus and SPEAr300 is also known as SPEArBasic
+
+The SPEAr SoC family also embeds a customizable logic that could be programmed
+one-time by a customer at silicon mask level (i.e. not at runtime!).
+We are now adding the support in u-boot for two SoC: SPEAr600 and SPEAr3xx.
+Pls note that SPEAr300/310/320 differs only for the default customization.
+
+All 4 SoCs share common peripherals.
+
+1. ARM926ejs core based (sp600 has two cores, the 2nd handled only in Linux)
+2. FastEthernet (sp600 has Gbit version, but same controller - GMAC)
+3. USB Host
+4. USB Device
+5. NAND controller (FSMC)
+6. Serial NOR ctrl
+7. I2C
+8. SPI
+9. CLCD
+10. others ..
+
+sp600 is not customized by default.
+sp3xx are differently customized.
+sp300 is more oriented to TELECOM/video (it has tdm, i2s, ITU i/f support)
+sp310 for networking (a part GMAC in fixed part, it has 5 MACB ctrls in
+custom)
+sp320 for industrial (SPP ctrl, CAN ctrl, 2 MACBs, ...)
+
+Everything is supported in Linux.
+u-boot is not currently supporting all peripeharls (just a few).
+
+More description can be found on Internet, for example here:
+
+http://embedded-system.net/spear-basic-customizable-arm-based-soc-stmicroelectronics.html
+
+Build options
+ make spear600_config
+ make spear300_config
+ make spear310_config
+ make spear320_config
+
+Further options
+ make ENV=NAND (supported by all 4 SoCs)
+ - This option generates a uboot image that saves environment inn NAND
+
+ make CONSOLE=USB (supported by all 4 SoCs)
+ - This option generates a uboot image for using usbdevice as a tty i/f
+
+ make FLASH=PNOR (supported by SPEAr310 and SPEAr320)
+ - This option generates a uboot image that supports emi controller for
+ CFI compliant parallel NOR flash
--
1.6.0.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [U-Boot] [PATCH v4 02/12] SPEAr : Adding basic SPEAr architecture support.
2010-01-11 11:15 ` [U-Boot] [PATCH v4 01/12] SPEAr : Adding README.spear in doc Vipin KUMAR
@ 2010-01-11 11:15 ` Vipin KUMAR
2010-01-11 11:15 ` [U-Boot] [PATCH v4 03/12] SPEAr : i2c driver support added for SPEAr SoCs Vipin KUMAR
0 siblings, 1 reply; 4+ messages in thread
From: Vipin KUMAR @ 2010-01-11 11:15 UTC (permalink / raw)
To: u-boot
SPEAr Architecture support added. It contains the support for
following SPEAr blocks
- Timer
- System controller
- Misc registers
Signed-off-by: Vipin <vipin.kumar@st.com>
---
cpu/arm926ejs/spear/Makefile | 52 ++++++++++
cpu/arm926ejs/spear/reset.c | 53 +++++++++++
cpu/arm926ejs/spear/timer.c | 150 ++++++++++++++++++++++++++++++
include/asm-arm/arch-spear/spr_gpt.h | 83 ++++++++++++++++
include/asm-arm/arch-spear/spr_misc.h | 130 ++++++++++++++++++++++++++
include/asm-arm/arch-spear/spr_syscntl.h | 38 ++++++++
6 files changed, 506 insertions(+), 0 deletions(-)
create mode 100755 cpu/arm926ejs/spear/Makefile
create mode 100755 cpu/arm926ejs/spear/reset.c
create mode 100755 cpu/arm926ejs/spear/timer.c
create mode 100755 include/asm-arm/arch-spear/spr_gpt.h
create mode 100644 include/asm-arm/arch-spear/spr_misc.h
create mode 100644 include/asm-arm/arch-spear/spr_syscntl.h
diff --git a/cpu/arm926ejs/spear/Makefile b/cpu/arm926ejs/spear/Makefile
new file mode 100755
index 0000000..bf8dfa8
--- /dev/null
+++ b/cpu/arm926ejs/spear/Makefile
@@ -0,0 +1,52 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd at 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)lib$(SOC).a
+
+COBJS := reset.o \
+ timer.o
+SOBJS :=
+
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+SOBJS := $(addprefix $(obj),$(SOBJS))
+
+$(LIB): $(obj).depend $(OBJS) $(SOBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
+
+clean:
+ rm -f $(SOBJS) $(OBJS)
+
+distclean: clean
+ rm -f $(LIB) core *.bak $(obj).depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/cpu/arm926ejs/spear/reset.c b/cpu/arm926ejs/spear/reset.c
new file mode 100755
index 0000000..4df46a9
--- /dev/null
+++ b/cpu/arm926ejs/spear/reset.c
@@ -0,0 +1,53 @@
+/*
+ * (C) Copyright 2009
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar at st.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>
+#include <asm/io.h>
+#include <asm/arch/spr_syscntl.h>
+
+void reset_cpu(ulong ignored)
+{
+ struct syscntl_regs *syscntl_regs_p =
+ (struct syscntl_regs *)CONFIG_SPEAR_SYSCNTLBASE;
+
+ printf("System is going to reboot ...\n");
+
+ /*
+ * This 1 second delay will allow the above message
+ * to be printed before reset
+ */
+ udelay((1000 * 1000));
+
+ /* Going into slow mode before resetting SOC */
+ writel(0x02, &syscntl_regs_p->scctrl);
+
+ /*
+ * Writing any value to the system status register will
+ * reset the SoC
+ */
+ writel(0x00, &syscntl_regs_p->scsysstat);
+
+ /* system will restart */
+ while (1)
+ ;
+}
diff --git a/cpu/arm926ejs/spear/timer.c b/cpu/arm926ejs/spear/timer.c
new file mode 100755
index 0000000..2a265fb
--- /dev/null
+++ b/cpu/arm926ejs/spear/timer.c
@@ -0,0 +1,150 @@
+/*
+ * (C) Copyright 2009
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar at st.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>
+#include <asm/io.h>
+#include <asm/arch/spr_gpt.h>
+#include <asm/arch/spr_misc.h>
+
+#define GPT_RESOLUTION (CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ)
+#define READ_TIMER() (readl(&gpt_regs_p->count) & GPT_FREE_RUNNING)
+
+static struct gpt_regs *const gpt_regs_p =
+ (struct gpt_regs *)CONFIG_SPEAR_TIMERBASE;
+
+static struct misc_regs *const misc_regs_p =
+ (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
+
+static ulong timestamp;
+static ulong lastdec;
+
+int timer_init(void)
+{
+ u32 synth;
+
+ /* Prescaler setting */
+#if defined(CONFIG_SPEAR3XX)
+ writel(MISC_PRSC_CFG, &misc_regs_p->prsc2_clk_cfg);
+ synth = MISC_GPT4SYNTH;
+#elif defined(CONFIG_SPEAR600)
+ writel(MISC_PRSC_CFG, &misc_regs_p->prsc1_clk_cfg);
+ synth = MISC_GPT3SYNTH;
+#endif
+
+ writel(readl(&misc_regs_p->periph_clk_cfg) | synth,
+ &misc_regs_p->periph_clk_cfg);
+
+ /* disable timers */
+ writel(GPT_PRESCALER_1 | GPT_MODE_AUTO_RELOAD, &gpt_regs_p->control);
+
+ /* load value for free running */
+ writel(GPT_FREE_RUNNING, &gpt_regs_p->compare);
+
+ /* auto reload, start timer */
+ writel(readl(&gpt_regs_p->control) | GPT_ENABLE, &gpt_regs_p->control);
+
+ reset_timer_masked();
+
+ return 0;
+}
+
+/*
+ * timer without interrupts
+ */
+
+void reset_timer(void)
+{
+ reset_timer_masked();
+}
+
+ulong get_timer(ulong base)
+{
+ return (get_timer_masked() / GPT_RESOLUTION) - base;
+}
+
+void set_timer(ulong t)
+{
+ timestamp = t;
+}
+
+void __udelay(unsigned long usec)
+{
+ ulong tmo;
+ ulong start = get_timer_masked();
+ ulong tenudelcnt = CONFIG_SYS_HZ_CLOCK / (1000 * 100);
+ ulong rndoff;
+
+ rndoff = (usec % 10) ? 1 : 0;
+
+ /* tenudelcnt timer tick gives 10 microsecconds delay */
+ tmo = ((usec / 10) + rndoff) * tenudelcnt;
+
+ while ((ulong) (get_timer_masked() - start) < tmo)
+ ;
+}
+
+void reset_timer_masked(void)
+{
+ /* reset time */
+ lastdec = READ_TIMER();
+ timestamp = 0;
+}
+
+ulong get_timer_masked(void)
+{
+ ulong now = READ_TIMER();
+
+ if (now >= lastdec) {
+ /* normal mode */
+ timestamp += now - lastdec;
+ } else {
+ /* we have an overflow ... */
+ timestamp += now + GPT_FREE_RUNNING - lastdec;
+ }
+ lastdec = now;
+
+ return timestamp;
+}
+
+void udelay_masked(unsigned long usec)
+{
+ return udelay(usec);
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+ return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+ return CONFIG_SYS_HZ;
+}
diff --git a/include/asm-arm/arch-spear/spr_gpt.h b/include/asm-arm/arch-spear/spr_gpt.h
new file mode 100755
index 0000000..8e62391
--- /dev/null
+++ b/include/asm-arm/arch-spear/spr_gpt.h
@@ -0,0 +1,83 @@
+/*
+ * (C) Copyright 2009
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar at st.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
+ */
+
+#ifndef _SPR_GPT_H
+#define _SPR_GPT_H
+
+struct gpt_regs {
+ u8 reserved[0x80];
+ u32 control;
+ u32 status;
+ u32 compare;
+ u32 count;
+ u32 capture_re;
+ u32 capture_fe;
+};
+
+/*
+ * TIMER_CONTROL register settings
+ */
+
+#define GPT_PRESCALER_MASK 0x000F
+#define GPT_PRESCALER_1 0x0000
+#define GPT_PRESCALER_2 0x0001
+#define GPT_PRESCALER_4 0x0002
+#define GPT_PRESCALER_8 0x0003
+#define GPT_PRESCALER_16 0x0004
+#define GPT_PRESCALER_32 0x0005
+#define GPT_PRESCALER_64 0x0006
+#define GPT_PRESCALER_128 0x0007
+#define GPT_PRESCALER_256 0x0008
+
+#define GPT_MODE_SINGLE_SHOT 0x0010
+#define GPT_MODE_AUTO_RELOAD 0x0000
+
+#define GPT_ENABLE 0x0020
+
+#define GPT_CAPT_MODE_MASK 0x00C0
+#define GPT_CAPT_MODE_NONE 0x0000
+#define GPT_CAPT_MODE_RE 0x0040
+#define GPT_CAPT_MODE_FE 0x0080
+#define GPT_CAPT_MODE_BOTH 0x00C0
+
+#define GPT_INT_MATCH 0x0100
+
+#define GPT_INT_FE 0x0200
+
+#define GPT_INT_RE 0x0400
+
+/*
+ * TIMER_STATUS register settings
+ */
+
+#define GPT_STS_MATCH 0x0001
+#define GPT_STS_FE 0x0002
+#define GPT_STS_RE 0x0004
+
+/*
+ * TIMER_COMPARE register settings
+ */
+
+#define GPT_FREE_RUNNING 0xFFFF
+
+#endif
diff --git a/include/asm-arm/arch-spear/spr_misc.h b/include/asm-arm/arch-spear/spr_misc.h
new file mode 100644
index 0000000..8b96d9b
--- /dev/null
+++ b/include/asm-arm/arch-spear/spr_misc.h
@@ -0,0 +1,130 @@
+/*
+ * (C) Copyright 2009
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar at st.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
+ */
+
+#ifndef _SPR_MISC_H
+#define _SPR_MISC_H
+
+struct misc_regs {
+ u32 auto_cfg_reg; /* 0x0 */
+ u32 armdbg_ctr_reg; /* 0x4 */
+ u32 pll1_cntl; /* 0x8 */
+ u32 pll1_frq; /* 0xc */
+ u32 pll1_mod; /* 0x10 */
+ u32 pll2_cntl; /* 0x14 */
+ u32 pll2_frq; /* 0x18 */
+ u32 pll2_mod; /* 0x1C */
+ u32 pll_ctr_reg; /* 0x20 */
+ u32 amba_clk_cfg; /* 0x24 */
+ u32 periph_clk_cfg; /* 0x28 */
+ u32 periph1_clken; /* 0x2C */
+ u32 periph2_clken; /* 0x30 */
+ u32 ras_clken; /* 0x34 */
+ u32 periph1_rst; /* 0x38 */
+ u32 periph2_rst; /* 0x3C */
+ u32 ras_rst; /* 0x40 */
+ u32 prsc1_clk_cfg; /* 0x44 */
+ u32 prsc2_clk_cfg; /* 0x48 */
+ u32 prsc3_clk_cfg; /* 0x4C */
+ u32 amem_cfg_ctrl; /* 0x50 */
+ u32 port_cfg_ctrl; /* 0x54 */
+ u32 reserved_1; /* 0x58 */
+ u32 clcd_synth_clk; /* 0x5C */
+ u32 irda_synth_clk; /* 0x60 */
+ u32 uart_synth_clk; /* 0x64 */
+ u32 gmac_synth_clk; /* 0x68 */
+ u32 ras_synth1_clk; /* 0x6C */
+ u32 ras_synth2_clk; /* 0x70 */
+ u32 ras_synth3_clk; /* 0x74 */
+ u32 ras_synth4_clk; /* 0x78 */
+ u32 arb_icm_ml1; /* 0x7C */
+ u32 arb_icm_ml2; /* 0x80 */
+ u32 arb_icm_ml3; /* 0x84 */
+ u32 arb_icm_ml4; /* 0x88 */
+ u32 arb_icm_ml5; /* 0x8C */
+ u32 arb_icm_ml6; /* 0x90 */
+ u32 arb_icm_ml7; /* 0x94 */
+ u32 arb_icm_ml8; /* 0x98 */
+ u32 arb_icm_ml9; /* 0x9C */
+ u32 dma_src_sel; /* 0xA0 */
+ u32 uphy_ctr_reg; /* 0xA4 */
+ u32 gmac_ctr_reg; /* 0xA8 */
+ u32 port_bridge_ctrl; /* 0xAC */
+ u32 reserved_2[4]; /* 0xB0--0xBC */
+ u32 prc1_ilck_ctrl_reg; /* 0xC0 */
+ u32 prc2_ilck_ctrl_reg; /* 0xC4 */
+ u32 prc3_ilck_ctrl_reg; /* 0xC8 */
+ u32 prc4_ilck_ctrl_reg; /* 0xCC */
+ u32 prc1_intr_ctrl_reg; /* 0xD0 */
+ u32 prc2_intr_ctrl_reg; /* 0xD4 */
+ u32 prc3_intr_ctrl_reg; /* 0xD8 */
+ u32 prc4_intr_ctrl_reg; /* 0xDC */
+ u32 powerdown_cfg_reg; /* 0xE0 */
+ u32 ddr_1v8_compensation; /* 0xE4 */
+ u32 ddr_2v5_compensation; /* 0xE8 */
+ u32 core_3v3_compensation; /* 0xEC */
+ u32 ddr_pad; /* 0xF0 */
+ u32 bist1_ctr_reg; /* 0xF4 */
+ u32 bist2_ctr_reg; /* 0xF8 */
+ u32 bist3_ctr_reg; /* 0xFC */
+ u32 bist4_ctr_reg; /* 0x100 */
+ u32 bist5_ctr_reg; /* 0x104 */
+ u32 bist1_rslt_reg; /* 0x108 */
+ u32 bist2_rslt_reg; /* 0x10C */
+ u32 bist3_rslt_reg; /* 0x110 */
+ u32 bist4_rslt_reg; /* 0x114 */
+ u32 bist5_rslt_reg; /* 0x118 */
+ u32 syst_error_reg; /* 0x11C */
+ u32 reserved_3[0x1FB8]; /* 0x120--0x7FFC */
+ u32 ras_gpp1_in; /* 0x8000 */
+ u32 ras_gpp2_in; /* 0x8004 */
+ u32 ras_gpp1_out; /* 0x8008 */
+ u32 ras_gpp2_out; /* 0x800C */
+};
+
+/* AUTO_CFG_REG value */
+#define MISC_SOCCFGMSK 0x0000003F
+#define MISC_SOCCFG30 0x0000000C
+#define MISC_SOCCFG31 0x0000000D
+#define MISC_NANDDIS 0x00020000
+
+/* PERIPH_CLK_CFG value */
+#define MISC_GPT3SYNTH 0x00000400
+#define MISC_GPT4SYNTH 0x00000800
+
+/* PRSC_CLK_CFG value */
+/*
+ * Fout = Fin / (2^(N+1) * (M + 1))
+ */
+#define MISC_PRSC_N_1 0x00001000
+#define MISC_PRSC_M_9 0x00000009
+#define MISC_PRSC_N_4 0x00004000
+#define MISC_PRSC_M_399 0x0000018F
+#define MISC_PRSC_N_6 0x00006000
+#define MISC_PRSC_M_2593 0x00000A21
+#define MISC_PRSC_M_124 0x0000007C
+#define MISC_PRSC_CFG (MISC_PRSC_N_1 | MISC_PRSC_M_9)
+
+/* PERIPH1_CLKEN, PERIPH1_RST value */
+#define MISC_USBDENB 0x01000000
+
+#endif
diff --git a/include/asm-arm/arch-spear/spr_syscntl.h b/include/asm-arm/arch-spear/spr_syscntl.h
new file mode 100644
index 0000000..3c92f09
--- /dev/null
+++ b/include/asm-arm/arch-spear/spr_syscntl.h
@@ -0,0 +1,38 @@
+/*
+ * (C) Copyright 2009
+ * Ryan CHEN, ST Micoelectronics, ryan.chen at st.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
+ */
+
+struct syscntl_regs {
+ u32 scctrl;
+ u32 scsysstat;
+ u32 scimctrl;
+ u32 scimsysstat;
+ u32 scxtalctrl;
+ u32 scpllctrl;
+ u32 scpllfctrl;
+ u32 scperctrl0;
+ u32 scperctrl1;
+ u32 scperen;
+ u32 scperdis;
+ const u32 scperclken;
+ const u32 scperstat;
+};
--
1.6.0.2
^ permalink raw reply related [flat|nested] 4+ messages in thread* [U-Boot] [PATCH v4 03/12] SPEAr : i2c driver support added for SPEAr SoCs
2010-01-11 11:15 ` [U-Boot] [PATCH v4 02/12] SPEAr : Adding basic SPEAr architecture support Vipin KUMAR
@ 2010-01-11 11:15 ` Vipin KUMAR
2010-01-11 11:15 ` [U-Boot] [PATCH v4 04/12] SPEAr : smi driver support " Vipin KUMAR
0 siblings, 1 reply; 4+ messages in thread
From: Vipin KUMAR @ 2010-01-11 11:15 UTC (permalink / raw)
To: u-boot
SPEAr SoCs contain a synopsys i2c controller.
This patch adds the driver for this IP.
Signed-off-by: Vipin <vipin.kumar@st.com>
---
drivers/i2c/Makefile | 1 +
drivers/i2c/spr_i2c.c | 330 ++++++++++++++++++++++++++++++++++
include/asm-arm/arch-spear/spr_i2c.h | 146 +++++++++++++++
3 files changed, 477 insertions(+), 0 deletions(-)
mode change 100644 => 100755 drivers/i2c/Makefile
create mode 100755 drivers/i2c/spr_i2c.c
create mode 100755 include/asm-arm/arch-spear/spr_i2c.h
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
old mode 100644
new mode 100755
index b860e89..29bda85
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -37,6 +37,7 @@ COBJS-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o
COBJS-$(CONFIG_DRIVER_S3C24X0_I2C) += s3c24x0_i2c.o
COBJS-$(CONFIG_S3C44B0_I2C) += s3c44b0_i2c.o
COBJS-$(CONFIG_SOFT_I2C) += soft_i2c.o
+COBJS-$(CONFIG_SPEAR_I2C) += spr_i2c.o
COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
COBJS := $(COBJS-y)
diff --git a/drivers/i2c/spr_i2c.c b/drivers/i2c/spr_i2c.c
new file mode 100755
index 0000000..096de65
--- /dev/null
+++ b/drivers/i2c/spr_i2c.c
@@ -0,0 +1,330 @@
+/*
+ * (C) Copyright 2009
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar at st.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>
+#include <asm/io.h>
+#include <asm/arch/spr_i2c.h>
+
+static struct i2c_regs *const i2c_regs_p =
+ (struct i2c_regs *)CONFIG_SYS_I2C_BASE;
+
+/*
+ * set_speed - Set the i2c speed mode (standard, high, fast)
+ * @i2c_spd: required i2c speed mode
+ *
+ * Set the i2c speed mode (standard, high, fast)
+ */
+static void set_speed(int i2c_spd)
+{
+ unsigned int cntl;
+ unsigned int hcnt, lcnt;
+ unsigned int high, low;
+
+ cntl = (readl(&i2c_regs_p->ic_con) & (~IC_CON_SPD_MSK));
+
+ switch (i2c_spd) {
+ case IC_SPEED_MODE_MAX:
+ cntl |= IC_CON_SPD_HS;
+ high = MIN_HS_SCL_HIGHTIME;
+ low = MIN_HS_SCL_LOWTIME;
+ break;
+
+ case IC_SPEED_MODE_STANDARD:
+ cntl |= IC_CON_SPD_SS;
+ high = MIN_SS_SCL_HIGHTIME;
+ low = MIN_SS_SCL_LOWTIME;
+ break;
+
+ case IC_SPEED_MODE_FAST:
+ default:
+ cntl |= IC_CON_SPD_FS;
+ high = MIN_FS_SCL_HIGHTIME;
+ low = MIN_FS_SCL_LOWTIME;
+ break;
+ }
+
+ writel(cntl, &i2c_regs_p->ic_con);
+
+ hcnt = (IC_CLK * high) / NANO_TO_MICRO;
+ writel(hcnt, &i2c_regs_p->ic_fs_scl_hcnt);
+
+ lcnt = (IC_CLK * low) / NANO_TO_MICRO;
+ writel(lcnt, &i2c_regs_p->ic_fs_scl_lcnt);
+}
+
+/*
+ * i2c_set_bus_speed - Set the i2c speed
+ * @speed: required i2c speed
+ *
+ * Set the i2c speed.
+ */
+void i2c_set_bus_speed(int speed)
+{
+ if (speed >= I2C_MAX_SPEED)
+ set_speed(IC_SPEED_MODE_MAX);
+ else if (speed >= I2C_FAST_SPEED)
+ set_speed(IC_SPEED_MODE_FAST);
+ else
+ set_speed(IC_SPEED_MODE_STANDARD);
+}
+
+/*
+ * i2c_get_bus_speed - Gets the i2c speed
+ *
+ * Gets the i2c speed.
+ */
+int i2c_get_bus_speed(void)
+{
+ u32 cntl;
+
+ cntl = (readl(&i2c_regs_p->ic_con) & IC_CON_SPD_MSK);
+
+ if (cntl == IC_CON_SPD_HS)
+ return I2C_MAX_SPEED;
+ else if (cntl == IC_CON_SPD_FS)
+ return I2C_FAST_SPEED;
+ else if (cntl == IC_CON_SPD_SS)
+ return I2C_STANDARD_SPEED;
+
+ return 0;
+}
+
+/*
+ * i2c_init - Init function
+ * @speed: required i2c speed
+ * @slaveadd: slave address for the spear device
+ *
+ * Initialization function.
+ */
+void i2c_init(int speed, int slaveadd)
+{
+ unsigned int enbl;
+
+ /* Disable i2c */
+ enbl = readl(&i2c_regs_p->ic_enable);
+ enbl &= ~IC_ENABLE_0B;
+ writel(enbl, &i2c_regs_p->ic_enable);
+
+ writel((IC_CON_SD | IC_CON_SPD_FS | IC_CON_MM), &i2c_regs_p->ic_con);
+ writel(IC_RX_TL, &i2c_regs_p->ic_rx_tl);
+ writel(IC_TX_TL, &i2c_regs_p->ic_tx_tl);
+ i2c_set_bus_speed(speed);
+ writel(IC_STOP_DET, &i2c_regs_p->ic_intr_mask);
+ writel(slaveadd, &i2c_regs_p->ic_sar);
+
+ /* Enable i2c */
+ enbl = readl(&i2c_regs_p->ic_enable);
+ enbl |= IC_ENABLE_0B;
+ writel(enbl, &i2c_regs_p->ic_enable);
+}
+
+/*
+ * i2c_setaddress - Sets the target slave address
+ * @i2c_addr: target i2c address
+ *
+ * Sets the target slave address.
+ */
+static void i2c_setaddress(unsigned int i2c_addr)
+{
+ writel(i2c_addr, &i2c_regs_p->ic_tar);
+}
+
+/*
+ * i2c_flush_rxfifo - Flushes the i2c RX FIFO
+ *
+ * Flushes the i2c RX FIFO
+ */
+static void i2c_flush_rxfifo(void)
+{
+ while (readl(&i2c_regs_p->ic_status) & IC_STATUS_RFNE)
+ readl(&i2c_regs_p->ic_cmd_data);
+}
+
+/*
+ * i2c_wait_for_bb - Waits for bus busy
+ *
+ * Waits for bus busy
+ */
+static int i2c_wait_for_bb(void)
+{
+ unsigned long start_time_bb = get_timer(0);
+
+ while ((readl(&i2c_regs_p->ic_status) & IC_STATUS_MA) ||
+ !(readl(&i2c_regs_p->ic_status) & IC_STATUS_TFE)) {
+
+ /* Evaluate timeout */
+ if (get_timer(start_time_bb) > (unsigned long)(I2C_BYTE_TO_BB))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* check parameters for i2c_read and i2c_write */
+static int check_params(uint addr, int alen, uchar *buffer, int len)
+{
+ if (buffer == NULL) {
+ printf("Buffer is invalid\n");
+ return 1;
+ }
+
+ if (alen > 1) {
+ printf("addr len %d not supported\n", alen);
+ return 1;
+ }
+
+ if (addr + len > 256) {
+ printf("address out of range\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int i2c_xfer_init(uchar chip, uint addr)
+{
+ if (i2c_wait_for_bb()) {
+ printf("Timed out waiting for bus\n");
+ return 1;
+ }
+
+ i2c_setaddress(chip);
+ writel(addr, &i2c_regs_p->ic_cmd_data);
+
+ return 0;
+}
+
+static int i2c_xfer_finish(void)
+{
+ ulong start_stop_det = get_timer(0);
+
+ while (1) {
+ if ((readl(&i2c_regs_p->ic_raw_intr_stat) & IC_STOP_DET)) {
+ readl(&i2c_regs_p->ic_clr_stop_det);
+ break;
+ } else if (get_timer(start_stop_det) > I2C_STOPDET_TO) {
+ break;
+ }
+ }
+
+ if (i2c_wait_for_bb()) {
+ printf("Timed out waiting for bus\n");
+ return 1;
+ }
+
+ i2c_flush_rxfifo();
+
+ /* Wait for read/write operation to complete on actual memory */
+ udelay(10000);
+
+ return 0;
+}
+
+/*
+ * i2c_read - Read from i2c memory
+ * @chip: target i2c address
+ * @addr: address to read from
+ * @alen:
+ * @buffer: buffer for read data
+ * @len: no of bytes to be read
+ *
+ * Read from i2c memory.
+ */
+int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+ unsigned long start_time_rx;
+
+ if (check_params(addr, alen, buffer, len))
+ return 1;
+
+ if (i2c_xfer_init(chip, addr))
+ return 1;
+
+ start_time_rx = get_timer(0);
+ while (len) {
+ writel(IC_CMD, &i2c_regs_p->ic_cmd_data);
+
+ if (readl(&i2c_regs_p->ic_status) & IC_STATUS_RFNE) {
+ *buffer++ = (uchar)readl(&i2c_regs_p->ic_cmd_data);
+ len--;
+ start_time_rx = get_timer(0);
+
+ } else if (get_timer(start_time_rx) > I2C_BYTE_TO) {
+ printf("Timed out. i2c read Failed\n");
+ return 1;
+ }
+ }
+
+ return i2c_xfer_finish();
+}
+
+/*
+ * i2c_write - Write to i2c memory
+ * @chip: target i2c address
+ * @addr: address to read from
+ * @alen:
+ * @buffer: buffer for read data
+ * @len: no of bytes to be read
+ *
+ * Write to i2c memory.
+ */
+int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+ int nb = len;
+ unsigned long start_time_tx;
+
+ if (check_params(addr, alen, buffer, len))
+ return 1;
+
+ if (i2c_xfer_init(chip, addr))
+ return 1;
+
+ start_time_tx = get_timer(0);
+ while (len) {
+ if (readl(&i2c_regs_p->ic_status) & IC_STATUS_TFNF) {
+ writel(*buffer, &i2c_regs_p->ic_cmd_data);
+ buffer++;
+ len--;
+ start_time_tx = get_timer(0);
+
+ } else if (get_timer(start_time_tx) > (nb * I2C_BYTE_TO)) {
+ printf("Timed out. i2c write Failed\n");
+ return 1;
+ }
+ }
+
+ return i2c_xfer_finish();
+}
+
+/*
+ * i2c_probe - Probe the i2c chip
+ */
+int i2c_probe(uchar chip)
+{
+ u32 tmp;
+
+ /*
+ * Try to read the first location of the chip.
+ */
+ return i2c_read(chip, 0, 1, (uchar *)&tmp, 1);
+}
diff --git a/include/asm-arm/arch-spear/spr_i2c.h b/include/asm-arm/arch-spear/spr_i2c.h
new file mode 100755
index 0000000..7521ebc
--- /dev/null
+++ b/include/asm-arm/arch-spear/spr_i2c.h
@@ -0,0 +1,146 @@
+/*
+ * (C) Copyright 2009
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar at st.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
+ */
+
+#ifndef __SPR_I2C_H_
+#define __SPR_I2C_H_
+
+struct i2c_regs {
+ u32 ic_con;
+ u32 ic_tar;
+ u32 ic_sar;
+ u32 ic_hs_maddr;
+ u32 ic_cmd_data;
+ u32 ic_ss_scl_hcnt;
+ u32 ic_ss_scl_lcnt;
+ u32 ic_fs_scl_hcnt;
+ u32 ic_fs_scl_lcnt;
+ u32 ic_hs_scl_hcnt;
+ u32 ic_hs_scl_lcnt;
+ u32 ic_intr_stat;
+ u32 ic_intr_mask;
+ u32 ic_raw_intr_stat;
+ u32 ic_rx_tl;
+ u32 ic_tx_tl;
+ u32 ic_clr_intr;
+ u32 ic_clr_rx_under;
+ u32 ic_clr_rx_over;
+ u32 ic_clr_tx_over;
+ u32 ic_clr_rd_req;
+ u32 ic_clr_tx_abrt;
+ u32 ic_clr_rx_done;
+ u32 ic_clr_activity;
+ u32 ic_clr_stop_det;
+ u32 ic_clr_start_det;
+ u32 ic_clr_gen_call;
+ u32 ic_enable;
+ u32 ic_status;
+ u32 ic_txflr;
+ u32 ix_rxflr;
+ u32 reserved_1;
+ u32 ic_tx_abrt_source;
+};
+
+#define IC_CLK 166
+#define NANO_TO_MICRO 1000
+
+/* High and low times in different speed modes (in ns) */
+#define MIN_SS_SCL_HIGHTIME 4000
+#define MIN_SS_SCL_LOWTIME 5000
+#define MIN_FS_SCL_HIGHTIME 800
+#define MIN_FS_SCL_LOWTIME 1700
+#define MIN_HS_SCL_HIGHTIME 60
+#define MIN_HS_SCL_LOWTIME 160
+
+/* Worst case timeout for 1 byte is kept as 2ms */
+#define I2C_BYTE_TO (CONFIG_SYS_HZ/500)
+#define I2C_STOPDET_TO (CONFIG_SYS_HZ/500)
+#define I2C_BYTE_TO_BB (I2C_BYTE_TO * 16)
+
+/* i2c control register definitions */
+#define IC_CON_SD 0x0040
+#define IC_CON_RE 0x0020
+#define IC_CON_10BITADDRMASTER 0x0010
+#define IC_CON_10BITADDR_SLAVE 0x0008
+#define IC_CON_SPD_MSK 0x0006
+#define IC_CON_SPD_SS 0x0002
+#define IC_CON_SPD_FS 0x0004
+#define IC_CON_SPD_HS 0x0006
+#define IC_CON_MM 0x0001
+
+/* i2c target address register definitions */
+#define TAR_ADDR 0x0050
+
+/* i2c slave address register definitions */
+#define IC_SLAVE_ADDR 0x0002
+
+/* i2c data buffer and command register definitions */
+#define IC_CMD 0x0100
+
+/* i2c interrupt status register definitions */
+#define IC_GEN_CALL 0x0800
+#define IC_START_DET 0x0400
+#define IC_STOP_DET 0x0200
+#define IC_ACTIVITY 0x0100
+#define IC_RX_DONE 0x0080
+#define IC_TX_ABRT 0x0040
+#define IC_RD_REQ 0x0020
+#define IC_TX_EMPTY 0x0010
+#define IC_TX_OVER 0x0008
+#define IC_RX_FULL 0x0004
+#define IC_RX_OVER 0x0002
+#define IC_RX_UNDER 0x0001
+
+/* fifo threshold register definitions */
+#define IC_TL0 0x00
+#define IC_TL1 0x01
+#define IC_TL2 0x02
+#define IC_TL3 0x03
+#define IC_TL4 0x04
+#define IC_TL5 0x05
+#define IC_TL6 0x06
+#define IC_TL7 0x07
+#define IC_RX_TL IC_TL0
+#define IC_TX_TL IC_TL0
+
+/* i2c enable register definitions */
+#define IC_ENABLE_0B 0x0001
+
+/* i2c status register definitions */
+#define IC_STATUS_SA 0x0040
+#define IC_STATUS_MA 0x0020
+#define IC_STATUS_RFF 0x0010
+#define IC_STATUS_RFNE 0x0008
+#define IC_STATUS_TFE 0x0004
+#define IC_STATUS_TFNF 0x0002
+#define IC_STATUS_ACT 0x0001
+
+/* Speed Selection */
+#define IC_SPEED_MODE_STANDARD 1
+#define IC_SPEED_MODE_FAST 2
+#define IC_SPEED_MODE_MAX 3
+
+#define I2C_MAX_SPEED 3400000
+#define I2C_FAST_SPEED 400000
+#define I2C_STANDARD_SPEED 100000
+
+#endif /* __SPR_I2C_H_ */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 4+ messages in thread* [U-Boot] [PATCH v4 04/12] SPEAr : smi driver support for SPEAr SoCs
2010-01-11 11:15 ` [U-Boot] [PATCH v4 03/12] SPEAr : i2c driver support added for SPEAr SoCs Vipin KUMAR
@ 2010-01-11 11:15 ` Vipin KUMAR
0 siblings, 0 replies; 4+ messages in thread
From: Vipin KUMAR @ 2010-01-11 11:15 UTC (permalink / raw)
To: u-boot
SPEAr SoCs contain a serial memory interface controller. This
controller is used to interface with spi based memories.
This patch adds the driver for this IP.
Signed-off-by: Vipin <vipin.kumar@st.com>
---
drivers/mtd/Makefile | 1 +
drivers/mtd/spr_smi.c | 529 ++++++++++++++++++++++++++++++++++
include/asm-arm/arch-spear/spr_smi.h | 117 ++++++++
3 files changed, 647 insertions(+), 0 deletions(-)
mode change 100644 => 100755 drivers/mtd/Makefile
create mode 100755 drivers/mtd/spr_smi.c
create mode 100755 include/asm-arm/arch-spear/spr_smi.h
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
old mode 100644
new mode 100755
index 754d648..cbf6f15
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -34,6 +34,7 @@ COBJS-$(CONFIG_FLASH_CFI_MTD) += cfi_mtd.o
COBJS-$(CONFIG_HAS_DATAFLASH) += dataflash.o
COBJS-$(CONFIG_FLASH_CFI_LEGACY) += jedec_flash.o
COBJS-$(CONFIG_MW_EEPROM) += mw_eeprom.o
+COBJS-$(CONFIG_SPEARSMI) += spr_smi.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
diff --git a/drivers/mtd/spr_smi.c b/drivers/mtd/spr_smi.c
new file mode 100755
index 0000000..092e313
--- /dev/null
+++ b/drivers/mtd/spr_smi.c
@@ -0,0 +1,529 @@
+/*
+ * (C) Copyright 2009
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar at st.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>
+#include <flash.h>
+#include <linux/err.h>
+
+#include <asm/io.h>
+#include <asm/arch/spr_smi.h>
+
+#if !defined(CONFIG_SYS_NO_FLASH)
+
+static struct smi_regs *const smicntl =
+ (struct smi_regs * const)CONFIG_SYS_SMI_BASE;
+static ulong bank_base[CONFIG_SYS_MAX_FLASH_BANKS] = CONFIG_SYS_FLASH_ADDR_BASE;
+flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
+
+#define ST_M25Pxx_ID 0x00002020
+
+static struct flash_dev flash_ids[] = {
+ {0x10, 64 * 1024, 2},
+ {0x11, 128 * 1024, 4},
+ {0x12, 256 * 1024, 4},
+ {0x13, 512 * 1024, 8},
+ {0x14, 1 * 1024 * 1024, 16},
+ {0x15, 2 * 1024 * 1024, 32},
+ {0x16, 4 * 1024 * 1024, 64},
+ {0x17, 8 * 1024 * 1024, 128},
+ {0x18, 16 * 1024 * 1024, 64},
+ {0x00,}
+};
+
+/*
+ * smi_wait_xfer_finish - Wait until TFF is set in status register
+ * @timeout: timeout in milliseconds
+ *
+ * Wait until TFF is set in status register
+ */
+static inline void smi_wait_xfer_finish(int timeout)
+{
+ while (timeout--) {
+ if (readl(&smicntl->smi_sr) & TFF)
+ break;
+ udelay(1000);
+ }
+}
+
+/*
+ * smi_read_id - Read flash id
+ * @info: flash_info structure pointer
+ * @banknum: bank number
+ *
+ * Read the flash id present at bank #banknum
+ */
+static unsigned int smi_read_id(flash_info_t *info, int banknum)
+{
+ unsigned int value;
+
+ writel(readl(&smicntl->smi_cr1) | SW_MODE, &smicntl->smi_cr1);
+ writel(READ_ID, &smicntl->smi_tr);
+ writel((banknum << BANKSEL_SHIFT) | SEND | TX_LEN_1 | RX_LEN_3,
+ &smicntl->smi_cr2);
+ smi_wait_xfer_finish(XFER_FINISH_TOUT);
+
+ value = (readl(&smicntl->smi_rr) & 0x00FFFFFF);
+
+ writel(readl(&smicntl->smi_sr) & ~(TFF), &smicntl->smi_sr);
+ writel(readl(&smicntl->smi_cr1) & ~(SW_MODE), &smicntl->smi_cr1);
+
+ return value;
+}
+
+/*
+ * flash_get_size - Detect the SMI flash by reading the ID.
+ * @base: Base address of the flash area bank #banknum
+ * @banknum: Bank number
+ *
+ * Detect the SMI flash by reading the ID. Initializes the flash_info structure
+ * with size, sector count etc.
+ */
+static ulong flash_get_size(ulong base, int banknum)
+{
+ flash_info_t *info = &flash_info[banknum];
+ struct flash_dev *dev;
+ unsigned int value;
+ unsigned int density;
+ int i;
+
+ value = smi_read_id(info, banknum);
+ density = (value >> 16) & 0xff;
+
+ for (i = 0, dev = &flash_ids[0]; dev->density != 0x0;
+ i++, dev = &flash_ids[i]) {
+ if (dev->density == density) {
+ info->size = dev->size;
+ info->sector_count = dev->sector_count;
+ break;
+ }
+ }
+
+ if (0x0 == dev->density)
+ return 0;
+
+ info->flash_id = value & 0xffff;
+ info->start[0] = base;
+
+ return info->size;
+}
+
+/*
+ * smi_read_sr - Read status register of SMI
+ * @bank: bank number
+ *
+ * This routine will get the status register of the flash chip present at the
+ * given bank
+ */
+static int smi_read_sr(int bank)
+{
+ u32 ctrlreg1;
+
+ /* store the CTRL REG1 state */
+ ctrlreg1 = readl(&smicntl->smi_cr1);
+
+ /* Program SMI in HW Mode */
+ writel(readl(&smicntl->smi_cr1) & ~(SW_MODE | WB_MODE),
+ &smicntl->smi_cr1);
+
+ /* Performing a RSR instruction in HW mode */
+ writel((bank << BANKSEL_SHIFT) | RD_STATUS_REG, &smicntl->smi_cr2);
+
+ smi_wait_xfer_finish(XFER_FINISH_TOUT);
+
+ /* Restore the CTRL REG1 state */
+ writel(ctrlreg1, &smicntl->smi_cr1);
+
+ return readl(&smicntl->smi_sr);
+}
+
+/*
+ * smi_wait_till_ready - Wait till last operation is over.
+ * @bank: bank number shifted.
+ * @timeout: timeout in milliseconds.
+ *
+ * This routine checks for WIP(write in progress)bit in Status register(SMSR-b0)
+ * The routine checks for #timeout loops, each at interval of 1 milli-second.
+ * If successful the routine returns 0.
+ */
+static int smi_wait_till_ready(int bank, int timeout)
+{
+ int count;
+ int sr;
+
+ /* One chip guarantees max 5 msec wait here after page writes,
+ but potentially three seconds (!) after page erase. */
+ for (count = 0; count < timeout; count++) {
+
+ sr = smi_read_sr(bank);
+ if (sr < 0)
+ break;
+ else if (!(sr & WIP_BIT))
+ return 0;
+
+ /* Try again after 1m-sec */
+ udelay(1000);
+ }
+ printf("SMI controller is still in wait, timeout=%d\n", timeout);
+ return -EIO;
+}
+
+/*
+ * smi_write_enable - Enable the flash to do write operation
+ * @bank: bank number
+ *
+ * Set write enable latch with Write Enable command.
+ * Returns negative if error occurred.
+ */
+static inline int smi_write_enable(int bank)
+{
+ u32 ctrlreg1;
+ int timeout = WMODE_TOUT;
+
+ /* Store the CTRL REG1 state */
+ ctrlreg1 = readl(&smicntl->smi_cr1);
+
+ /* Program SMI in H/W Mode */
+ writel(readl(&smicntl->smi_cr1) & ~SW_MODE, &smicntl->smi_cr1);
+
+ /* Give the Flash, Write Enable command */
+ writel((bank << BANKSEL_SHIFT) | WE, &smicntl->smi_cr2);
+
+ smi_wait_xfer_finish(XFER_FINISH_TOUT);
+
+ /* Restore the CTRL REG1 state */
+ writel(ctrlreg1, &smicntl->smi_cr1);
+
+ while (timeout--) {
+ if (smi_read_sr(bank) & (1 << (bank + WM_SHIFT)))
+ break;
+ udelay(1000);
+ }
+
+ return 0;
+}
+
+/*
+ * smi_init - SMI initialization routine
+ *
+ * SMI initialization routine. Sets SMI control register1.
+ */
+static void smi_init(void)
+{
+ /* Setting the fast mode values. SMI working@166/4 = 41.5 MHz */
+ writel(HOLD1 | FAST_MODE | BANK_EN | DSEL_TIME | PRESCAL4,
+ &smicntl->smi_cr1);
+}
+
+/*
+ * smi_sector_erase - Erase flash sector
+ * @info: flash_info structure pointer
+ * @sector: sector number
+ *
+ * Set write enable latch with Write Enable command.
+ * Returns negative if error occurred.
+ */
+static int smi_sector_erase(flash_info_t *info, unsigned int sector)
+{
+ int bank;
+ unsigned int sect_add;
+ unsigned int instruction;
+
+ switch (info->start[0]) {
+ case SMIBANK0_BASE:
+ bank = BANK0;
+ break;
+ case SMIBANK1_BASE:
+ bank = BANK1;
+ break;
+ case SMIBANK2_BASE:
+ bank = BANK2;
+ break;
+ case SMIBANK3_BASE:
+ bank = BANK3;
+ break;
+ default:
+ return -1;
+ }
+
+ sect_add = sector * (info->size / info->sector_count);
+ instruction = ((sect_add >> 8) & 0x0000FF00) | SECTOR_ERASE;
+
+ writel(readl(&smicntl->smi_sr) & ~(ERF1 | ERF2), &smicntl->smi_sr);
+
+ if (info->flash_id == ST_M25Pxx_ID) {
+ /* Wait until finished previous write command. */
+ if (smi_wait_till_ready(bank, CONFIG_SYS_FLASH_ERASE_TOUT))
+ return -EBUSY;
+
+ /* Send write enable, before erase commands. */
+ if (smi_write_enable(bank))
+ return -EIO;
+
+ /* Put SMI in SW mode */
+ writel(readl(&smicntl->smi_cr1) | SW_MODE, &smicntl->smi_cr1);
+
+ /* Send Sector Erase command in SW Mode */
+ writel(instruction, &smicntl->smi_tr);
+ writel((bank << BANKSEL_SHIFT) | SEND | TX_LEN_4,
+ &smicntl->smi_cr2);
+ smi_wait_xfer_finish(XFER_FINISH_TOUT);
+
+ if (smi_wait_till_ready(bank, CONFIG_SYS_FLASH_ERASE_TOUT))
+ return -EBUSY;
+
+ /* Put SMI in HW mode */
+ writel(readl(&smicntl->smi_cr1) & ~(SW_MODE),
+ &smicntl->smi_cr1);
+
+ return 0;
+ } else {
+ /* Put SMI in HW mode */
+ writel(readl(&smicntl->smi_cr1) & ~(SW_MODE),
+ &smicntl->smi_cr1);
+ return -EINVAL;
+ }
+}
+
+/*
+ * smi_write - Write to SMI flash
+ * @src_addr: source buffer
+ * @dst_addr: destination buffer
+ * @length: length to write in words
+ * @bank: bank base address
+ *
+ * Write to SMI flash
+ */
+static int smi_write(unsigned int *src_addr, unsigned int *dst_addr,
+ unsigned int length, ulong bank_addr)
+{
+ int banknum;
+ unsigned int WM;
+
+ switch (bank_addr) {
+ case SMIBANK0_BASE:
+ banknum = BANK0;
+ WM = WM0;
+ break;
+ case SMIBANK1_BASE:
+ banknum = BANK1;
+ WM = WM1;
+ break;
+ case SMIBANK2_BASE:
+ banknum = BANK2;
+ WM = WM2;
+ break;
+ case SMIBANK3_BASE:
+ banknum = BANK3;
+ WM = WM3;
+ break;
+ default:
+ return -1;
+ }
+
+ if (smi_wait_till_ready(banknum, CONFIG_SYS_FLASH_WRITE_TOUT))
+ return -EBUSY;
+
+ /* Set SMI in Hardware Mode */
+ writel(readl(&smicntl->smi_cr1) & ~(SW_MODE), &smicntl->smi_cr1);
+
+ if (smi_write_enable(banknum))
+ return -EIO;
+
+ /* Perform the write command */
+ while (length--) {
+ if (((ulong) (dst_addr) % SFLASH_PAGE_SIZE) == 0) {
+ if (smi_wait_till_ready(banknum,
+ CONFIG_SYS_FLASH_WRITE_TOUT))
+ return -EBUSY;
+
+ if (smi_write_enable(banknum))
+ return -EIO;
+ }
+
+ *dst_addr++ = *src_addr++;
+
+ if ((readl(&smicntl->smi_sr) & (ERF1 | ERF2)))
+ return -EIO;
+ }
+
+ if (smi_wait_till_ready(banknum, CONFIG_SYS_FLASH_WRITE_TOUT))
+ return -EBUSY;
+
+ writel(readl(&smicntl->smi_sr) & ~(WCF), &smicntl->smi_sr);
+
+ return 0;
+}
+
+/*
+ * write_buff - Write to SMI flash
+ * @info: flash info structure
+ * @src: source buffer
+ * @dest_addr: destination buffer
+ * @length: length to write in words
+ *
+ * Write to SMI flash
+ */
+int write_buff(flash_info_t *info, uchar *src, ulong dest_addr, ulong length)
+{
+ smi_write((unsigned int *)src, (unsigned int *)dest_addr,
+ (length + 3) / 4, info->start[0]);
+ return 0;
+}
+
+/*
+ * flash_init - SMI flash initialization
+ *
+ * SMI flash initialization
+ */
+unsigned long flash_init(void)
+{
+ unsigned long size = 0;
+ int i, j;
+
+ smi_init();
+
+ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
+ flash_info[i].flash_id = FLASH_UNKNOWN;
+ size += flash_info[i].size = flash_get_size(bank_base[i], i);
+ }
+
+ for (j = 0; j < CONFIG_SYS_MAX_FLASH_BANKS; j++) {
+ for (i = 1; i < flash_info[j].sector_count; i++)
+ flash_info[j].start[i] =
+ flash_info[j].start[i - 1] +
+ flash_info->size / flash_info->sector_count;
+
+ }
+
+ return size;
+}
+
+/*
+ * flash_print_info - Print SMI flash information
+ *
+ * Print SMI flash information
+ */
+void flash_print_info(flash_info_t *info)
+{
+ int i;
+ if (info->flash_id == FLASH_UNKNOWN) {
+ puts("missing or unknown FLASH type\n");
+ return;
+ }
+ printf(" Size: %ld MB in %d Sectors\n",
+ info->size >> 20, info->sector_count);
+
+ puts(" Sector Start Addresses:");
+ for (i = 0; i < info->sector_count; ++i) {
+#ifdef CONFIG_SYS_FLASH_EMPTY_INFO
+ int size;
+ int erased;
+ u32 *flash;
+
+ /*
+ * Check if whole sector is erased
+ */
+ size = (info->size) / (info->sector_count);
+ flash = (u32 *) info->start[i];
+ size = size / sizeof(int);
+
+ while ((size--) && (*flash++ == ~0))
+ ;
+
+ size++;
+ if (size)
+ erased = 0;
+ else
+ erased = 1;
+
+ if ((i % 5) == 0)
+ printf("\n");
+
+ printf(" %08lX%s%s",
+ info->start[i],
+ erased ? " E" : " ", info->protect[i] ? "RO " : " ");
+#else
+ if ((i % 5) == 0)
+ printf("\n ");
+ printf(" %08lX%s",
+ info->start[i], info->protect[i] ? " (RO) " : " ");
+#endif
+ }
+ putc('\n');
+ return;
+}
+
+/*
+ * flash_erase - Erase SMI flash
+ *
+ * Erase SMI flash
+ */
+int flash_erase(flash_info_t *info, int s_first, int s_last)
+{
+ int rcode = 0;
+ int prot = 0;
+ flash_sect_t sect;
+
+ if (info->flash_id == FLASH_UNKNOWN) {
+ puts("Can't erase unknown flash type - aborted\n");
+ return 1;
+ }
+
+ if ((s_first < 0) || (s_first > s_last)) {
+ puts("- no sectors to erase\n");
+ return 1;
+ }
+
+ for (sect = s_first; sect <= s_last; ++sect) {
+ if (info->protect[sect])
+ prot++;
+ }
+ if (prot) {
+ printf("- Warning: %d protected sectors will not be erased!\n",
+ prot);
+ } else {
+ putc('\n');
+ }
+
+ for (sect = s_first; sect <= s_last; sect++) {
+ if (info->protect[sect] == 0) {
+ switch (info->flash_id) {
+ case ST_M25Pxx_ID:
+ if (smi_sector_erase(info, sect))
+ rcode = 1;
+ else
+ putc('.');
+
+ break;
+
+ default:
+ printf("Unkown flash vendor 0x%x\n",
+ (u32) info->flash_id);
+ break;
+ }
+ }
+ }
+ puts(" done\n");
+ return rcode;
+}
+#endif
diff --git a/include/asm-arm/arch-spear/spr_smi.h b/include/asm-arm/arch-spear/spr_smi.h
new file mode 100755
index 0000000..a42a874
--- /dev/null
+++ b/include/asm-arm/arch-spear/spr_smi.h
@@ -0,0 +1,117 @@
+/*
+ * (C) Copyright 2009
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar at st.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
+ */
+
+#ifndef SPR_SMI_H
+#define SPR_SMI_H
+
+/* 0xF800.0000 . 0xFBFF.FFFF 64MB SMI (Serial Flash Mem) */
+/* 0xFC00.0000 . 0xFC1F.FFFF 2MB SMI (Serial Flash Reg.) */
+
+#define SMI_BASE CONFIG_SYS_SMI_BASE
+
+#define FLASH_START_ADDRESS CONFIG_SYS_FLASH_BASE
+#define FLASH_BANK_SIZE CONFIG_SYS_FLASH_BANK_SIZE
+
+#define SMIBANK0_BASE (FLASH_START_ADDRESS)
+#define SMIBANK1_BASE (SMIBANK0_BASE + FLASH_BANK_SIZE)
+#define SMIBANK2_BASE (SMIBANK1_BASE + FLASH_BANK_SIZE)
+#define SMIBANK3_BASE (SMIBANK2_BASE + FLASH_BANK_SIZE)
+
+#define BANK0 0
+#define BANK1 1
+#define BANK2 2
+#define BANK3 3
+
+struct smi_regs {
+ u32 smi_cr1;
+ u32 smi_cr2;
+ u32 smi_sr;
+ u32 smi_tr;
+ u32 smi_rr;
+};
+
+/* CONTROL REG 1 */
+#define BANK_EN 0x0000000F /* enables all banks */
+#define DSEL_TIME 0x00000060 /* Deselect time 6+1 SMI_CK periods */
+#define PRESCAL5 0x00000500 /* AHB_CK prescaling value */
+#define PRESCALA 0x00000A00 /* AHB_CK prescaling value */
+#define PRESCAL3 0x00000300 /* AHB_CK prescaling value */
+#define PRESCAL4 0x00000400 /* AHB_CK prescaling value */
+#define SW_MODE 0x10000000 /* enables SW Mode */
+#define WB_MODE 0x20000000 /* Write Burst Mode */
+#define FAST_MODE 0x00008000 /* Fast Mode */
+#define HOLD1 0x00010000
+
+/* CONTROL REG 2 */
+#define RD_STATUS_REG 0x00000400 /* reads status reg */
+#define WE 0x00000800 /* Write Enable */
+#define BANK0_SEL 0x00000000 /* Select Banck0 */
+#define BANK1_SEL 0x00001000 /* Select Banck1 */
+#define BANK2_SEL 0x00002000 /* Select Banck2 */
+#define BANK3_SEL 0x00003000 /* Select Banck3 */
+#define BANKSEL_SHIFT 12
+#define SEND 0x00000080 /* Send data */
+#define TX_LEN_1 0x00000001 /* data length = 1 byte */
+#define TX_LEN_2 0x00000002 /* data length = 2 byte */
+#define TX_LEN_3 0x00000003 /* data length = 3 byte */
+#define TX_LEN_4 0x00000004 /* data length = 4 byte */
+#define RX_LEN_1 0x00000010 /* data length = 1 byte */
+#define RX_LEN_2 0x00000020 /* data length = 2 byte */
+#define RX_LEN_3 0x00000030 /* data length = 3 byte */
+#define RX_LEN_4 0x00000040 /* data length = 4 byte */
+#define TFIE 0x00000100 /* Transmission Flag Interrupt Enable */
+#define WCIE 0x00000200 /* Write Complete Interrupt Enable */
+
+/* STATUS_REG */
+#define INT_WCF_CLR 0xFFFFFDFF /* clear: WCF clear */
+#define INT_TFF_CLR 0xFFFFFEFF /* clear: TFF clear */
+#define WIP_BIT 0x00000001 /* WIP Bit of SPI SR on SMI SR */
+#define WEL_BIT 0x00000002 /* WEL Bit of SPI SR on SMI SR */
+#define RSR 0x00000005 /* Read Status regiser */
+#define TFF 0x00000100 /* Transfer Finished FLag */
+#define WCF 0x00000200 /* Transfer Finished FLag */
+#define ERF1 0x00000400 /* Error Flag 1 */
+#define ERF2 0x00000800 /* Error Flag 2 */
+#define WM0 0x00001000 /* WM Bank 0 */
+#define WM1 0x00002000 /* WM Bank 1 */
+#define WM2 0x00004000 /* WM Bank 2 */
+#define WM3 0x00008000 /* WM Bank 3 */
+#define WM_SHIFT 12
+
+/* TR REG */
+#define READ_ID 0x0000009F /* Read Identification */
+#define BULK_ERASE 0x000000C7 /* BULK erase */
+#define SECTOR_ERASE 0x000000D8 /* SECTOR erase */
+#define WRITE_ENABLE 0x00000006 /* Wenable command to FLASH */
+
+struct flash_dev {
+ u32 density;
+ ulong size;
+ ushort sector_count;
+};
+
+#define SFLASH_PAGE_SIZE 0x100
+#define XFER_FINISH_TOUT 2
+#define WMODE_TOUT 2
+
+#endif
--
1.6.0.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2010-01-14 15:22 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-01-13 13:08 [U-Boot] [PATCH v4 04/12] SPEAr : smi driver support for SPEAr SoCs Tom
2010-01-14 10:50 ` Vipin Kumar
2010-01-14 15:22 ` Tom
-- strict thread matches above, loose matches on Subject: below --
2010-01-11 11:15 [U-Boot] [PATCH v4 00/12] Support " Vipin KUMAR
2010-01-11 11:15 ` [U-Boot] [PATCH v4 01/12] SPEAr : Adding README.spear in doc Vipin KUMAR
2010-01-11 11:15 ` [U-Boot] [PATCH v4 02/12] SPEAr : Adding basic SPEAr architecture support Vipin KUMAR
2010-01-11 11:15 ` [U-Boot] [PATCH v4 03/12] SPEAr : i2c driver support added for SPEAr SoCs Vipin KUMAR
2010-01-11 11:15 ` [U-Boot] [PATCH v4 04/12] SPEAr : smi driver support " Vipin KUMAR
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox