Exemplo n.º 1
0
static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
	local_irq_disable();
	rtc_wait_not_busy();

	alm->time.tm_sec = rtc_read(OMAP_RTC_ALARM_SECONDS_REG);
	alm->time.tm_min = rtc_read(OMAP_RTC_ALARM_MINUTES_REG);
	alm->time.tm_hour = rtc_read(OMAP_RTC_ALARM_HOURS_REG);
	alm->time.tm_mday = rtc_read(OMAP_RTC_ALARM_DAYS_REG);
	alm->time.tm_mon = rtc_read(OMAP_RTC_ALARM_MONTHS_REG);
	alm->time.tm_year = rtc_read(OMAP_RTC_ALARM_YEARS_REG);

	local_irq_enable();

	bcd2tm(&alm->time);
	alm->enabled = !!(rtc_read(OMAP_RTC_INTERRUPTS_REG)
			& OMAP_RTC_INTERRUPTS_IT_ALARM);

	return 0;
}
Exemplo n.º 2
0
Arquivo: rtc.c Projeto: acceso/jOS
void
rtc_get_tm (struct tm *tim)
{	
	u16 daysmonth[] = { 0, 0, 31, 59, 90, 120, 151, 
		181, 212, 243, 273, 304, 334 };

	/* When this bit is set, rtc is updating the count. 
	 * It gives us 244 usecs */
	while ((rtc_read (0xa) & 0x80) != 0)
		;

	tim->tm_sec = rtc_read (0);
	tim->tm_min = rtc_read (2);
	tim->tm_hour = rtc_read (4);
	tim->tm_mday = rtc_read (7);
	tim->tm_mon = rtc_read (8);
	tim->tm_year = rtc_read (9) + 2000;
		/* Century will be assumed 20. 
		 * This code doesn't always work: */
		/* + bcd2int (rtc_read (0x32)) * 100; */
	tim->tm_wday = rtc_read (6) - 1;

	tim->tm_yday = daysmonth[tim->tm_mon] + tim->tm_mday;
}
Exemplo n.º 3
0
static int omap_rtc_resume(struct device *dev)
{
	u8 irqwake_stat;
	struct platform_device *pdev = to_platform_device(dev);
	const struct platform_device_id *id_entry =
				platform_get_device_id(pdev);

	/* Enable the clock/module so that we can access the registers */
	pm_runtime_get_sync(dev);

	if (device_may_wakeup(dev)) {
		disable_irq_wake(omap_rtc_alarm);

		if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) {
			irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN);
			irqwake_stat &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
			rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN);
		}
	} else {
		rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG);
	}
	return 0;
}
Exemplo n.º 4
0
static int omap_rtc_suspend(struct platform_device *pdev, pm_message_t state)
{
	struct rtc_time rtc_tm;
	struct timespec time;

	time.tv_nsec = 0;
	omap_rtc_read_time(NULL, &rtc_tm);
	rtc_tm_to_time(&rtc_tm, &time.tv_sec);

	save_time_delta(&rtc_delta, &time);
	irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG);

	/* FIXME the RTC alarm is not currently acting as a wakeup event
	 * source, and in fact this enable() call is just saving a flag
	 * that's never used...
	 */
	if (device_may_wakeup(&pdev->dev))
		enable_irq_wake(omap_rtc_alarm);
	else
		rtc_write(0, OMAP_RTC_INTERRUPTS_REG);

	return 0;
}
Exemplo n.º 5
0
 int main() 
 {
    time_t seconds;
    struct tm *timeinfo;
    
    rtc_init();
    rtc_write(1256729737);  // Set RTC time to Wed, 28 Oct 2009 11:35:37

    while(1) {
        seconds = rtc_read();
        timeinfo = localtime(&seconds);

        DBG_8195A("Time as seconds since January 1, 1970 = %d\n", seconds);

        DBG_8195A("Time as a basic string = %s", ctime(&seconds));

        DBG_8195A("Time as a custom formatted string = %d-%d-%d %d:%d:%d ", 
            timeinfo->tm_year, timeinfo->tm_mon, timeinfo->tm_mday, timeinfo->tm_hour,
            timeinfo->tm_min,timeinfo->tm_sec);

        wait(1);
    }
 }
Exemplo n.º 6
0
static int omap_rtc_suspend(struct device *dev)
{
	struct omap_rtc *rtc = dev_get_drvdata(dev);

	rtc->interrupts_reg = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG);

	rtc->type->unlock(rtc);
	/*
	 * FIXME: the RTC alarm is not currently acting as a wakeup event
	 * source on some platforms, and in fact this enable() call is just
	 * saving a flag that's never used...
	 */
	if (device_may_wakeup(dev))
		enable_irq_wake(rtc->irq_alarm);
	else
		rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0);
	rtc->type->lock(rtc);

	/* Disable the clock/module */
	pm_runtime_put_sync(dev);

	return 0;
}
Exemplo n.º 7
0
static int __exit omap_rtc_remove(struct platform_device *pdev)
{
	struct omap_rtc *rtc = platform_get_drvdata(pdev);
	u8 reg;

	if (pm_power_off == omap_rtc_power_off &&
			omap_rtc_power_off_rtc == rtc) {
		pm_power_off = NULL;
		omap_rtc_power_off_rtc = NULL;
	}

	device_init_wakeup(&pdev->dev, 0);

	if (!IS_ERR(rtc->clk))
		clk_disable_unprepare(rtc->clk);

	rtc->type->unlock(rtc);
	/* leave rtc running, but disable irqs */
	rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0);

	if (rtc->has_ext_clk) {
		reg = rtc_read(rtc, OMAP_RTC_OSC_REG);
		reg &= ~OMAP_RTC_OSC_SEL_32KCLK_SRC;
		rtc_write(rtc, OMAP_RTC_OSC_REG, reg);
	}

	rtc->type->lock(rtc);

	/* Disable the clock/module */
	pm_runtime_put_sync(&pdev->dev);
	pm_runtime_disable(&pdev->dev);

	/* Remove ext_wakeup pinconf */
	pinctrl_unregister(rtc->pctldev);

	return 0;
}
Exemplo n.º 8
0
static int omap_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	/* we don't report wday/yday/isdst ... */
	local_irq_disable();
	rtc_wait_not_busy();

	tm->tm_sec = rtc_read(OMAP_RTC_SECONDS_REG);
	tm->tm_min = rtc_read(OMAP_RTC_MINUTES_REG);
	tm->tm_hour = rtc_read(OMAP_RTC_HOURS_REG);
	tm->tm_mday = rtc_read(OMAP_RTC_DAYS_REG);
	tm->tm_mon = rtc_read(OMAP_RTC_MONTHS_REG);
	tm->tm_year = rtc_read(OMAP_RTC_YEARS_REG);

	local_irq_enable();

	bcd2tm(tm);
	return 0;
}
Exemplo n.º 9
0
static irqreturn_t rtc_irq(int irq, void *dev_id)
{
	struct omap_rtc	*rtc = dev_id;
	unsigned long events = 0;
	u8 irq_data;

	irq_data = rtc_read(rtc, OMAP_RTC_STATUS_REG);

	/* alarm irq? */
	if (irq_data & OMAP_RTC_STATUS_ALARM) {
		rtc->type->unlock(rtc);
		rtc_write(rtc, OMAP_RTC_STATUS_REG, OMAP_RTC_STATUS_ALARM);
		rtc->type->lock(rtc);
		events |= RTC_IRQF | RTC_AF;
	}

	/* 1/sec periodic/update irq? */
	if (irq_data & OMAP_RTC_STATUS_1S_EVENT)
		events |= RTC_IRQF | RTC_UF;

	rtc_update_irq(rtc->rtc, 1, events);

	return IRQ_HANDLED;
}
Exemplo n.º 10
0
/*
 * Return current RTC time. Note that due to waiting for the update cycle to
 * complete, this call may take some time.
 */
