linux/arch/mips/lasat/ds1603.c
<<
>>
Prefs
   1/*
   2 * Dallas Semiconductors 1603 RTC driver
   3 *
   4 * Brian Murphy <brian@murphy.dk>
   5 *
   6 */
   7#include <linux/kernel.h>
   8#include <asm/lasat/lasat.h>
   9#include <linux/delay.h>
  10#include <asm/lasat/ds1603.h>
  11#include <asm/time.h>
  12
  13#include "ds1603.h"
  14
  15#define READ_TIME_CMD 0x81
  16#define SET_TIME_CMD 0x80
  17#define TRIMMER_SET_CMD 0xC0
  18#define TRIMMER_VALUE_MASK 0x38
  19#define TRIMMER_SHIFT 3
  20
  21struct ds_defs *ds1603;
  22
  23/* HW specific register functions */
  24static void rtc_reg_write(unsigned long val)
  25{
  26        *ds1603->reg = val;
  27}
  28
  29static unsigned long rtc_reg_read(void)
  30{
  31        unsigned long tmp = *ds1603->reg;
  32        return tmp;
  33}
  34
  35static unsigned long rtc_datareg_read(void)
  36{
  37        unsigned long tmp = *ds1603->data_reg;
  38        return tmp;
  39}
  40
  41static void rtc_nrst_high(void)
  42{
  43        rtc_reg_write(rtc_reg_read() | ds1603->rst);
  44}
  45
  46static void rtc_nrst_low(void)
  47{
  48        rtc_reg_write(rtc_reg_read() & ~ds1603->rst);
  49}
  50
  51static void rtc_cycle_clock(unsigned long data)
  52{
  53        data |= ds1603->clk;
  54        rtc_reg_write(data);
  55        lasat_ndelay(250);
  56        if (ds1603->data_reversed)
  57                data &= ~ds1603->data;
  58        else
  59                data |= ds1603->data;
  60        data &= ~ds1603->clk;
  61        rtc_reg_write(data);
  62        lasat_ndelay(250 + ds1603->huge_delay);
  63}
  64
  65static void rtc_write_databit(unsigned int bit)
  66{
  67        unsigned long data = rtc_reg_read();
  68        if (ds1603->data_reversed)
  69                bit = !bit;
  70        if (bit)
  71                data |= ds1603->data;
  72        else
  73                data &= ~ds1603->data;
  74
  75        rtc_reg_write(data);
  76        lasat_ndelay(50 + ds1603->huge_delay);
  77        rtc_cycle_clock(data);
  78}
  79
  80static unsigned int rtc_read_databit(void)
  81{
  82        unsigned int data;
  83
  84        data = (rtc_datareg_read() & (1 << ds1603->data_read_shift))
  85                >> ds1603->data_read_shift;
  86        rtc_cycle_clock(rtc_reg_read());
  87        return data;
  88}
  89
  90static void rtc_write_byte(unsigned int byte)
  91{
  92        int i;
  93
  94        for (i = 0; i <= 7; i++) {
  95                rtc_write_databit(byte & 1L);
  96                byte >>= 1;
  97        }
  98}
  99
 100static void rtc_write_word(unsigned long word)
 101{
 102        int i;
 103
 104        for (i = 0; i <= 31; i++) {
 105                rtc_write_databit(word & 1L);
 106                word >>= 1;
 107        }
 108}
 109
 110static unsigned long rtc_read_word(void)
 111{
 112        int i;
 113        unsigned long word = 0;
 114        unsigned long shift = 0;
 115
 116        for (i = 0; i <= 31; i++) {
 117                word |= rtc_read_databit() << shift;
 118                shift++;
 119        }
 120        return word;
 121}
 122
 123static void rtc_init_op(void)
 124{
 125        rtc_nrst_high();
 126
 127        rtc_reg_write(rtc_reg_read() & ~ds1603->clk);
 128
 129        lasat_ndelay(50);
 130}
 131
 132static void rtc_end_op(void)
 133{
 134        rtc_nrst_low();
 135        lasat_ndelay(1000);
 136}
 137
 138unsigned long read_persistent_clock(void)
 139{
 140        unsigned long word;
 141        unsigned long flags;
 142
 143        spin_lock_irqsave(&rtc_lock, flags);
 144        rtc_init_op();
 145        rtc_write_byte(READ_TIME_CMD);
 146        word = rtc_read_word();
 147        rtc_end_op();
 148        spin_unlock_irqrestore(&rtc_lock, flags);
 149
 150        return word;
 151}
 152
 153int rtc_mips_set_mmss(unsigned long time)
 154{
 155        unsigned long flags;
 156
 157        spin_lock_irqsave(&rtc_lock, flags);
 158        rtc_init_op();
 159        rtc_write_byte(SET_TIME_CMD);
 160        rtc_write_word(time);
 161        rtc_end_op();
 162        spin_unlock_irqrestore(&rtc_lock, flags);
 163
 164        return 0;
 165}
 166
 167void ds1603_set_trimmer(unsigned int trimval)
 168{
 169        rtc_init_op();
 170        rtc_write_byte(((trimval << TRIMMER_SHIFT) & TRIMMER_VALUE_MASK)
 171                        | (TRIMMER_SET_CMD));
 172        rtc_end_op();
 173}
 174
 175void ds1603_disable(void)
 176{
 177        ds1603_set_trimmer(TRIMMER_DISABLE_RTC);
 178}
 179
 180void ds1603_enable(void)
 181{
 182        ds1603_set_trimmer(TRIMMER_DEFAULT);
 183}
 184