Merge branch 'next' of git://git.denx.de/u-boot-mpc83xx
[platform/kernel/u-boot.git] / drivers / mtd / spi / eeprom_m95xxx.c
1 /*
2  * Copyright (C) 2009
3  * Albin Tonnerre, Free Electrons <albin.tonnerre@free-electrons.com>
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
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
24 #ifndef CONFIG_SYS_SPI_WRITE_TOUT
25 #define CONFIG_SYS_SPI_WRITE_TOUT (5 * CONFIG_SYS_HZ)
26 #endif
27
28 ssize_t spi_read(uchar *addr, int alen, uchar *buffer, int len)
29 {
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);
35         if (!slave)
36                 return 0;
37
38         spi_claim_bus(slave);
39
40         /* command */
41         if (spi_xfer(slave, 8, &cmd, NULL, SPI_XFER_BEGIN))
42                 return -1;
43
44         /*
45          * if alen == 3, addr[0] is the block number, we never use it here.
46          * All we need are the lower 16 bits.
47          */
48         if (alen == 3)
49                 addr++;
50
51         /* address, and data */
52         if (spi_xfer(slave, 16, addr, NULL, 0))
53                 return -1;
54         if (spi_xfer(slave, 8 * len, NULL, buffer, SPI_XFER_END))
55                 return -1;
56
57         spi_release_bus(slave);
58         spi_free_slave(slave);
59         return len;
60 }
61
62 ssize_t spi_write(uchar *addr, int alen, uchar *buffer, int len)
63 {
64         struct spi_slave *slave;
65         char buf[3];
66         ulong start;
67
68         slave = spi_setup_slave(CONFIG_DEFAULT_SPI_BUS, 1, 1000000,
69                         CONFIG_DEFAULT_SPI_MODE);
70         if (!slave)
71                 return 0;
72
73         spi_claim_bus(slave);
74
75         buf[0] = SPI_EEPROM_WREN;
76         if (spi_xfer(slave, 8, buf, NULL, SPI_XFER_BEGIN | SPI_XFER_END))
77                 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 */
89         if (spi_xfer(slave, 24, buf, NULL, SPI_XFER_BEGIN))
90                 return -1;
91         if (spi_xfer(slave, len * 8, buffer, NULL, SPI_XFER_END))
92                 return -1;
93
94         start = get_timer(0);
95         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
103         } while (get_timer(start) < CONFIG_SYS_SPI_WRITE_TOUT);
104
105         if (buf[1] & 1)
106                 printf("*** spi_write: Timeout while writing!\n");
107
108         spi_release_bus(slave);
109         spi_free_slave(slave);
110         return len;
111 }