static uint64_t rtc_gettimeofday(void) {
    struct bmk_clock_ymdhms dt;

    interrupts_disable();

    /*
     * If RTC_UIP is down, we have at least 244us to obtain a
     * consistent reading before an update can occur.
     */
    while (rtc_read(RTC_STATUS_A) & RTC_UIP)
        continue;

    dt.dt_sec = bcdtobin(rtc_read(RTC_SEC));
    dt.dt_min = bcdtobin(rtc_read(RTC_MIN));
    dt.dt_hour = bcdtobin(rtc_read(RTC_HOUR));
    dt.dt_day = bcdtobin(rtc_read(RTC_DAY));
    dt.dt_mon = bcdtobin(rtc_read(RTC_MONTH));
    dt.dt_year = bcdtobin(rtc_read(RTC_YEAR)) + 2000;

    interrupts_enable();

    return clock_ymdhms_to_secs(&dt) * NSEC_PER_SEC;
}
Exemplo n.º 11
0
static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
	struct omap_rtc *rtc = dev_get_drvdata(dev);
	u8 interrupts;

	local_irq_disable();
	rtc_wait_not_busy(rtc);

	alm->time.tm_sec = rtc_read(rtc, OMAP_RTC_ALARM_SECONDS_REG);
	alm->time.tm_min = rtc_read(rtc, OMAP_RTC_ALARM_MINUTES_REG);
	alm->time.tm_hour = rtc_read(rtc, OMAP_RTC_ALARM_HOURS_REG);
	alm->time.tm_mday = rtc_read(rtc, OMAP_RTC_ALARM_DAYS_REG);
	alm->time.tm_mon = rtc_read(rtc, OMAP_RTC_ALARM_MONTHS_REG);
	alm->time.tm_year = rtc_read(rtc, OMAP_RTC_ALARM_YEARS_REG);

	local_irq_enable();

	bcd2tm(&alm->time);

	interrupts = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG);
	alm->enabled = !!(interrupts & OMAP_RTC_INTERRUPTS_IT_ALARM);

	return 0;
}
Exemplo n.º 12
0
int rtc_get(struct rtc_time *rtc)
{
	uchar sec, min, hour, mday, month, year;

	/* Reading counts register latches the current RTC calendar count.
	 * This guranties the coherence of the read during aprox 500 ms */
	sec = rtc_read (DA9052_COUNTS_REG);
	if (!(sec & DA9052_COUNTS_MONITOR)) {
		puts("*** ERROR: " DEV_NAME " - incorrect date/time (Power was lost)\n");
	}
	min = rtc_read (DA9052_COUNTMI_REG);
	hour = rtc_read (DA9052_COUNTH_REG);
	mday = rtc_read (DA9052_COUNTD_REG);
	month = rtc_read (DA9052_COUNTMO_REG);
	year = rtc_read (DA9052_COUNTY_REG);

	DBG ("Get RTC year: %02d mon: %02d mday: %02d "
		"hr: %02d min: %02d sec: %02d\n",
		year, month, mday, hour, min, sec);

	rtc->tm_sec  = sec & DA9052_COUNTS_COUNTSEC;
	rtc->tm_min  = min & DA9052_COUNTMI_COUNTMIN;
	rtc->tm_hour = hour & DA9052_COUNTH_COUNTHOUR;
	rtc->tm_mday = mday & DA9052_COUNTD_COUNTDAY;
	rtc->tm_mon  = month & DA9052_COUNTMO_COUNTMONTH;
	rtc->tm_year = (year & DA9052_COUNTY_COUNTYEAR) + 2000;

	/* Compute the the day of week, not available in the RTC registers */
	GregorianDay(rtc);

	DBG ("Get DATE: %4d-%02d-%02d   TIME: %2d:%02d:%02d\n",
		rtc->tm_year, rtc->tm_mon, rtc->tm_mday,
		rtc->tm_hour, rtc->tm_min, rtc->tm_sec);

	return 0;
}
Exemplo n.º 13
0
/*
 * set the rtc chip's idea of the time.
 * stupidly, some callers call with year unmolested;
 * and some call with  year = year - 1900.  thanks.
 */
