MINI2440: General update
[qemu/mini2440.git] / hw / eeprom24c0x.c
blob90779b1f8ac6ae12428dbf23cdcd9235e3f6d47f
1 /*
2 * QEMU EEPROM 24c0x emulation
4 * Copyright (c) 2009 Michel Pollet <buserror@gmail.com>
5 * Copyright (c) 2006 Aurelien Jarno
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <assert.h>
23 #include "hw.h"
24 #include "eeprom24c0x.h"
27 * EEPROM 24C01 / 24C02 emulation.
29 * Emulation for serial EEPROMs:
30 * 24C01 - 1024 bit (128 x 8)
31 * 24C02 - 2048 bit (256 x 8)
32 * 24C04 - 4096 bit (512 x 8)
33 * 24C08 - 8192 bit (1024 x 8)
35 * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
38 #define DEBUG
40 #if defined(DEBUG)
41 # define logout(fmt, args...) fprintf(stderr, "24C\t%-24s" fmt, __func__, ##args)
42 #else
43 # define logout(fmt, args...) ((void)0)
44 #endif
46 struct _eeprom24c0x_t {
47 uint8_t kind;
48 uint8_t tick;
49 uint8_t address;
50 uint8_t command;
51 uint8_t ack;
52 uint8_t scl;
53 uint8_t sda;
54 uint8_t data;
55 //~ uint16_t size;
56 uint8_t contents[1024];
59 //typedef struct _eeprom24c0x_t eeprom24c0x_t;
62 eeprom24c0x_t * eeprom24c0x_new(int eeprom_kind)
64 eeprom24c0x_t *eeprom = (eeprom24c0x_t *)qemu_mallocz(sizeof(eeprom24c0x_t));
66 eeprom->kind = eeprom_kind;
67 memset(eeprom->contents, 0xff, sizeof(eeprom->contents));
68 return eeprom;
71 void eeprom24c0x_free(eeprom24c0x_t *eeprom)
73 logout("eeprom = 0x%p\n", eeprom);
74 qemu_free(eeprom);
77 uint8_t *eeprom24c0x_data(eeprom24c0x_t *eeprom)
79 return eeprom->contents;
82 uint8_t eeprom24c0x_read(eeprom24c0x_t * eeprom)
84 logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
85 eeprom->tick, eeprom->scl, eeprom->sda, eeprom->data);
86 return eeprom->sda;
89 void eeprom24c0x_write(eeprom24c0x_t * eeprom, int scl, int sda)
91 if (eeprom->scl && scl && (eeprom->sda != sda)) {
92 logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
93 eeprom->tick, eeprom->scl, scl, eeprom->sda, sda, sda ? "stop" : "start");
94 if (!sda) {
95 eeprom->tick = 1;
96 eeprom->command = 0;
98 } else if (eeprom->tick == 0 && !eeprom->ack) {
99 /* Waiting for start. */
100 logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
101 eeprom->tick, eeprom->scl, scl, eeprom->sda, sda);
102 } else if (!eeprom->scl && scl) {
103 logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
104 eeprom->tick, eeprom->scl, scl, eeprom->sda, sda);
105 if (eeprom->ack) {
106 logout("\ti2c ack bit = 0\n");
107 sda = 0;
108 eeprom->ack = 0;
109 } else if (eeprom->sda == sda) {
110 uint8_t bit = (sda != 0);
111 logout("\ti2c bit = %d\n", bit);
112 if (eeprom->tick < 9) {
113 eeprom->command <<= 1;
114 eeprom->command += bit;
115 eeprom->tick++;
116 if (eeprom->tick == 9) {
117 logout("\tcommand 0x%04x, %s\n", eeprom->command, bit ? "read" : "write");
118 eeprom->ack = 1;
120 } else if (eeprom->tick < 17) {
121 if (eeprom->command & 1) {
122 sda = ((eeprom->data & 0x80) != 0);
124 eeprom->address <<= 1;
125 eeprom->address += bit;
126 eeprom->tick++;
127 eeprom->data <<= 1;
128 if (eeprom->tick == 17) {
129 eeprom->data = eeprom->contents[eeprom->address];
130 logout("\taddress 0x%04x, data 0x%02x\n", eeprom->address, eeprom->data);
131 eeprom->ack = 1;
132 eeprom->tick = 0;
134 } else if (eeprom->tick >= 17) {
135 sda = 0;
137 } else {
138 logout("\tsda changed with raising scl\n");
140 } else {
141 logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom->tick, eeprom->scl, scl, eeprom->sda, sda);
143 eeprom->scl = scl;
144 eeprom->sda = sda;