static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)
{
	struct i2c_client	*client = to_i2c_client(dev);
	struct rs5c372		*rs5c = i2c_get_clientdata(client);
	int			status, addr, i;
	unsigned char		buf[3];

	
	if (t->time.tm_mday != -1
			|| t->time.tm_mon != -1
			|| t->time.tm_year != -1)
		return -EINVAL;

	

	
	status = rs5c_get_regs(rs5c);
	if (status < 0)
		return status;
	if (rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE) {
		addr = RS5C_ADDR(RS5C_REG_CTRL1);
		buf[0] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE;
		if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) {
			pr_debug("%s: can't disable alarm\n", rs5c->rtc->name);
			return -EIO;
		}
		rs5c->regs[RS5C_REG_CTRL1] = buf[0];
	}

	
	buf[0] = bin2bcd(t->time.tm_min);
	buf[1] = rs5c_hr2reg(rs5c, t->time.tm_hour);
	buf[2] = 0x7f;	

	for (i = 0; i < sizeof(buf); i++) {
		addr = RS5C_ADDR(RS5C_REG_ALARM_A_MIN + i);
		if (i2c_smbus_write_byte_data(client, addr, buf[i]) < 0) {
			pr_debug("%s: can't set alarm time\n", rs5c->rtc->name);
			return -EIO;
		}
	}

	
	if (t->enabled) {
		addr = RS5C_ADDR(RS5C_REG_CTRL1);
		buf[0] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE;
		if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0)
			printk(KERN_WARNING "%s: can't enable alarm\n",
				rs5c->rtc->name);
		rs5c->regs[RS5C_REG_CTRL1] = buf[0];
	}

	return 0;
}
Exemple #2
0
static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)
{
	struct i2c_client	*client = to_i2c_client(dev);
	struct rs5c372		*rs5c = i2c_get_clientdata(client);
	int			status, addr, i;
	unsigned char		buf[3];

	/* only handle up to 24 hours in the future, like RTC_ALM_SET */
	if (t->time.tm_mday != -1
			|| t->time.tm_mon != -1
			|| t->time.tm_year != -1)
		return -EINVAL;

	/* REVISIT: round up tm_sec */

	/* if needed, disable irq (clears pending status) */
	status = rs5c_get_regs(rs5c);
	if (status < 0)
		return status;
	if (rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE) {
		addr = RS5C_ADDR(RS5C_REG_CTRL1);
		buf[0] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE;
		if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) {
			pr_debug("%s: can't disable alarm\n", rs5c->rtc->name);
			return -EIO;
		}
		rs5c->regs[RS5C_REG_CTRL1] = buf[0];
	}

	/* set alarm */
	buf[0] = bin2bcd(t->time.tm_min);
	buf[1] = rs5c_hr2reg(rs5c, t->time.tm_hour);
	buf[2] = 0x7f;	/* any/all days */

	for (i = 0; i < sizeof(buf); i++) {
		addr = RS5C_ADDR(RS5C_REG_ALARM_A_MIN + i);
		if (i2c_smbus_write_byte_data(client, addr, buf[i]) < 0) {
			pr_debug("%s: can't set alarm time\n", rs5c->rtc->name);
			return -EIO;
		}
	}

	/* ... and maybe enable its irq */
	if (t->enabled) {
		addr = RS5C_ADDR(RS5C_REG_CTRL1);
		buf[0] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE;
		if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0)
			printk(KERN_WARNING "%s: can't enable alarm\n",
				rs5c->rtc->name);
		rs5c->regs[RS5C_REG_CTRL1] = buf[0];
	}

	return 0;
}
Exemple #3
0
static int rs5c_oscillator_setup(struct rs5c372 *rs5c372)
{
	unsigned char buf[2];
	int addr, i, ret = 0;

	if (rs5c372->type == rtc_r2025sd) {
		if (!(rs5c372->regs[RS5C_REG_CTRL2] & R2025_CTRL2_XST))
			return ret;
		rs5c372->regs[RS5C_REG_CTRL2] &= ~R2025_CTRL2_XST;
	} else {
		if (!(rs5c372->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_XSTP))
			return ret;
		rs5c372->regs[RS5C_REG_CTRL2] &= ~RS5C_CTRL2_XSTP;
	}

	addr   = RS5C_ADDR(RS5C_REG_CTRL1);
	buf[0] = rs5c372->regs[RS5C_REG_CTRL1];
	buf[1] = rs5c372->regs[RS5C_REG_CTRL2];

	/* use 24hr mode */
	switch (rs5c372->type) {
	case rtc_rs5c372a:
	case rtc_rs5c372b:
		buf[1] |= RS5C372_CTRL2_24;
		rs5c372->time24 = 1;
		break;
	case rtc_r2025sd:
	case rtc_rv5c386:
	case rtc_rv5c387a:
		buf[0] |= RV5C387_CTRL1_24;
		rs5c372->time24 = 1;
		break;
	default:
		/* impossible */
		break;
	}

	for (i = 0; i < sizeof(buf); i++) {
		addr = RS5C_ADDR(RS5C_REG_CTRL1 + i);
		ret = i2c_smbus_write_byte_data(rs5c372->client, addr, buf[i]);
		if (unlikely(ret < 0))
			return ret;
	}

	rs5c372->regs[RS5C_REG_CTRL1] = buf[0];
	rs5c372->regs[RS5C_REG_CTRL2] = buf[1];

	return 0;
}
Exemple #4
0
static int rs5c_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
	struct i2c_client	*client = to_i2c_client(dev);
	struct rs5c372		*rs5c = i2c_get_clientdata(client);
	unsigned char		buf;
	int			status, addr;

	buf = rs5c->regs[RS5C_REG_CTRL1];

	if (!rs5c->has_irq)
		return -EINVAL;

	status = rs5c_get_regs(rs5c);
	if (status < 0)
		return status;

	addr = RS5C_ADDR(RS5C_REG_CTRL1);
	if (enabled)
		buf |= RS5C_CTRL1_AALE;
	else
		buf &= ~RS5C_CTRL1_AALE;

	if (i2c_smbus_write_byte_data(client, addr, buf) < 0) {
		printk(KERN_WARNING "%s: can't update alarm\n",
			rs5c->rtc->name);
		status = -EIO;
	} else
		rs5c->regs[RS5C_REG_CTRL1] = buf;

	return status;
}
Exemple #5
0
static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{
	struct rs5c372	*rs5c = i2c_get_clientdata(client);
	unsigned char	buf[7];
	int		addr;

	dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d "
		"mday=%d, mon=%d, year=%d, wday=%d\n",
		__func__,
		tm->tm_sec, tm->tm_min, tm->tm_hour,
		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);

	addr   = RS5C_ADDR(RS5C372_REG_SECS);
	buf[0] = bin2bcd(tm->tm_sec);
	buf[1] = bin2bcd(tm->tm_min);
	buf[2] = rs5c_hr2reg(rs5c, tm->tm_hour);
	buf[3] = bin2bcd(tm->tm_wday);
	buf[4] = bin2bcd(tm->tm_mday);
	buf[5] = bin2bcd(tm->tm_mon + 1);
	buf[6] = bin2bcd(tm->tm_year - 100);

	if (i2c_smbus_write_i2c_block_data(client, addr, sizeof(buf), buf) < 0) {
		dev_err(&client->dev, "%s: write error\n", __func__);
		return -EIO;
	}

	return 0;
}
Exemple #6
0
static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{
	struct rs5c372	*rs5c = i2c_get_clientdata(client);
	unsigned char	buf[8];

	dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d "
		"mday=%d, mon=%d, year=%d, wday=%d\n",
		__FUNCTION__,
		tm->tm_sec, tm->tm_min, tm->tm_hour,
		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);

	buf[0] = RS5C_ADDR(RS5C372_REG_SECS);
	buf[1] = BIN2BCD(tm->tm_sec);
	buf[2] = BIN2BCD(tm->tm_min);
	buf[3] = rs5c_hr2reg(rs5c, tm->tm_hour);
	buf[4] = BIN2BCD(tm->tm_wday);
	buf[5] = BIN2BCD(tm->tm_mday);
	buf[6] = BIN2BCD(tm->tm_mon + 1);
	buf[7] = BIN2BCD(tm->tm_year - 100);

	if ((i2c_master_send(client, buf, 8)) != 8) {
		dev_err(&client->dev, "%s: write error\n", __FUNCTION__);
		return -EIO;
	}

	return 0;
}
static int rs5c_get_regs(struct rs5c372 *rs5c)
{
	struct i2c_client	*client = rs5c->client;
	struct i2c_msg		msgs[] = {
		{ client->addr, I2C_M_RD, sizeof rs5c->buf, rs5c->buf },
	};

	if (rs5c->smbus) {
		int addr = RS5C_ADDR(RS5C372_REG_SECS);
		int size = sizeof(rs5c->buf) - 1;

		if (i2c_smbus_read_i2c_block_data(client, addr, size,
						  rs5c->buf + 1) != size) {
			dev_warn(&client->dev, "can't read registers\n");
			return -EIO;
		}
	} else {
		if ((i2c_transfer(client->adapter, msgs, 1)) != 1) {
			dev_warn(&client->dev, "can't read registers\n");
			return -EIO;
		}
	}

	dev_dbg(&client->dev,
		"%02x %02x %02x (%02x) %02x %02x %02x (%02x), "
		"%02x %02x %02x, %02x %02x %02x; %02x %02x\n",
		rs5c->regs[0],  rs5c->regs[1],  rs5c->regs[2],  rs5c->regs[3],
		rs5c->regs[4],  rs5c->regs[5],  rs5c->regs[6],  rs5c->regs[7],
		rs5c->regs[8],  rs5c->regs[9],  rs5c->regs[10], rs5c->regs[11],
		rs5c->regs[12], rs5c->regs[13], rs5c->regs[14], rs5c->regs[15]);

	return 0;
}
static int
rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
	struct i2c_client	*client = to_i2c_client(dev);
	struct rs5c372		*rs5c = i2c_get_clientdata(client);
	unsigned char		buf;
	int			status, addr;

	buf = rs5c->regs[RS5C_REG_CTRL1];
	switch (cmd) {
	case RTC_UIE_OFF:
	case RTC_UIE_ON:
		/* some 327a modes use a different IRQ pin for 1Hz irqs */
		if (rs5c->type == rtc_rs5c372a
				&& (buf & RS5C372A_CTRL1_SL1))
			return -ENOIOCTLCMD;
	case RTC_AIE_OFF:
	case RTC_AIE_ON:
		/* these irq management calls only make sense for chips
		 * which are wired up to an IRQ.
		 */
		if (!rs5c->has_irq)
			return -ENOIOCTLCMD;
		break;
	default:
		return -ENOIOCTLCMD;
	}

	status = rs5c_get_regs(rs5c);
	if (status < 0)
		return status;

	addr = RS5C_ADDR(RS5C_REG_CTRL1);
	switch (cmd) {
	case RTC_AIE_OFF:	/* alarm off */
		buf &= ~RS5C_CTRL1_AALE;
		break;
	case RTC_AIE_ON:	/* alarm on */
		buf |= RS5C_CTRL1_AALE;
		break;
	case RTC_UIE_OFF:	/* update off */
		buf &= ~RS5C_CTRL1_CT_MASK;
		break;
	case RTC_UIE_ON:	/* update on */
		buf &= ~RS5C_CTRL1_CT_MASK;
		buf |= RS5C_CTRL1_CT4;
		break;
	}

	if (i2c_smbus_write_byte_data(client, addr, buf) < 0) {
		printk(KERN_WARNING "%s: can't update alarm\n",
			rs5c->rtc->name);
		status = -EIO;
	} else
		rs5c->regs[RS5C_REG_CTRL1] = buf;

	return status;
}
Exemple #9
0
static int
rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
	struct i2c_client	*client = to_i2c_client(dev);
	struct rs5c372		*rs5c = i2c_get_clientdata(client);
	unsigned char		buf;
	int			status, addr;

	buf = rs5c->regs[RS5C_REG_CTRL1];
	switch (cmd) {
	case RTC_UIE_OFF:
	case RTC_UIE_ON:
		
		if (rs5c->type == rtc_rs5c372a
				&& (buf & RS5C372A_CTRL1_SL1))
			return -ENOIOCTLCMD;
	case RTC_AIE_OFF:
	case RTC_AIE_ON:
		
		if (!rs5c->has_irq)
			return -ENOIOCTLCMD;
		break;
	default:
		return -ENOIOCTLCMD;
	}

	status = rs5c_get_regs(rs5c);
	if (status < 0)
		return status;

	addr = RS5C_ADDR(RS5C_REG_CTRL1);
	switch (cmd) {
	case RTC_AIE_OFF:	
		buf &= ~RS5C_CTRL1_AALE;
		break;
	case RTC_AIE_ON:	
		buf |= RS5C_CTRL1_AALE;
		break;
	case RTC_UIE_OFF:	
		buf &= ~RS5C_CTRL1_CT_MASK;
		break;
	case RTC_UIE_ON:	
		buf &= ~RS5C_CTRL1_CT_MASK;
		buf |= RS5C_CTRL1_CT4;
		break;
	}

	if (i2c_smbus_write_byte_data(client, addr, buf) < 0) {
		printk(KERN_WARNING "%s: can't update alarm\n",
			rs5c->rtc->name);
		status = -EIO;
	} else
		rs5c->regs[RS5C_REG_CTRL1] = buf;

	return status;
}
Exemple #10
0
static int rs5c_get_regs(struct rs5c372 *rs5c)
{
	struct i2c_client	*client = rs5c->client;
	struct i2c_msg		msgs[] = {
		{ client->addr, I2C_M_RD, sizeof rs5c->buf, rs5c->buf },
	};

	/* This implements the third reading method from the datasheet, using
	 * an internal address that's reset after each transaction (by STOP)
	 * to 0x0f ... so we read extra registers, and skip the first one.
	 *
	 * The first method doesn't work with the iop3xx adapter driver, on at
	 * least 80219 chips; this works around that bug.
	 *
	 * The third method on the other hand doesn't work for the SMBus-only
	 * configurations, so we use the the first method there, stripping off
	 * the extra register in the process.
	 */
	if (rs5c->smbus) {
		int addr = RS5C_ADDR(RS5C372_REG_SECS);
		int size = sizeof(rs5c->buf) - 1;

		if (i2c_smbus_read_i2c_block_data(client, addr, size,
						  rs5c->buf + 1) != size) {
			dev_warn(&client->dev, "can't read registers\n");
			return -EIO;
		}
	} else {
		if ((i2c_transfer(client->adapter, msgs, 1)) != 1) {
			dev_warn(&client->dev, "can't read registers\n");
			return -EIO;
		}
	}

	dev_dbg(&client->dev,
		"%02x %02x %02x (%02x) %02x %02x %02x (%02x), "
		"%02x %02x %02x, %02x %02x %02x; %02x %02x\n",
		rs5c->regs[0],  rs5c->regs[1],  rs5c->regs[2],  rs5c->regs[3],
		rs5c->regs[4],  rs5c->regs[5],  rs5c->regs[6],  rs5c->regs[7],
		rs5c->regs[8],  rs5c->regs[9],  rs5c->regs[10], rs5c->regs[11],
		rs5c->regs[12], rs5c->regs[13], rs5c->regs[14], rs5c->regs[15]);

	return 0;
}
Exemple #11
0
static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
{
	int err = 0;
	struct i2c_client *client;
	struct rs5c372 *rs5c372;
	struct rtc_time tm;

	dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__);

	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
		err = -ENODEV;
		goto exit;
	}

	if (!(rs5c372 = kzalloc(sizeof(struct rs5c372), GFP_KERNEL))) {
		err = -ENOMEM;
		goto exit;
	}

	/* we read registers 0x0f then 0x00-0x0f; skip the first one */
	rs5c372->regs=&rs5c372->buf[1];

	/* On conversion to a "new style" i2c driver, we'll be handed
	 * the i2c_client (we won't create it)
	 */
	client = &rs5c372->dev;
	rs5c372->client = client;

	/* I2C client */
	client->addr = address;
	client->driver = &rs5c372_driver;
	client->adapter = adapter;

	strlcpy(client->name, rs5c372_driver.driver.name, I2C_NAME_SIZE);

	i2c_set_clientdata(client, rs5c372);

	/* Inform the i2c layer */
	if ((err = i2c_attach_client(client)))
		goto exit_kfree;

	err = rs5c_get_regs(rs5c372);
	if (err < 0)
		goto exit_detach;

	/* For "new style" drivers, irq is in i2c_client and chip type
	 * info comes from i2c_client.dev.platform_data.  Meanwhile:
	 *
	 * STICK BOARD-SPECIFIC SETUP CODE RIGHT HERE
	 */
	if (rs5c372->type == rtc_undef) {
		rs5c372->type = rtc_rs5c372b;
		dev_warn(&client->dev, "assuming rs5c372b\n");
	}

	/* clock may be set for am/pm or 24 hr time */
	switch (rs5c372->type) {
	case rtc_rs5c372a:
	case rtc_rs5c372b:
		/* alarm uses ALARM_A; and nINTRA on 372a, nINTR on 372b.
		 * so does periodic irq, except some 327a modes.
		 */
		if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C372_CTRL2_24)
			rs5c372->time24 = 1;
		break;
	case rtc_rv5c386:
	case rtc_rv5c387a:
		if (rs5c372->regs[RS5C_REG_CTRL1] & RV5C387_CTRL1_24)
			rs5c372->time24 = 1;
		/* alarm uses ALARM_W; and nINTRB for alarm and periodic
		 * irq, on both 386 and 387
		 */
		break;
	default:
		dev_err(&client->dev, "unknown RTC type\n");
		goto exit_detach;
	}

	/* if the oscillator lost power and no other software (like
	 * the bootloader) set it up, do it here.
	 */
	if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_XSTP) {
		unsigned char buf[3];

		rs5c372->regs[RS5C_REG_CTRL2] &= ~RS5C_CTRL2_XSTP;

		buf[0] = RS5C_ADDR(RS5C_REG_CTRL1);
		buf[1] = rs5c372->regs[RS5C_REG_CTRL1];
		buf[2] = rs5c372->regs[RS5C_REG_CTRL2];

		/* use 24hr mode */
		switch (rs5c372->type) {
		case rtc_rs5c372a:
		case rtc_rs5c372b:
			buf[2] |= RS5C372_CTRL2_24;
			rs5c372->time24 = 1;
			break;
		case rtc_rv5c386:
		case rtc_rv5c387a:
			buf[1] |= RV5C387_CTRL1_24;
			rs5c372->time24 = 1;
			break;
		default:
			/* impossible */
			break;
		}

		if ((i2c_master_send(client, buf, 3)) != 3) {
			dev_err(&client->dev, "setup error\n");
			goto exit_detach;
		}
		rs5c372->regs[RS5C_REG_CTRL1] = buf[1];
		rs5c372->regs[RS5C_REG_CTRL2] = buf[2];
	}

	if (rs5c372_get_datetime(client, &tm) < 0)
		dev_warn(&client->dev, "clock needs to be set\n");

	dev_info(&client->dev, "%s found, %s, driver version " DRV_VERSION "\n",
			({ char *s; switch (rs5c372->type) {
			case rtc_rs5c372a:	s = "rs5c372a"; break;
			case rtc_rs5c372b:	s = "rs5c372b"; break;
			case rtc_rv5c386:	s = "rv5c386"; break;
			case rtc_rv5c387a:	s = "rv5c387a"; break;
			default:		s = "chip"; break;
			}; s;}),
static int rs5c372_probe(struct i2c_client *client,
			 const struct i2c_device_id *id)
{
	int err = 0;
	struct rs5c372 *rs5c372;
	struct rtc_time tm;

	dev_dbg(&client->dev, "%s\n", __func__);

	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		err = -ENODEV;
		goto exit;
	}

	if (!(rs5c372 = kzalloc(sizeof(struct rs5c372), GFP_KERNEL))) {
		err = -ENOMEM;
		goto exit;
	}

	rs5c372->client = client;
	i2c_set_clientdata(client, rs5c372);
	rs5c372->type = id->driver_data;

	/* we read registers 0x0f then 0x00-0x0f; skip the first one */
	rs5c372->regs = &rs5c372->buf[1];

	err = rs5c_get_regs(rs5c372);
	if (err < 0)
		goto exit_kfree;

	/* clock may be set for am/pm or 24 hr time */
	switch (rs5c372->type) {
	case rtc_rs5c372a:
	case rtc_rs5c372b:
		/* alarm uses ALARM_A; and nINTRA on 372a, nINTR on 372b.
		 * so does periodic irq, except some 327a modes.
		 */
		if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C372_CTRL2_24)
			rs5c372->time24 = 1;
		break;
	case rtc_rv5c386:
	case rtc_rv5c387a:
		if (rs5c372->regs[RS5C_REG_CTRL1] & RV5C387_CTRL1_24)
			rs5c372->time24 = 1;
		/* alarm uses ALARM_W; and nINTRB for alarm and periodic
		 * irq, on both 386 and 387
		 */
		break;
	default:
		dev_err(&client->dev, "unknown RTC type\n");
		goto exit_kfree;
	}

	/* if the oscillator lost power and no other software (like
	 * the bootloader) set it up, do it here.
	 */
	if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_XSTP) {
		unsigned char buf[3];

		rs5c372->regs[RS5C_REG_CTRL2] &= ~RS5C_CTRL2_XSTP;

		buf[0] = RS5C_ADDR(RS5C_REG_CTRL1);
		buf[1] = rs5c372->regs[RS5C_REG_CTRL1];
		buf[2] = rs5c372->regs[RS5C_REG_CTRL2];

		/* use 24hr mode */
		switch (rs5c372->type) {
		case rtc_rs5c372a:
		case rtc_rs5c372b:
			buf[2] |= RS5C372_CTRL2_24;
			rs5c372->time24 = 1;
			break;
		case rtc_rv5c386:
		case rtc_rv5c387a:
			buf[1] |= RV5C387_CTRL1_24;
			rs5c372->time24 = 1;
			break;
		default:
			/* impossible */
			break;
		}

		if ((i2c_master_send(client, buf, 3)) != 3) {
			dev_err(&client->dev, "setup error\n");
			goto exit_kfree;
		}
		rs5c372->regs[RS5C_REG_CTRL1] = buf[1];
		rs5c372->regs[RS5C_REG_CTRL2] = buf[2];
	}

	if (rs5c372_get_datetime(client, &tm) < 0)
		dev_warn(&client->dev, "clock needs to be set\n");

	dev_info(&client->dev, "%s found, %s, driver version " DRV_VERSION "\n",
			({ char *s; switch (rs5c372->type) {
			case rtc_rs5c372a:	s = "rs5c372a"; break;
			case rtc_rs5c372b:	s = "rs5c372b"; break;
			case rtc_rv5c386:	s = "rv5c386"; break;
			case rtc_rv5c387a:	s = "rv5c387a"; break;
			default:		s = "chip"; break;
			}; s;}),