static int ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm)
{
	u8 mon, day, dow, hrs, min, sec, yrs, cen;
	unsigned long flags;

	/*
	 * won't have to change this for a while
	 */
	if (rtc_tm->tm_year < 1900) {
		rtc_tm->tm_year += 1900;
	}

	if (rtc_tm->tm_year < 1970) {
		return -EINVAL;
	}
	yrs = rtc_tm->tm_year % 100;
	cen = rtc_tm->tm_year / 100;
	mon = rtc_tm->tm_mon + 1;   /* tm_mon starts at zero */
	day = rtc_tm->tm_mday;
	dow = rtc_tm->tm_wday & 0x7; /* automatic BCD */
	hrs = rtc_tm->tm_hour;
	min = rtc_tm->tm_min;
	sec = rtc_tm->tm_sec;

	if ((mon > 12) || (day == 0)) {
		return -EINVAL;
	}

	if (day > rtc_month_days(rtc_tm->tm_mon, rtc_tm->tm_year)) {
		return -EINVAL;
	}

	if ((hrs >= 24) || (min >= 60) || (sec >= 60)) {
		return -EINVAL;
	}

	/*
	 * each register is a different number of valid bits
	 */
	sec = bin2bcd(sec) & 0x7f;
	min = bin2bcd(min) & 0x7f;
	hrs = bin2bcd(hrs) & 0x3f;
	day = bin2bcd(day) & 0x3f;
	mon = bin2bcd(mon) & 0x1f;
	yrs = bin2bcd(yrs) & 0xff;
	cen = bin2bcd(cen) & 0xff;

	spin_lock_irqsave(&ds1511_lock, flags);
	rtc_disable_update();
	rtc_write(cen, RTC_CENTURY);
	rtc_write(yrs, RTC_YEAR);
	rtc_write((rtc_read(RTC_MON) & 0xe0) | mon, RTC_MON);
	rtc_write(day, RTC_DOM);
	rtc_write(hrs, RTC_HOUR);
	rtc_write(min, RTC_MIN);
	rtc_write(sec, RTC_SEC);
	rtc_write(dow, RTC_DOW);
	rtc_enable_update();
	spin_unlock_irqrestore(&ds1511_lock, flags);

	return 0;
}
Exemplo n.º 14
0
int main(void)
{
  uart_t *u0;

  /* Delay for one second to avoid multiple resets during programming. */
  _delay_ms(1000);

  /* Initialize USART0 and set up stdout to write to it. */
  u0 = uart_init("0", UART_BAUD_SELECT(38400, F_CPU));
  uart_init_stdout(u0);
  uart_set_rx_callback(u0, notice_uart_input);

  i2c_init();

  /*
   * Test if pullup is required on the I2C pins, and enable if the pins are
   * reading low. This allows external pullups to optionally be used, so that
   * for example the I2C bus can be pulled up to 3.3V to allow communication
   * between 3.3V and 5V devices at 3.3V.
   */
  if((PINC & (_BV(PC0) | _BV(PC1))) == 0)
  {
    DDRC  = _BV(PC0) | _BV(PC1);
    PORTC = _BV(PC0) | _BV(PC1);
  }

  sei();

  printf_P(PSTR("\n\nBooted!\n"));

  printf_P(PSTR("Reading saved configuration...\n\n"));
  configuration_restore();

  printf_P(PSTR(
    "Configuration:\n"
    "  tz_offset:  %2i\n"
    "  dst_offset: %2i\n"
    "\n"
  ), configuration.tz_offset, configuration.dst_offset);

  printf_P(PSTR(
    "Commands:\n"
    "  Get the current time:\n"
    "    G\n"
    "  Set the current time:\n"
    "    S YYYY-MM-DD hh:mm:ss\n"
    "  Set the timezone offset from UTC:\n"
    "    O <tz_offset> <dst_offset>\n"
    "  Set the time from GPS (if available):"
    "    s\n"
    "\n"
  ));

  rtc_init(rtc);
  rtc_sqw_enable(rtc);
  rtc_sqw_rate(rtc, 1);

  /* Enable pullup and interrupt for PC6/PCINT22, DS1307 SQW pin. */
  PORTC  |= _BV(PC6);
  PCMSK2 |= _BV(PCINT22);
  PCICR  |= _BV(PCIE2);

  /* Initialize the sequencer with 1000Hz tick rate. */
  led_sequencer_init(1000);

  /* Initialize and load the LED Analog Clock LED display. */
  led_charlieplex_init(&LED_DISPLAY);
  led_sequencer_push_front_matrix("c", &LED_DISPLAY);

  /*
   * Add empty sequences for hour, minute, second, hourly show, and minutely
   * show.
   */
  led_sequencer_push_back_sequence("h");
  led_sequencer_push_back_sequence("m");
  led_sequencer_push_back_sequence("s");
  led_sequencer_push_back_sequence("H");
  led_sequencer_push_back_sequence("M");

  /*
   * Initially read the time, set last_* for use later, and push a sequencer
   * step into the second, minute, and hour sequences.  The steps pushed
   * below are never removed, as they are modified in place in update_hms()
   * with each time change.
   */
  rtc_read(rtc, &current_time);
  last_hour   = current_time.hour;
  last_minute = current_time.minute;
  last_second = current_time.second;
  step_hour   = led_sequencer_sequence_push_back_step("h", LED_SEQUENCER_STEP_SHOW, "c", led_mapping_qhour[((current_time.hour % 12) * 4) + (current_time.minute / 15)], 255);
  step_minute = led_sequencer_sequence_push_back_step("m", LED_SEQUENCER_STEP_SHOW, "c", led_mapping_minute[current_time.minute], 255);
  step_second = led_sequencer_sequence_push_back_step("s", LED_SEQUENCER_STEP_SHOW, "c", led_mapping_minute[current_time.second], 255);

  enqueue_hourly_show();

  led_sequencer_run();

  srand(current_time.hour * current_time.minute * current_time.second);

  /*
   * Main infinite loop.
   */
  while(1)
  {
    /* Handle UART input when ready. */
    if(ready_flags & READY_UART_DATA)
    {
      ready_flags &= ~READY_UART_DATA;
      handle_uart_input(u0);
    }

    /* A time change has occurred, update the clock display. */
    if(ready_flags & READY_UPDATE_HMS)
    {
      ready_flags &= ~READY_UPDATE_HMS;
      update_hms();
    }

    /*
     * Run one loop through the current sequence, with interrupts disabled.
     */
    cli();
    led_sequencer_display();
    sei();
  }

  /* Never reached. */
  return(0);
}
Exemplo n.º 15
0
int rtc_get( struct rtc_time *tmp)
{
	if (phantom_flag < 0)
		phantom_flag = get_phantom_flag();

	if (phantom_flag)
	{
		unsigned char rtc[8];

		phantom_rtc_read(RTC_BASE, rtc);

		tmp->tm_sec	= bcd2bin(rtc[1] & 0x7f);
		tmp->tm_min	= bcd2bin(rtc[2] & 0x7f);
		tmp->tm_hour	= bcd2bin(rtc[3] & 0x1f);
		tmp->tm_wday	= bcd2bin(rtc[4] & 0x7);
		tmp->tm_mday	= bcd2bin(rtc[5] & 0x3f);
		tmp->tm_mon	= bcd2bin(rtc[6] & 0x1f);
		tmp->tm_year	= bcd2bin(rtc[7]) + 1900;
		tmp->tm_yday = 0;
		tmp->tm_isdst = 0;

		if( (rtc[3] & 0x80)  && (rtc[3] & 0x40) ) tmp->tm_hour += 12;
		if (tmp->tm_year < 1970) tmp->tm_year += 100;
	} else {
		uchar sec, min, hour;
		uchar mday, wday, mon, year;

		int century;

		uchar reg_a;

		if (century_flag < 0)
			century_flag = get_century_flag();

		reg_a = rtc_read( RTC_CONTROLA );
		/* lock clock registers for read */
		rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_READ ));

		sec     = rtc_read( RTC_SECONDS );
		min     = rtc_read( RTC_MINUTES );
		hour    = rtc_read( RTC_HOURS );
		mday    = rtc_read( RTC_DAY_OF_MONTH );
		wday    = rtc_read( RTC_DAY_OF_WEEK );
		mon     = rtc_read( RTC_MONTH );
		year    = rtc_read( RTC_YEAR );
		century = rtc_read( RTC_CENTURY );

		/* unlock clock registers after read */
		rtc_write( RTC_CONTROLA, ( reg_a & ~RTC_CA_READ ));

		tmp->tm_sec  = bcd2bin( sec  & 0x7F );
		tmp->tm_min  = bcd2bin( min  & 0x7F );
		tmp->tm_hour = bcd2bin( hour & 0x3F );
		tmp->tm_mday = bcd2bin( mday & 0x3F );
		tmp->tm_mon  = bcd2bin( mon & 0x1F );
		tmp->tm_wday = bcd2bin( wday & 0x07 );

		if (century_flag) {
			tmp->tm_year = bcd2bin( year ) +
				( bcd2bin( century & 0x3F ) * 100 );
		} else {
			tmp->tm_year = bcd2bin( year ) + 1900;
			if (tmp->tm_year < 1970) tmp->tm_year += 100;
		}

		tmp->tm_yday = 0;
		tmp->tm_isdst= 0;
	}

	return 0;
}
Exemplo n.º 16
0
void timer_sync_time( void )
{
	current_time = rtc_read();
}
Exemplo n.º 17
0
/**
 * Update the "h", "m", and "s" sequences, optionally queuing an animation
 * into "H" or "M" sequences, depending on the new time.  This function is
 * called once per second during the main loop after the interrupt triggered
 * by the time change marks update_hms_ready.
 *
 * The "h", "m", and "s" sequences are updated in-place in order to avoid
 * additional work and possible memory fragmentation from removing and
 * re-enqueuing the applicable LED.
 */
