Commit 3ac374c0f0b7d856f1a43317a286f2079106bd6a

Authored by Albin Tonnerre
Committed by Wolfgang Denk
1 parent 30951960ba

Add driver for the ST M95xxx SPI EEPROM

This chip is used in a number of boards manufactured by Calao-Systems
which should be supported soon. This driver provides the necessary
spi_read and spi_write functions necessary to communicate with the chip.

Signed-off-by: Albin Tonnerre <albin.tonnerre@free-electrons.com>

Showing 2 changed files with 118 additions and 0 deletions Side-by-side Diff

drivers/mtd/spi/Makefile
... ... @@ -31,6 +31,7 @@
31 31 COBJS-$(CONFIG_SPI_FLASH_SPANSION) += spansion.o
32 32 COBJS-$(CONFIG_SPI_FLASH_SST) += sst.o
33 33 COBJS-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.o
  34 +COBJS-$(CONFIG_SPI_M95XXX) += eeprom_m95xxx.o
34 35  
35 36 COBJS := $(COBJS-y)
36 37 SRCS := $(COBJS:.o=.c)
drivers/mtd/spi/eeprom_m95xxx.c
  1 +/*
  2 + * Copyright (C) 2009
  3 + * Albin Tonnerre, Free Electrons <albin.tonnerre@free-electrons.com>
  4 + *
  5 + * See file CREDITS for list of people who contributed to this
  6 + * project.
  7 + *
  8 + * This program is free software; you can redistribute it and/or
  9 + * modify it under the terms of the GNU General Public License as
  10 + * published by the Free Software Foundation; either version 2 of
  11 + * the License, or (at your option) any later version.
  12 + *
  13 + * This program is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16 + * GNU General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU General Public License
  19 + * along with this program; if not, write to the Free Software
  20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 + * MA 02111-1307 USA
  22 + */
  23 +
  24 +#include <common.h>
  25 +#include <spi.h>
  26 +
  27 +#define SPI_EEPROM_WREN 0x06
  28 +#define SPI_EEPROM_RDSR 0x05
  29 +#define SPI_EEPROM_READ 0x03
  30 +#define SPI_EEPROM_WRITE 0x02
  31 +
  32 +#ifndef CONFIG_DEFAULT_SPI_BUS
  33 +#define CONFIG_DEFAULT_SPI_BUS 0
  34 +#endif
  35 +
  36 +#ifndef CONFIG_DEFAULT_SPI_MODE
  37 +#define CONFIG_DEFAULT_SPI_MODE SPI_MODE_0
  38 +#endif
  39 +
  40 +ssize_t spi_read (uchar *addr, int alen, uchar *buffer, int len)
  41 +{
  42 + struct spi_slave *slave;
  43 + u8 cmd = SPI_EEPROM_READ;
  44 +
  45 + slave = spi_setup_slave(CONFIG_DEFAULT_SPI_BUS, 1, 1000000,
  46 + CONFIG_DEFAULT_SPI_MODE);
  47 + spi_claim_bus(slave);
  48 +
  49 + /* command */
  50 + if(spi_xfer(slave, 8, &cmd, NULL, SPI_XFER_BEGIN))
  51 + return -1;
  52 +
  53 + /*
  54 + * if alen == 3, addr[0] is the block number, we never use it here. All we
  55 + * need are the lower 16 bits
  56 + */
  57 + if (alen == 3)
  58 + addr++;
  59 +
  60 + /* address, and data */
  61 + if(spi_xfer(slave, 16, addr, NULL, 0))
  62 + return -1;
  63 + if(spi_xfer(slave, 8 * len, NULL, buffer, SPI_XFER_END))
  64 + return -1;
  65 +
  66 + spi_release_bus(slave);
  67 + spi_free_slave(slave);
  68 + return len;
  69 +}
  70 +
  71 +ssize_t spi_write (uchar *addr, int alen, uchar *buffer, int len)
  72 +{
  73 + struct spi_slave *slave;
  74 + int i;
  75 + char buf[3];
  76 +
  77 + slave = spi_setup_slave(CONFIG_DEFAULT_SPI_BUS, 1, 1000000,
  78 + CONFIG_DEFAULT_SPI_MODE);
  79 + spi_claim_bus(slave);
  80 +
  81 + buf[0] = SPI_EEPROM_WREN;
  82 + if(spi_xfer(slave, 8, buf, NULL, SPI_XFER_BEGIN | SPI_XFER_END))
  83 + return -1;
  84 +
  85 + buf[0] = SPI_EEPROM_WRITE;
  86 +
  87 + /* As for reading, drop addr[0] if alen is 3 */
  88 + if (alen == 3) {
  89 + alen--;
  90 + addr++;
  91 + }
  92 +
  93 + memcpy(buf + 1, addr, alen);
  94 + /* command + addr, then data */
  95 + if(spi_xfer(slave, 24, buf, NULL, SPI_XFER_BEGIN))
  96 + return -1;
  97 + if(spi_xfer(slave, len * 8, buffer, NULL, SPI_XFER_END))
  98 + return -1;
  99 +
  100 + reset_timer_masked();
  101 + do {
  102 + buf[0] = SPI_EEPROM_RDSR;
  103 + buf[1] = 0;
  104 + spi_xfer(slave, 16, buf, buf, SPI_XFER_BEGIN | SPI_XFER_END);
  105 +
  106 + if (!(buf[1] & 1))
  107 + break;
  108 +
  109 + } while (get_timer_masked() < CONFIG_SYS_SPI_WRITE_TOUT);
  110 +
  111 + if (buf[1] & 1)
  112 + printf ("*** spi_write: Time out while writing!\n");
  113 +
  114 + spi_release_bus(slave);
  115 + spi_free_slave(slave);
  116 + return len;
  117 +}