Training courses
Kernel and Embedded Linux
Bootlin training courses
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
/* * Atmel AT93C46 serial eeprom driver * * Brian Murphy <brian.murphy@eicon.com> * */ #include <linux/kernel.h> #include <linux/delay.h> #include <asm/lasat/lasat.h> #include <linux/module.h> #include "at93c.h" #define AT93C_ADDR_SHIFT 7 #define AT93C_ADDR_MAX ((1 << AT93C_ADDR_SHIFT) - 1) #define AT93C_RCMD (0x6 << AT93C_ADDR_SHIFT) #define AT93C_WCMD (0x5 << AT93C_ADDR_SHIFT) #define AT93C_WENCMD 0x260 #define AT93C_WDSCMD 0x200 struct at93c_defs *at93c; static void at93c_reg_write(u32 val) { *at93c->reg = val; } static u32 at93c_reg_read(void) { u32 tmp = *at93c->reg; return tmp; } static u32 at93c_datareg_read(void) { u32 tmp = *at93c->rdata_reg; return tmp; } static void at93c_cycle_clk(u32 data) { at93c_reg_write(data | at93c->clk); lasat_ndelay(250); at93c_reg_write(data & ~at93c->clk); lasat_ndelay(250); } static void at93c_write_databit(u8 bit) { u32 data = at93c_reg_read(); if (bit) data |= 1 << at93c->wdata_shift; else data &= ~(1 << at93c->wdata_shift); at93c_reg_write(data); lasat_ndelay(100); at93c_cycle_clk(data); } static unsigned int at93c_read_databit(void) { u32 data; at93c_cycle_clk(at93c_reg_read()); data = (at93c_datareg_read() >> at93c->rdata_shift) & 1; return data; } static u8 at93c_read_byte(void) { int i; u8 data = 0; for (i = 0; i <= 7; i++) { data <<= 1; data |= at93c_read_databit(); } return data; } static void at93c_write_bits(u32 data, int size) { int i; int shift = size - 1; u32 mask = (1 << shift); for (i = 0; i < size; i++) { at93c_write_databit((data & mask) >> shift); data <<= 1; } } static void at93c_init_op(void) { at93c_reg_write((at93c_reg_read() | at93c->cs) & ~at93c->clk & ~(1 << at93c->rdata_shift)); lasat_ndelay(50); } static void at93c_end_op(void) { at93c_reg_write(at93c_reg_read() & ~at93c->cs); lasat_ndelay(250); } static void at93c_wait(void) { at93c_init_op(); while (!at93c_read_databit()) ; at93c_end_op(); }; static void at93c_disable_wp(void) { at93c_init_op(); at93c_write_bits(AT93C_WENCMD, 10); at93c_end_op(); } static void at93c_enable_wp(void) { at93c_init_op(); at93c_write_bits(AT93C_WDSCMD, 10); at93c_end_op(); } u8 at93c_read(u8 addr) { u8 byte; at93c_init_op(); at93c_write_bits((addr & AT93C_ADDR_MAX)|AT93C_RCMD, 10); byte = at93c_read_byte(); at93c_end_op(); return byte; } void at93c_write(u8 addr, u8 data) { at93c_disable_wp(); at93c_init_op(); at93c_write_bits((addr & AT93C_ADDR_MAX)|AT93C_WCMD, 10); at93c_write_bits(data, 8); at93c_end_op(); at93c_wait(); at93c_enable_wp(); }