void update_hms(void)
{
  uint8_t rc;
  rtc_datetime_24h_t offset_time;

  if(++time_elapsed_since_gps_sync > 1777)
  {
    printf_P(PSTR("Maximum time limit exceeded since last GPS sync, syncing...\n"));
    command_set_from_gps();
    time_elapsed_since_gps_sync = 0;
  }

  rc = rtc_read(rtc, &current_time);
  if(rc) return;

  rtc_offset_time(&current_time, &offset_time,
    configuration.tz_offset + configuration.dst_offset);

  if(current_time.hour != last_hour)
  {
    configuration.dst_offset = rtc_find_dst_offset(offset_time, usa_dst_dates);
    rtc_offset_time(&current_time, &offset_time,
      configuration.tz_offset + configuration.dst_offset);
  }

  led_sequencer_halt();

  /*
   * If the second has changed since the last time the time was checked,
   * we should update the "second", "minute, and "hour" sequences.  In practice
   * this is nearly always the case, since the interrupts ensure we're only
   * really called when needed.
   */
  if(current_time.second != last_second)
  {
    led_sequencer_sequence_modify_step(step_second, led_mapping_minute[offset_time.second], 255);
    led_sequencer_sequence_modify_step(step_minute, led_mapping_minute[offset_time.minute], 255);
    led_sequencer_sequence_modify_step(step_hour,   led_mapping_qhour[((offset_time.hour % 12) * 4) + (offset_time.minute / 15)], 255);
    enqueue_secondly_show();
    last_second = current_time.second;
  }

  /* Do something nice for New Years */
  if(offset_time.month == 1 && offset_time.date == 1
		  && offset_time.hour == 0 && offset_time.minute == 0
		  && offset_time.second == 0)
  {
    enqueue_nye_show();
    last_hour   = current_time.hour;
    last_minute = current_time.minute;
  }

  /*
   * If the hour has changed, enqueue the hourly show.
   */
  else if(current_time.hour != last_hour)
  {
    enqueue_hourly_show();
    last_hour = current_time.hour;
  }

  /*
   * If the hour is still the same, enqueue the minutely show.
   */
  else if(current_time.minute != last_minute)
  {
    enqueue_minutely_show();
    last_minute = current_time.minute;
  }

  led_sequencer_run();
  update_gps();
  write_remote_lcd(&offset_time, gps_data.gps_signal_strength);
}
Exemplo n.º 18
0
static int __init omap_rtc_probe(struct platform_device *pdev)
{
	struct resource		*res, *mem;
	struct rtc_device	*rtc;
	u8			reg, new_ctrl;

	omap_rtc_timer = platform_get_irq(pdev, 0);
	if (omap_rtc_timer <= 0) {
		pr_debug("%s: no update irq?\n", pdev->name);
		return -ENOENT;
	}

	omap_rtc_alarm = platform_get_irq(pdev, 1);
	if (omap_rtc_alarm <= 0) {
		pr_debug("%s: no alarm irq?\n", pdev->name);
		return -ENOENT;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		pr_debug("%s: RTC resource data missing\n", pdev->name);
		return -ENOENT;
	}

	mem = request_mem_region(res->start, resource_size(res), pdev->name);
	if (!mem) {
		pr_debug("%s: RTC registers at %08x are not free\n",
			pdev->name, res->start);
		return -EBUSY;
	}

	rtc_base = ioremap(res->start, resource_size(res));
	if (!rtc_base) {
		pr_debug("%s: RTC registers can't be mapped\n", pdev->name);
		goto fail;
	}

	rtc = rtc_device_register(pdev->name, &pdev->dev,
			&omap_rtc_ops, THIS_MODULE);
	if (IS_ERR(rtc)) {
		pr_debug("%s: can't register RTC device, err %ld\n",
			pdev->name, PTR_ERR(rtc));
		goto fail0;
	}
	platform_set_drvdata(pdev, rtc);
	dev_set_drvdata(&rtc->dev, mem);

	/* clear pending irqs, and set 1/second periodic,
	 * which we'll use instead of update irqs
	 */
	rtc_write(0, OMAP_RTC_INTERRUPTS_REG);

	/* clear old status */
	reg = rtc_read(OMAP_RTC_STATUS_REG);
	if (reg & (u8) OMAP_RTC_STATUS_POWER_UP) {
		pr_info("%s: RTC power up reset detected\n",
			pdev->name);
		rtc_write(OMAP_RTC_STATUS_POWER_UP, OMAP_RTC_STATUS_REG);
	}
	if (reg & (u8) OMAP_RTC_STATUS_ALARM)
		rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG);

	/* handle periodic and alarm irqs */
	if (request_irq(omap_rtc_timer, rtc_irq, IRQF_DISABLED,
			dev_name(&rtc->dev), rtc)) {
		pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n",
			pdev->name, omap_rtc_timer);
		goto fail1;
	}
	if ((omap_rtc_timer != omap_rtc_alarm) &&
		(request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED,
			dev_name(&rtc->dev), rtc))) {
		pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n",
			pdev->name, omap_rtc_alarm);
		goto fail2;
	}

	/* On boards with split power, RTC_ON_NOFF won't reset the RTC */
	reg = rtc_read(OMAP_RTC_CTRL_REG);
	if (reg & (u8) OMAP_RTC_CTRL_STOP)
		pr_info("%s: already running\n", pdev->name);

	/* force to 24 hour mode */
	new_ctrl = reg & ~(OMAP_RTC_CTRL_SPLIT|OMAP_RTC_CTRL_AUTO_COMP);
	new_ctrl |= OMAP_RTC_CTRL_STOP;

	/* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE:
	 *
	 *  - Device wake-up capability setting should come through chip
	 *    init logic. OMAP1 boards should initialize the "wakeup capable"
	 *    flag in the platform device if the board is wired right for
	 *    being woken up by RTC alarm. For OMAP-L138, this capability
	 *    is built into the SoC by the "Deep Sleep" capability.
	 *
	 *  - Boards wired so RTC_ON_nOFF is used as the reset signal,
	 *    rather than nPWRON_RESET, should forcibly enable split
	 *    power mode.  (Some chip errata report that RTC_CTRL_SPLIT
	 *    is write-only, and always reads as zero...)
	 */

	if (new_ctrl & (u8) OMAP_RTC_CTRL_SPLIT)
		pr_info("%s: split power mode\n", pdev->name);

	if (reg != new_ctrl)
		rtc_write(new_ctrl, OMAP_RTC_CTRL_REG);

	return 0;

