]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* credit winbond-840.c |
2 | */ | |
3 | #include <asm/io.h> | |
4 | struct eeprom_ops { | |
5 | void (*set_cs)(void *ee); | |
6 | void (*clear_cs)(void *ee); | |
7 | }; | |
8 | ||
9 | #define EEPOL_EEDI 0x01 | |
10 | #define EEPOL_EEDO 0x02 | |
11 | #define EEPOL_EECLK 0x04 | |
12 | #define EEPOL_EESEL 0x08 | |
13 | ||
14 | struct eeprom { | |
15 | void *dev; | |
16 | struct eeprom_ops *ops; | |
17 | ||
18 | void __iomem * addr; | |
19 | ||
20 | unsigned ee_addr_bits; | |
21 | ||
22 | unsigned eesel; | |
23 | unsigned eeclk; | |
24 | unsigned eedo; | |
25 | unsigned eedi; | |
26 | unsigned polarity; | |
27 | unsigned ee_state; | |
28 | ||
29 | spinlock_t *lock; | |
30 | u32 *cache; | |
31 | }; | |
32 | ||
33 | ||
34 | u8 eeprom_readb(struct eeprom *ee, unsigned address); | |
35 | void eeprom_read(struct eeprom *ee, unsigned address, u8 *bytes, | |
36 | unsigned count); | |
37 | void eeprom_writeb(struct eeprom *ee, unsigned address, u8 data); | |
38 | void eeprom_write(struct eeprom *ee, unsigned address, u8 *bytes, | |
39 | unsigned count); | |
40 | ||
41 | /* The EEPROM commands include the alway-set leading bit. */ | |
42 | enum EEPROM_Cmds { | |
43 | EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6), | |
44 | }; | |
45 | ||
46 | void setup_ee_mem_bitbanger(struct eeprom *ee, void __iomem *memaddr, int eesel_bit, int eeclk_bit, int eedo_bit, int eedi_bit, unsigned polarity) | |
47 | { | |
48 | ee->addr = memaddr; | |
49 | ee->eesel = 1 << eesel_bit; | |
50 | ee->eeclk = 1 << eeclk_bit; | |
51 | ee->eedo = 1 << eedo_bit; | |
52 | ee->eedi = 1 << eedi_bit; | |
53 | ||
54 | ee->polarity = polarity; | |
55 | ||
56 | *ee->cache = readl(ee->addr); | |
57 | } | |
58 | ||
59 | /* foo. put this in a .c file */ | |
60 | static inline void eeprom_update(struct eeprom *ee, u32 mask, int pol) | |
61 | { | |
62 | unsigned long flags; | |
63 | u32 data; | |
64 | ||
65 | spin_lock_irqsave(ee->lock, flags); | |
66 | data = *ee->cache; | |
67 | ||
68 | data &= ~mask; | |
69 | if (pol) | |
70 | data |= mask; | |
71 | ||
72 | *ee->cache = data; | |
73 | //printk("update: %08x\n", data); | |
74 | writel(data, ee->addr); | |
75 | spin_unlock_irqrestore(ee->lock, flags); | |
76 | } | |
77 | ||
78 | void eeprom_clk_lo(struct eeprom *ee) | |
79 | { | |
80 | int pol = !!(ee->polarity & EEPOL_EECLK); | |
81 | ||
82 | eeprom_update(ee, ee->eeclk, pol); | |
83 | udelay(2); | |
84 | } | |
85 | ||
86 | void eeprom_clk_hi(struct eeprom *ee) | |
87 | { | |
88 | int pol = !!(ee->polarity & EEPOL_EECLK); | |
89 | ||
90 | eeprom_update(ee, ee->eeclk, !pol); | |
91 | udelay(2); | |
92 | } | |
93 | ||
94 | void eeprom_send_addr(struct eeprom *ee, unsigned address) | |
95 | { | |
96 | int pol = !!(ee->polarity & EEPOL_EEDI); | |
97 | unsigned i; | |
98 | address |= 6 << 6; | |
99 | ||
100 | /* Shift the read command bits out. */ | |
101 | for (i=0; i<11; i++) { | |
102 | eeprom_update(ee, ee->eedi, ((address >> 10) & 1) ^ pol); | |
103 | address <<= 1; | |
104 | eeprom_clk_hi(ee); | |
105 | eeprom_clk_lo(ee); | |
106 | } | |
107 | eeprom_update(ee, ee->eedi, pol); | |
108 | } | |
109 | ||
110 | u16 eeprom_readw(struct eeprom *ee, unsigned address) | |
111 | { | |
112 | unsigned i; | |
113 | u16 res = 0; | |
114 | ||
115 | eeprom_clk_lo(ee); | |
116 | eeprom_update(ee, ee->eesel, 1 ^ !!(ee->polarity & EEPOL_EESEL)); | |
117 | eeprom_send_addr(ee, address); | |
118 | ||
119 | for (i=0; i<16; i++) { | |
120 | u32 data; | |
121 | eeprom_clk_hi(ee); | |
122 | res <<= 1; | |
123 | data = readl(ee->addr); | |
124 | //printk("eeprom_readw: %08x\n", data); | |
125 | res |= !!(data & ee->eedo) ^ !!(ee->polarity & EEPOL_EEDO); | |
126 | eeprom_clk_lo(ee); | |
127 | } | |
128 | eeprom_update(ee, ee->eesel, 0 ^ !!(ee->polarity & EEPOL_EESEL)); | |
129 | ||
130 | return res; | |
131 | } | |
132 | ||
133 | ||
134 | void eeprom_writeb(struct eeprom *ee, unsigned address, u8 data) | |
135 | { | |
136 | } |