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