fail2:
	free_irq(omap_rtc_timer, rtc);
fail1:
	rtc_device_unregister(rtc);
fail0:
	iounmap(rtc_base);
fail:
	release_mem_region(mem->start, resource_size(mem));
	return -EIO;
}
Exemplo n.º 19
0
rtems_device_driver Clock_initialize(
  rtems_device_major_number major,
  rtems_device_minor_number minor,
  void *pargp
)
{
  unsigned timer_counter_init_value;
  unsigned char clock_lsb, clock_msb;

#ifdef BSP_DEBUG
  printk("Initializing clock driver in Clock_initialize().\n");
#endif

#ifdef LOAD_RTC_AT_START
  /* Initialize clock from on-board real time clock.  This breaks the  */
  /* test code which assumes which assumes the application will do it. */
  {
    rtems_time_of_day now;


#ifdef BSP_DEBUG
    printk("Loading clock from on-board real-time clock.\n");
#endif

    init_rtc();
    if (rtc_read(&now) >= 0)
      rtems_clock_set(&now);
  }
#endif

  Clock_driver_ticks = 0;

  Clock_isrs =
    Clock_initial_isr_value =
    rtems_configuration_get_microseconds_per_tick() / 1000; /* ticks per clock_isr */

  /*
   * configure the counter timer ( should be based on microsecs/tick )
   * NB. The divisor(Clock_isrs) resolves the  is the same number that appears in confdefs.h
   * when setting the microseconds_per_tick value.
   */
  ClockOff      ( &clockIrqData );

  timer_counter_init_value  =  rtems_configuration_get_microseconds_per_tick() / Clock_isrs;
  clock_lsb = (unsigned char)timer_counter_init_value;
  clock_msb = timer_counter_init_value >> 8;

  outport_byte (TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
  outport_byte (TIMER_CNTR0, clock_lsb );   /* load LSB first */
  outport_byte (TIMER_CNTR0, clock_msb );   /* then MSB       */

  if (!BSP_install_rtems_irq_handler (&clockIrqData)) {
    printk("Unable to initialize system clock\n");
    rtems_fatal_error_occurred(1);
  }

  /*
   * make major/minor avail to others such as shared memory driver
   */

  rtems_clock_major = major;
  rtems_clock_minor = minor;

  return RTEMS_SUCCESSFUL;
}
Exemplo n.º 20
0
unsigned char time_get(unsigned char addr) {
	rtc_write(addr);
	unsigned char ret = rtc_read();
	rtc_transm_end();
	return ret;
}
Exemplo n.º 21
0
static int omap_rtc_probe(struct platform_device *pdev)
{
	struct omap_rtc	*rtc;
	struct resource	*res;
	u8 reg, mask, new_ctrl;
	const struct platform_device_id *id_entry;
	const struct of_device_id *of_id;
	int ret;

	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
	if (!rtc)
		return -ENOMEM;

	of_id = of_match_device(omap_rtc_of_match, &pdev->dev);
	if (of_id) {
		rtc->type = of_id->data;
		rtc->is_pmic_controller = rtc->type->has_pmic_mode &&
				of_property_read_bool(pdev->dev.of_node,
						"system-power-controller");
	} else {
		id_entry = platform_get_device_id(pdev);
		rtc->type = (void *)id_entry->driver_data;
	}

	rtc->irq_timer = platform_get_irq(pdev, 0);
	if (rtc->irq_timer <= 0)
		return -ENOENT;

	rtc->irq_alarm = platform_get_irq(pdev, 1);
	if (rtc->irq_alarm <= 0)
		return -ENOENT;

	rtc->clk = devm_clk_get(&pdev->dev, "ext-clk");
	if (!IS_ERR(rtc->clk))
		rtc->has_ext_clk = true;
	else
		rtc->clk = devm_clk_get(&pdev->dev, "int-clk");

	if (!IS_ERR(rtc->clk))
		clk_prepare_enable(rtc->clk);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	rtc->base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(rtc->base))
		return PTR_ERR(rtc->base);

	platform_set_drvdata(pdev, rtc);

	/* Enable the clock/module so that we can access the registers */
	pm_runtime_enable(&pdev->dev);
	pm_runtime_get_sync(&pdev->dev);

	rtc->type->unlock(rtc);

	/*
	 * disable interrupts
	 *
	 * NOTE: ALARM2 is not cleared on AM3352 if rtc_write (writeb) is used
	 */
	rtc_writel(rtc, OMAP_RTC_INTERRUPTS_REG, 0);

	/* enable RTC functional clock */
	if (rtc->type->has_32kclk_en) {
		reg = rtc_read(rtc, OMAP_RTC_OSC_REG);
		rtc_writel(rtc, OMAP_RTC_OSC_REG,
				reg | OMAP_RTC_OSC_32KCLK_EN);
	}

	/* clear old status */
	reg = rtc_read(rtc, OMAP_RTC_STATUS_REG);

	mask = OMAP_RTC_STATUS_ALARM;

	if (rtc->type->has_pmic_mode)
		mask |= OMAP_RTC_STATUS_ALARM2;

	if (rtc->type->has_power_up_reset) {
		mask |= OMAP_RTC_STATUS_POWER_UP;
		if (reg & OMAP_RTC_STATUS_POWER_UP)
			dev_info(&pdev->dev, "RTC power up reset detected\n");
	}

	if (reg & mask)
		rtc_write(rtc, OMAP_RTC_STATUS_REG, reg & mask);

	/* On boards with split power, RTC_ON_NOFF won't reset the RTC */
	reg = rtc_read(rtc, OMAP_RTC_CTRL_REG);
	if (reg & OMAP_RTC_CTRL_STOP)
		dev_info(&pdev->dev, "already running\n");

	/* force to 24 hour mode */
	new_ctrl = reg & (OMAP_RTC_CTRL_SPLIT | OMAP_RTC_CTRL_AUTO_COMP);
	new_ctrl |= OMAP_RTC_CTRL_STOP;

	/*
	 * BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE:
	 *
	 *  - Device wake-up capability setting should come through chip
	 *    init logic. OMAP1 boards should initialize the "wakeup capable"
	 *    flag in the platform device if the board is wired right for
	 *    being woken up by RTC alarm. For OMAP-L138, this capability
	 *    is built into the SoC by the "Deep Sleep" capability.
	 *
	 *  - Boards wired so RTC_ON_nOFF is used as the reset signal,
	 *    rather than nPWRON_RESET, should forcibly enable split
	 *    power mode.  (Some chip errata report that RTC_CTRL_SPLIT
	 *    is write-only, and always reads as zero...)
	 */

	if (new_ctrl & OMAP_RTC_CTRL_SPLIT)
		dev_info(&pdev->dev, "split power mode\n");

	if (reg != new_ctrl)
		rtc_write(rtc, OMAP_RTC_CTRL_REG, new_ctrl);

	/*
	 * If we have the external clock then switch to it so we can keep
	 * ticking across suspend.
	 */
	if (rtc->has_ext_clk) {
		reg = rtc_read(rtc, OMAP_RTC_OSC_REG);
		reg &= ~OMAP_RTC_OSC_OSC32K_GZ_DISABLE;
		reg |= OMAP_RTC_OSC_32KCLK_EN | OMAP_RTC_OSC_SEL_32KCLK_SRC;
		rtc_writel(rtc, OMAP_RTC_OSC_REG, reg);
	}

	rtc->type->lock(rtc);

	device_init_wakeup(&pdev->dev, true);

	rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
			&omap_rtc_ops, THIS_MODULE);
	if (IS_ERR(rtc->rtc)) {
		ret = PTR_ERR(rtc->rtc);
		goto err;
	}

	/* handle periodic and alarm irqs */
	ret = devm_request_irq(&pdev->dev, rtc->irq_timer, rtc_irq, 0,
			dev_name(&rtc->rtc->dev), rtc);
	if (ret)
		goto err;

	if (rtc->irq_timer != rtc->irq_alarm) {
		ret = devm_request_irq(&pdev->dev, rtc->irq_alarm, rtc_irq, 0,
				dev_name(&rtc->rtc->dev), rtc);
		if (ret)
			goto err;
	}

	if (rtc->is_pmic_controller) {
		if (!pm_power_off) {
			omap_rtc_power_off_rtc = rtc;
			pm_power_off = omap_rtc_power_off;
		}
	}

	/* Support ext_wakeup pinconf */
	rtc_pinctrl_desc.name = dev_name(&pdev->dev);

	rtc->pctldev = pinctrl_register(&rtc_pinctrl_desc, &pdev->dev, rtc);
	if (IS_ERR(rtc->pctldev)) {
		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
		return PTR_ERR(rtc->pctldev);
	}

	return 0;

