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