blob: a019939b8b926f8d0181160ffb6741bd27c167e4 [file] [log] [blame]
Albin Tonnerre626e02a2009-08-07 12:37:36 +02001/*
2 * Copyright (C) 2009
3 * Albin Tonnerre, Free Electrons <albin.tonnerre@free-electrons.com>
4 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
Albin Tonnerre626e02a2009-08-07 12:37:36 +02006 */
7
8#include <common.h>
9#include <spi.h>
10
11#define SPI_EEPROM_WREN 0x06
12#define SPI_EEPROM_RDSR 0x05
13#define SPI_EEPROM_READ 0x03
14#define SPI_EEPROM_WRITE 0x02
15
16#ifndef CONFIG_DEFAULT_SPI_BUS
17#define CONFIG_DEFAULT_SPI_BUS 0
18#endif
19
20#ifndef CONFIG_DEFAULT_SPI_MODE
21#define CONFIG_DEFAULT_SPI_MODE SPI_MODE_0
22#endif
23
Mike Frysinger19f0c242012-01-19 22:31:01 -050024#ifndef CONFIG_SYS_SPI_WRITE_TOUT
25#define CONFIG_SYS_SPI_WRITE_TOUT (5 * CONFIG_SYS_HZ)
26#endif
27
Mike Frysingerd0e3ad62012-01-19 22:25:55 -050028ssize_t spi_read(uchar *addr, int alen, uchar *buffer, int len)
Albin Tonnerre626e02a2009-08-07 12:37:36 +020029{
30 struct spi_slave *slave;
31 u8 cmd = SPI_EEPROM_READ;
32
33 slave = spi_setup_slave(CONFIG_DEFAULT_SPI_BUS, 1, 1000000,
34 CONFIG_DEFAULT_SPI_MODE);
Mike Frysingerd0e3ad62012-01-19 22:25:55 -050035 if (!slave)
Albin Tonnerre81671082010-03-14 18:47:23 +010036 return 0;
37
Albin Tonnerre626e02a2009-08-07 12:37:36 +020038 spi_claim_bus(slave);
39
40 /* command */
Mike Frysingerd0e3ad62012-01-19 22:25:55 -050041 if (spi_xfer(slave, 8, &cmd, NULL, SPI_XFER_BEGIN))
Albin Tonnerre626e02a2009-08-07 12:37:36 +020042 return -1;
43
44 /*
Mike Frysingerd0e3ad62012-01-19 22:25:55 -050045 * if alen == 3, addr[0] is the block number, we never use it here.
46 * All we need are the lower 16 bits.
Albin Tonnerre626e02a2009-08-07 12:37:36 +020047 */
48 if (alen == 3)
49 addr++;
50
51 /* address, and data */
Mike Frysingerd0e3ad62012-01-19 22:25:55 -050052 if (spi_xfer(slave, 16, addr, NULL, 0))
Albin Tonnerre626e02a2009-08-07 12:37:36 +020053 return -1;
Mike Frysingerd0e3ad62012-01-19 22:25:55 -050054 if (spi_xfer(slave, 8 * len, NULL, buffer, SPI_XFER_END))
Albin Tonnerre626e02a2009-08-07 12:37:36 +020055 return -1;
56
57 spi_release_bus(slave);
58 spi_free_slave(slave);
59 return len;
60}
61
Mike Frysingerd0e3ad62012-01-19 22:25:55 -050062ssize_t spi_write(uchar *addr, int alen, uchar *buffer, int len)
Albin Tonnerre626e02a2009-08-07 12:37:36 +020063{
64 struct spi_slave *slave;
Albin Tonnerre626e02a2009-08-07 12:37:36 +020065 char buf[3];
Graeme Russf8b82ee2011-07-15 23:31:37 +000066 ulong start;
Albin Tonnerre626e02a2009-08-07 12:37:36 +020067
68 slave = spi_setup_slave(CONFIG_DEFAULT_SPI_BUS, 1, 1000000,
69 CONFIG_DEFAULT_SPI_MODE);
Albin Tonnerre81671082010-03-14 18:47:23 +010070 if (!slave)
71 return 0;
72
Albin Tonnerre626e02a2009-08-07 12:37:36 +020073 spi_claim_bus(slave);
74
75 buf[0] = SPI_EEPROM_WREN;
Mike Frysingerd0e3ad62012-01-19 22:25:55 -050076 if (spi_xfer(slave, 8, buf, NULL, SPI_XFER_BEGIN | SPI_XFER_END))
Albin Tonnerre626e02a2009-08-07 12:37:36 +020077 return -1;
78
79 buf[0] = SPI_EEPROM_WRITE;
80
81 /* As for reading, drop addr[0] if alen is 3 */
82 if (alen == 3) {
83 alen--;
84 addr++;
85 }
86
87 memcpy(buf + 1, addr, alen);
88 /* command + addr, then data */
Mike Frysingerd0e3ad62012-01-19 22:25:55 -050089 if (spi_xfer(slave, 24, buf, NULL, SPI_XFER_BEGIN))
Albin Tonnerre626e02a2009-08-07 12:37:36 +020090 return -1;
Mike Frysingerd0e3ad62012-01-19 22:25:55 -050091 if (spi_xfer(slave, len * 8, buffer, NULL, SPI_XFER_END))
Albin Tonnerre626e02a2009-08-07 12:37:36 +020092 return -1;
93
Graeme Russf8b82ee2011-07-15 23:31:37 +000094 start = get_timer(0);
Albin Tonnerre626e02a2009-08-07 12:37:36 +020095 do {
96 buf[0] = SPI_EEPROM_RDSR;
97 buf[1] = 0;
98 spi_xfer(slave, 16, buf, buf, SPI_XFER_BEGIN | SPI_XFER_END);
99
100 if (!(buf[1] & 1))
101 break;
102
Graeme Russf8b82ee2011-07-15 23:31:37 +0000103 } while (get_timer(start) < CONFIG_SYS_SPI_WRITE_TOUT);
Albin Tonnerre626e02a2009-08-07 12:37:36 +0200104
105 if (buf[1] & 1)
Mike Frysingerd0e3ad62012-01-19 22:25:55 -0500106 printf("*** spi_write: Timeout while writing!\n");
Albin Tonnerre626e02a2009-08-07 12:37:36 +0200107
108 spi_release_bus(slave);
109 spi_free_slave(slave);
110 return len;
111}