err:
	device_init_wakeup(&pdev->dev, false);
	rtc->type->lock(rtc);
	pm_runtime_put_sync(&pdev->dev);
	pm_runtime_disable(&pdev->dev);

	return ret;
}
Exemplo n.º 22
0
 static inline void
rtc_disable_update(void)
{
	rtc_write((rtc_read(RTC_CMD) & ~RTC_TE), RTC_CMD);
}
Exemplo n.º 23
0
/*
 * Get the current time from the RTC
 */
int rtc_get (struct rtc_time *tmp)
{
	int rel = 0;
	uchar sec, min, hour, mday, wday, mon, year;

#ifdef CONFIG_RTC_MCP79411
read_rtc:
#endif
	sec = rtc_read (RTC_SEC_REG_ADDR);
	min = rtc_read (RTC_MIN_REG_ADDR);
	hour = rtc_read (RTC_HR_REG_ADDR);
	wday = rtc_read (RTC_DAY_REG_ADDR);
	mday = rtc_read (RTC_DATE_REG_ADDR);
	mon = rtc_read (RTC_MON_REG_ADDR);
	year = rtc_read (RTC_YR_REG_ADDR);

	DEBUGR ("Get RTC year: %02x mon: %02x mday: %02x wday: %02x "
		"hr: %02x min: %02x sec: %02x\n",
		year, mon, mday, wday, hour, min, sec);

#ifdef CONFIG_RTC_DS1307
	if (sec & RTC_SEC_BIT_CH) {
		printf ("### Warning: RTC oscillator has stopped\n");
		/* clear the CH flag */
		rtc_write (RTC_SEC_REG_ADDR,
			   rtc_read (RTC_SEC_REG_ADDR) & ~RTC_SEC_BIT_CH);
		rel = -1;
	}
#endif

#ifdef CONFIG_RTC_MCP79411
	/* make sure that the backup battery is enabled */
	if (!(wday & MCP7941X_BIT_VBATEN)) {
		rtc_write(RTC_DAY_REG_ADDR,
			  wday | MCP7941X_BIT_VBATEN);
	}

	/* clock halted?  turn it on, so clock can tick. */
	if (!(sec & MCP7941X_BIT_ST)) {
		rtc_write(RTC_SEC_REG_ADDR, MCP7941X_BIT_ST);
		printf("Started RTC\n");
		goto read_rtc;
	}
#endif


	tmp->tm_sec  = bcd2bin (sec & 0x7F);
	tmp->tm_min  = bcd2bin (min & 0x7F);
	tmp->tm_hour = bcd2bin (hour & 0x3F);
	tmp->tm_mday = bcd2bin (mday & 0x3F);
	tmp->tm_mon  = bcd2bin (mon & 0x1F);
	tmp->tm_year = bcd2bin (year) + ( bcd2bin (year) >= 70 ? 1900 : 2000);
	tmp->tm_wday = bcd2bin ((wday - 1) & 0x07);
	tmp->tm_yday = 0;
	tmp->tm_isdst= 0;

	DEBUGR ("Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
		tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
		tmp->tm_hour, tmp->tm_min, tmp->tm_sec);

	return rel;
}
Exemplo n.º 24
0
/*
 * ioctl calls for this driver. Why return -ENOTTY upon error? Because
 * POSIX says so!
 */
int
pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
	/* Some sanity checks. */
	if (_IOC_TYPE(cmd) != RTC_MAGIC)
		return -ENOTTY;

	if (_IOC_NR(cmd) > RTC_MAX_IOCTL)
		return -ENOTTY;

	switch (cmd) {
		case RTC_RD_TIME:
			{
				struct rtc_time tm;

				get_rtc_time(&tm);

				if (copy_to_user((struct rtc_time *) arg, &tm, sizeof(struct rtc_time))) {
					return -EFAULT;
				}

				return 0;
			}
			break;
		case RTC_SET_TIME:
			{
#ifdef CONFIG_ETRAX_RTC_READONLY
				return -EPERM;
#else
				int leap;
				int century;
				struct rtc_time tm;

				memset(&tm, 0, sizeof (struct rtc_time));
				if (!capable(CAP_SYS_TIME))
					return -EPERM;

				if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof(struct rtc_time)))
					return -EFAULT;

				/* Convert from struct tm to struct rtc_time. */
				tm.tm_year += 1900;
				tm.tm_mon += 1;
				
				leap = ((tm.tm_mon == 2) && ((tm.tm_year % 4) == 0)) ? 1 : 0;

				/* Perform some sanity checks. */
				if ((tm.tm_year < 1970) ||
				    (tm.tm_mon > 12) ||
				    (tm.tm_mday == 0) ||
				    (tm.tm_mday > days_in_month[tm.tm_mon] + leap) ||
				    (tm.tm_hour >= 24) ||
				    (tm.tm_min >= 60) ||
				    (tm.tm_sec >= 60))
					return -EINVAL;

				century = (tm.tm_year >= 2000) ? 0x80 : 0;
				tm.tm_year = tm.tm_year % 100;

				BIN_TO_BCD(tm.tm_year);
				BIN_TO_BCD(tm.tm_mday);
				BIN_TO_BCD(tm.tm_hour);
				BIN_TO_BCD(tm.tm_min);
				BIN_TO_BCD(tm.tm_sec);
				tm.tm_mon |= century;
				
				rtc_write(RTC_YEAR, tm.tm_year);
				rtc_write(RTC_MONTH, tm.tm_mon);
				rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday);
				rtc_write(RTC_HOURS, tm.tm_hour);
				rtc_write(RTC_MINUTES, tm.tm_min);
				rtc_write(RTC_SECONDS, tm.tm_sec);

				return 0;
#endif /* !CONFIG_ETRAX_RTC_READONLY */
			}

		case RTC_VLOW_RD:
		{
			int vl_bit = 0;

			if (rtc_read(RTC_SECONDS) & 0x80) {
				vl_bit = 1;
				printk(KERN_WARNING "%s: RTC Voltage Low - reliable "
				       "date/time information is no longer guaranteed!\n",
				       PCF8563_NAME);
			}
			if (copy_to_user((int *) arg, &vl_bit, sizeof(int)))
				return -EFAULT;

			return 0;
		}

		case RTC_VLOW_SET:
		{
			/* Clear the VL bit in the seconds register */
			int ret = rtc_read(RTC_SECONDS);

			rtc_write(RTC_SECONDS, (ret & 0x7F));

			return 0;
		}

		default:
				return -ENOTTY;
	}

	return 0;
}
Exemplo n.º 25
0
int __init
pcf8563_init(void)
{
	static int res;
	static int first = 1;

	if (!first)
		return res;
	first = 0;

	/* Initiate the i2c protocol. */
	res = i2c_init();
	if (res < 0) {
		printk(KERN_CRIT "pcf8563_init: Failed to init i2c.\n");
		return res;
	}

	/*
	 * First of all we need to reset the chip. This is done by
	 * clearing control1, control2 and clk freq and resetting
	 * all alarms.
	 */
	if (rtc_write(RTC_CONTROL1, 0x00) < 0)
		goto err;

	if (rtc_write(RTC_CONTROL2, 0x00) < 0)
		goto err;

	if (rtc_write(RTC_CLOCKOUT_FREQ, 0x00) < 0)
		goto err;

	if (rtc_write(RTC_TIMER_CONTROL, 0x03) < 0)
		goto err;

	/* Reset the alarms. */
	if (rtc_write(RTC_MINUTE_ALARM, 0x80) < 0)
		goto err;

	if (rtc_write(RTC_HOUR_ALARM, 0x80) < 0)
		goto err;

	if (rtc_write(RTC_DAY_ALARM, 0x80) < 0)
		goto err;

	if (rtc_write(RTC_WEEKDAY_ALARM, 0x80) < 0)
		goto err;

	/* Check for low voltage, and warn about it. */
	if (rtc_read(RTC_SECONDS) & 0x80) {
		voltage_low = 1;
		printk(KERN_WARNING "%s: RTC Voltage Low - reliable "
		       "date/time information is no longer guaranteed!\n",
		       PCF8563_NAME);
	}

	return res;

err:
	printk(KERN_INFO "%s: Error initializing chip.\n", PCF8563_NAME);
	res = -1;
	return res;
}
Exemplo n.º 26
0
 static void
rtc_enable_update(void)
{
	rtc_write((rtc_read(RTC_CMD) | RTC_TE), RTC_CMD);
}
Exemplo n.º 27
0
/*
 * ioctl calls for this driver. Why return -ENOTTY upon error? Because
 * POSIX says so!
 */
static int pcf8563_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	/* Some sanity checks. */
	if (_IOC_TYPE(cmd) != RTC_MAGIC)
		return -ENOTTY;

	if (_IOC_NR(cmd) > RTC_MAX_IOCTL)
		return -ENOTTY;

	switch (cmd) {
	case RTC_RD_TIME:
	{
		struct rtc_time tm;

		mutex_lock(&rtc_lock);
		memset(&tm, 0, sizeof tm);
		get_rtc_time(&tm);

		if (copy_to_user((struct rtc_time *) arg, &tm,
				 sizeof tm)) {
			mutex_unlock(&rtc_lock);
			return -EFAULT;
		}

		mutex_unlock(&rtc_lock);

		return 0;
	}
	case RTC_SET_TIME:
	{
		int leap;
		int year;
		int century;
		struct rtc_time tm;

		memset(&tm, 0, sizeof tm);
		if (!capable(CAP_SYS_TIME))
			return -EPERM;

		if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof tm))
			return -EFAULT;

		/* Convert from struct tm to struct rtc_time. */
		tm.tm_year += 1900;
		tm.tm_mon += 1;

		/*
		 * Check if tm.tm_year is a leap year. A year is a leap
		 * year if it is divisible by 4 but not 100, except
		 * that years divisible by 400 _are_ leap years.
		 */
		year = tm.tm_year;
		leap = (tm.tm_mon == 2) &&
			((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);

		/* Perform some sanity checks. */
		if ((tm.tm_year < 1970) ||
		    (tm.tm_mon > 12) ||
		    (tm.tm_mday == 0) ||
		    (tm.tm_mday > days_in_month[tm.tm_mon] + leap) ||
		    (tm.tm_wday >= 7) ||
		    (tm.tm_hour >= 24) ||
		    (tm.tm_min >= 60) ||
		    (tm.tm_sec >= 60))
			return -EINVAL;

		century = (tm.tm_year >= 2000) ? 0x80 : 0;
		tm.tm_year = tm.tm_year % 100;

		tm.tm_year = bin2bcd(tm.tm_year);
		tm.tm_mon = bin2bcd(tm.tm_mon);
		tm.tm_mday = bin2bcd(tm.tm_mday);
		tm.tm_hour = bin2bcd(tm.tm_hour);
		tm.tm_min = bin2bcd(tm.tm_min);
		tm.tm_sec = bin2bcd(tm.tm_sec);
		tm.tm_mon |= century;

		mutex_lock(&rtc_lock);

		rtc_write(RTC_YEAR, tm.tm_year);
		rtc_write(RTC_MONTH, tm.tm_mon);
		rtc_write(RTC_WEEKDAY, tm.tm_wday); /* Not coded in BCD. */
		rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday);
		rtc_write(RTC_HOURS, tm.tm_hour);
		rtc_write(RTC_MINUTES, tm.tm_min);
		rtc_write(RTC_SECONDS, tm.tm_sec);

		mutex_unlock(&rtc_lock);

		return 0;
	}
	case RTC_VL_READ:
		if (voltage_low) {
			printk(KERN_ERR "%s: RTC Voltage Low - "
			       "reliable date/time information is no "
			       "longer guaranteed!\n", PCF8563_NAME);
		}

		if (copy_to_user((int *) arg, &voltage_low, sizeof(int)))
			return -EFAULT;
		return 0;

	case RTC_VL_CLR:
	{
		/* Clear the VL bit in the seconds register in case
		 * the time has not been set already (which would
		 * have cleared it). This does not really matter
		 * because of the cached voltage_low value but do it
		 * anyway for consistency. */

		int ret = rtc_read(RTC_SECONDS);

		rtc_write(RTC_SECONDS, (ret & 0x7F));

		/* Clear the cached value. */
		voltage_low = 0;

		return 0;
	}
	default:
		return -ENOTTY;
	}

	return 0;
}
Exemplo n.º 28
0
static int ds1511_rtc_probe(struct platform_device *pdev)
{
	struct rtc_device *rtc;
	struct resource *res;
	struct rtc_plat_data *pdata;
	int ret = 0;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		return -ENODEV;
	}
	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
	if (!pdata)
		return -ENOMEM;
	pdata->size = resource_size(res);
	if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size,
			pdev->name))
		return -EBUSY;
	ds1511_base = devm_ioremap(&pdev->dev, res->start, pdata->size);
	if (!ds1511_base)
		return -ENOMEM;
	pdata->ioaddr = ds1511_base;
	pdata->irq = platform_get_irq(pdev, 0);

	/*
	 * turn on the clock and the crystal, etc.
	 */
	rtc_write(0, RTC_CMD);
	rtc_write(0, RTC_CMD1);
	/*
	 * clear the wdog counter
	 */
	rtc_write(0, DS1511_WD_MSEC);
	rtc_write(0, DS1511_WD_SEC);
	/*
	 * start the clock
	 */
	rtc_enable_update();

	/*
	 * check for a dying bat-tree
	 */
	if (rtc_read(RTC_CMD1) & DS1511_BLF1) {
		dev_warn(&pdev->dev, "voltage-low detected.\n");
	}

	spin_lock_init(&pdata->lock);
	platform_set_drvdata(pdev, pdata);
	/*
	 * if the platform has an interrupt in mind for this device,
	 * then by all means, set it
	 */
	if (pdata->irq > 0) {
		rtc_read(RTC_CMD1);
		if (devm_request_irq(&pdev->dev, pdata->irq, ds1511_interrupt,
			IRQF_SHARED, pdev->name, pdev) < 0) {

			dev_warn(&pdev->dev, "interrupt not available.\n");
			pdata->irq = 0;
		}
	}

	rtc = rtc_device_register(pdev->name, &pdev->dev, &ds1511_rtc_ops,
		THIS_MODULE);
	if (IS_ERR(rtc))
		return PTR_ERR(rtc);
	pdata->rtc = rtc;

	ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr);
	if (ret)
		rtc_device_unregister(pdata->rtc);
	return ret;
}
Exemplo n.º 29
0
int rtc_get (struct rtc_time *tmp)
{
	uchar sec, min, hour, mday, wday, mon, year;

	/* check if rtc is available for access */
	while( rtc_read(RTC_CONTROL_A) & RTC_CA_UIP)
		;

	sec  = rtc_read(RTC_SECONDS);
	min  = rtc_read(RTC_MINUTES);
	hour = rtc_read(RTC_HOURS);
	mday = rtc_read(RTC_DATE_OF_MONTH);
	wday = rtc_read(RTC_DAY_OF_WEEK);
	mon  = rtc_read(RTC_MONTH);
	year = rtc_read(RTC_YEAR);

#ifdef RTC_DEBUG
	printf( "Get RTC year: %d; mon: %d; mday: %d; wday: %d; "
		"hr: %d; min: %d; sec: %d\n",
		year, mon, mday, wday, hour, min, sec );

	printf ( "Alarms: hour: %02x min: %02x sec: %02x\n",
		 rtc_read (RTC_HOURS_ALARM),
		 rtc_read (RTC_MINUTES_ALARM),
		 rtc_read (RTC_SECONDS_ALARM) );
#endif

	if( !(rtc_read(RTC_CONTROL_B) & RTC_CB_DM))
	{	    /* Information is in BCD format */
printf(" Get: Convert BSD to BIN\n");
		tmp->tm_sec  = bcd2bin (sec  & 0x7F);
		tmp->tm_min  = bcd2bin (min  & 0x7F);
		tmp->tm_hour = bcd2bin (hour & 0x3F);
		tmp->tm_mday = bcd2bin (mday & 0x3F);
		tmp->tm_mon  = bcd2bin (mon & 0x1F);
		tmp->tm_year = bcd2bin (year);
		tmp->tm_wday = bcd2bin (wday & 0x07);
	}
else
	{
		tmp->tm_sec  = sec  & 0x7F;
		tmp->tm_min  = min  & 0x7F;
		tmp->tm_hour = hour & 0x3F;
		tmp->tm_mday = mday & 0x3F;
		tmp->tm_mon  = mon & 0x1F;
		tmp->tm_year = year;
		tmp->tm_wday = wday & 0x07;
	}


	if(tmp->tm_year<70)
		tmp->tm_year+=2000;
	else
		tmp->tm_year+=1900;

	tmp->tm_yday = 0;
	tmp->tm_isdst= 0;
#ifdef RTC_DEBUG
	printf ( "Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
		tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
		tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
#endif

	return 0;
}
Exemplo n.º 30
0
satime_t
getsecs(void)
{
	uint32_t sec, min, hour, day;
#if 0
	uint32_t mon, year;
#endif
	satime_t secs;

	sec = rtc_read(RS5C313_SEC1);
	sec += rtc_read(RS5C313_SEC10) * 10;
	min = rtc_read(RS5C313_MIN1);
	min += rtc_read(RS5C313_MIN10) * 10;
	hour = rtc_read(RS5C313_HOUR1);
	hour += rtc_read(RS5C313_HOUR10) * 10;
	day = rtc_read(RS5C313_DAY1);
	day += rtc_read(RS5C313_DAY10) * 10;
#if 0
	mon = rtc_read(RS5C313_MON1);
	mon += rtc_read(RS5C313_MON10) * 10;
	year = rtc_read(RS5C313_YEAR1);
	year += rtc_read(RS5C313_YEAR10) * 10;
#endif

	secs = sec;
	secs += min * 60;
	secs += hour * 60 * 60;
	secs += day * 60 * 60 * 24;
#if 0
	/* XXX mon, year */
#endif

#if defined(DEBUG)
	printf("getsecs: secs = %d\n", (uint32_t)secs);
#endif

	return secs;
}