Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c38dec71 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull RTC updates from Alexandre Belloni:
 "Core:
   - fix module reference count in rtc-proc
   - Replace simple_strtoul by kstrtoul

  New driver:
   - Epson RX8010SJ

  Subsystem wide cleanups:
   - use %ph for short hex dumps
   - constify *_chip_ops structures

  Drivers:
   - abx80x: Microcrystal rv1805 support, alarm support
   - cmos: prevent kernel warning on IRQ flags mismatch
   - s5m: various cleanups
   - rv8803: rx8900 compatibility, small error path fix
   - sunxi: various cleanups
   - lpc32xx: remove irq > NR_IRQS check from probe()
   - imxdi: fix spelling mistake in warning message
   - ds1685: don't try to micromanage sysfs output size
   - da9063: avoid writing undefined data to rtc
   - gemini: Remove unnecessary platform_set_drvdata()
   - efi: add efi_procfs in efi_rtc_ops
   - pcf8523: refuse to write dates later than 2099"

* tag 'rtc-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (24 commits)
  rtc: cmos: prevent kernel warning on IRQ flags mismatch
  rtc: rtc-ds2404: constify ds2404_chip_ops structures
  rtc: s5m: Make register configuration per S2MPS device to remove exceptions
  rtc: s5m: Add separate field for storing auto-cleared mask in register config
  rtc: s5m: Cleanup by removing useless 'rtc' prefix from fields
  rtc: Replace simple_strtoul by kstrtoul
  rtc: abx80x: add alarm support
  rtc: abx80x: Add Microcrystal rv1805 support
  rtc: v3020: constify v3020_chip_ops structures
  rtc: rv8803: Extend compatibility with the rx8900
  rtc: rv8803: fix handling return value of i2c_smbus_read_byte_data
  rtc: Add Epson RX8010SJ RTC driver
  rtc: lpc32xx: remove irq > NR_IRQS check from probe()
  rtc: imxdi: fix spelling mistake in warning message
  rtc: ds1685: don't try to micromanage sysfs output size
  rtc: use %ph for short hex dumps
  rtc: da9063: avoid writing undefined data to rtc
  rtc: sunxi: use of_device_get_match_data
  rtc: sunxi: constify the data_year_param structure
  rtc: sunxi: fix signedness issues
  ...
parents d43fb9f3 079062b2
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -558,6 +558,16 @@ config RTC_DRV_FM3130
	  This driver can also be built as a module. If so the module
	  will be called rtc-fm3130.

config RTC_DRV_RX8010
	tristate "Epson RX8010SJ"
	depends on I2C
	help
	  If you say yes here you get support for the Epson RX8010SJ RTC
	  chip.

	  This driver can also be built as a module. If so, the module
	  will be called rtc-rx8010.

config RTC_DRV_RX8581
	tristate "Epson RX-8581"
	help
+1 −0
Original line number Diff line number Diff line
@@ -128,6 +128,7 @@ obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
obj-$(CONFIG_RTC_DRV_RV3029C2)	+= rtc-rv3029c2.o
obj-$(CONFIG_RTC_DRV_RV8803)	+= rtc-rv8803.o
obj-$(CONFIG_RTC_DRV_RX4581)	+= rtc-rx4581.o
obj-$(CONFIG_RTC_DRV_RX8010)	+= rtc-rx8010.o
obj-$(CONFIG_RTC_DRV_RX8025)	+= rtc-rx8025.o
obj-$(CONFIG_RTC_DRV_RX8581)	+= rtc-rx8581.o
obj-$(CONFIG_RTC_DRV_S35390A)	+= rtc-s35390a.o
+142 −4
Original line number Diff line number Diff line
@@ -27,10 +27,28 @@
#define ABX8XX_REG_YR		0x06
#define ABX8XX_REG_WD		0x07

#define ABX8XX_REG_AHTH		0x08
#define ABX8XX_REG_ASC		0x09
#define ABX8XX_REG_AMN		0x0a
#define ABX8XX_REG_AHR		0x0b
#define ABX8XX_REG_ADA		0x0c
#define ABX8XX_REG_AMO		0x0d
#define ABX8XX_REG_AWD		0x0e

#define ABX8XX_REG_STATUS	0x0f
#define ABX8XX_STATUS_AF	BIT(2)

#define ABX8XX_REG_CTRL1	0x10
#define ABX8XX_CTRL_WRITE	BIT(0)
#define ABX8XX_CTRL_ARST	BIT(2)
#define ABX8XX_CTRL_12_24	BIT(6)

#define ABX8XX_REG_IRQ		0x12
#define ABX8XX_IRQ_AIE		BIT(2)
#define ABX8XX_IRQ_IM_1_4	(0x3 << 5)

#define ABX8XX_REG_CD_TIMER_CTL	0x18

#define ABX8XX_REG_CFG_KEY	0x1f
#define ABX8XX_CFG_KEY_MISC	0x9d

@@ -63,8 +81,6 @@ static struct abx80x_cap abx80x_caps[] = {
	[ABX80X] = {.pn = 0}
};

static struct i2c_driver abx80x_driver;

static int abx80x_enable_trickle_charger(struct i2c_client *client,
					 u8 trickle_cfg)
{
@@ -148,9 +164,111 @@ static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
	return 0;
}

static irqreturn_t abx80x_handle_irq(int irq, void *dev_id)
{
	struct i2c_client *client = dev_id;
	struct rtc_device *rtc = i2c_get_clientdata(client);
	int status;

	status = i2c_smbus_read_byte_data(client, ABX8XX_REG_STATUS);
	if (status < 0)
		return IRQ_NONE;

	if (status & ABX8XX_STATUS_AF)
		rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF);

	i2c_smbus_write_byte_data(client, ABX8XX_REG_STATUS, 0);

	return IRQ_HANDLED;
}

static int abx80x_read_alarm(struct device *dev, struct rtc_wkalrm *t)
{
	struct i2c_client *client = to_i2c_client(dev);
	unsigned char buf[7];

	int irq_mask, err;

	if (client->irq <= 0)
		return -EINVAL;

	err = i2c_smbus_read_i2c_block_data(client, ABX8XX_REG_ASC,
					    sizeof(buf), buf);
	if (err)
		return err;

	irq_mask = i2c_smbus_read_byte_data(client, ABX8XX_REG_IRQ);
	if (irq_mask < 0)
		return irq_mask;

	t->time.tm_sec = bcd2bin(buf[0] & 0x7F);
	t->time.tm_min = bcd2bin(buf[1] & 0x7F);
	t->time.tm_hour = bcd2bin(buf[2] & 0x3F);
	t->time.tm_mday = bcd2bin(buf[3] & 0x3F);
	t->time.tm_mon = bcd2bin(buf[4] & 0x1F) - 1;
	t->time.tm_wday = buf[5] & 0x7;

	t->enabled = !!(irq_mask & ABX8XX_IRQ_AIE);
	t->pending = (buf[6] & ABX8XX_STATUS_AF) && t->enabled;

	return err;
}

static int abx80x_set_alarm(struct device *dev, struct rtc_wkalrm *t)
{
	struct i2c_client *client = to_i2c_client(dev);
	u8 alarm[6];
	int err;

	if (client->irq <= 0)
		return -EINVAL;

	alarm[0] = 0x0;
	alarm[1] = bin2bcd(t->time.tm_sec);
	alarm[2] = bin2bcd(t->time.tm_min);
	alarm[3] = bin2bcd(t->time.tm_hour);
	alarm[4] = bin2bcd(t->time.tm_mday);
	alarm[5] = bin2bcd(t->time.tm_mon + 1);

	err = i2c_smbus_write_i2c_block_data(client, ABX8XX_REG_AHTH,
					     sizeof(alarm), alarm);
	if (err < 0) {
		dev_err(&client->dev, "Unable to write alarm registers\n");
		return -EIO;
	}

	if (t->enabled) {
		err = i2c_smbus_write_byte_data(client, ABX8XX_REG_IRQ,
						(ABX8XX_IRQ_IM_1_4 |
						 ABX8XX_IRQ_AIE));
		if (err)
			return err;
	}

	return 0;
}

static int abx80x_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
	struct i2c_client *client = to_i2c_client(dev);
	int err;

	if (enabled)
		err = i2c_smbus_write_byte_data(client, ABX8XX_REG_IRQ,
						(ABX8XX_IRQ_IM_1_4 |
						 ABX8XX_IRQ_AIE));
	else
		err = i2c_smbus_write_byte_data(client, ABX8XX_REG_IRQ,
						ABX8XX_IRQ_IM_1_4);
	return err;
}

static const struct rtc_class_ops abx80x_rtc_ops = {
	.read_time	= abx80x_rtc_read_time,
	.set_time	= abx80x_rtc_set_time,
	.read_alarm	= abx80x_read_alarm,
	.set_alarm	= abx80x_set_alarm,
	.alarm_irq_enable = abx80x_alarm_irq_enable,
};

static int abx80x_dt_trickle_cfg(struct device_node *np)
@@ -225,7 +343,8 @@ static int abx80x_probe(struct i2c_client *client,
	}

	err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CTRL1,
					((data & ~ABX8XX_CTRL_12_24) |
					((data & ~(ABX8XX_CTRL_12_24 |
						   ABX8XX_CTRL_ARST)) |
					 ABX8XX_CTRL_WRITE));
	if (err < 0) {
		dev_err(&client->dev, "Unable to write control register\n");
@@ -260,7 +379,12 @@ static int abx80x_probe(struct i2c_client *client,
		abx80x_enable_trickle_charger(client, trickle_cfg);
	}

	rtc = devm_rtc_device_register(&client->dev, abx80x_driver.driver.name,
	err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CD_TIMER_CTL,
					BIT(2));
	if (err)
		return err;

	rtc = devm_rtc_device_register(&client->dev, "abx8xx",
				       &abx80x_rtc_ops, THIS_MODULE);

	if (IS_ERR(rtc))
@@ -268,6 +392,19 @@ static int abx80x_probe(struct i2c_client *client,

	i2c_set_clientdata(client, rtc);

	if (client->irq > 0) {
		dev_info(&client->dev, "IRQ %d supplied\n", client->irq);
		err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
						abx80x_handle_irq,
						IRQF_SHARED | IRQF_ONESHOT,
						"abx8xx",
						client);
		if (err) {
			dev_err(&client->dev, "unable to request IRQ, alarms disabled\n");
			client->irq = 0;
		}
	}

	return 0;
}

@@ -286,6 +423,7 @@ static const struct i2c_device_id abx80x_id[] = {
	{ "ab1803", AB1803 },
	{ "ab1804", AB1804 },
	{ "ab1805", AB1805 },
	{ "rv1805", AB1805 },
	{ }
};
MODULE_DEVICE_TABLE(i2c, abx80x_id);
+1 −1
Original line number Diff line number Diff line
@@ -725,7 +725,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
			rtc_cmos_int_handler = cmos_interrupt;

		retval = request_irq(rtc_irq, rtc_cmos_int_handler,
				0, dev_name(&cmos_rtc.rtc->dev),
				IRQF_SHARED, dev_name(&cmos_rtc.rtc->dev),
				cmos_rtc.rtc);
		if (retval < 0) {
			dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq);
+6 −17
Original line number Diff line number Diff line
@@ -191,24 +191,13 @@ static void da9063_tm_to_data(struct rtc_time *tm, u8 *data,
{
	const struct da9063_compatible_rtc_regmap *config = rtc->config;

	data[RTC_SEC] &= ~config->rtc_count_sec_mask;
	data[RTC_SEC] |= tm->tm_sec & config->rtc_count_sec_mask;

	data[RTC_MIN] &= ~config->rtc_count_min_mask;
	data[RTC_MIN] |= tm->tm_min & config->rtc_count_min_mask;

	data[RTC_HOUR] &= ~config->rtc_count_hour_mask;
	data[RTC_HOUR] |= tm->tm_hour & config->rtc_count_hour_mask;

	data[RTC_DAY] &= ~config->rtc_count_day_mask;
	data[RTC_DAY] |= tm->tm_mday & config->rtc_count_day_mask;

	data[RTC_MONTH] &= ~config->rtc_count_month_mask;
	data[RTC_MONTH] |= MONTHS_TO_DA9063(tm->tm_mon) &
	data[RTC_SEC]   = tm->tm_sec & config->rtc_count_sec_mask;
	data[RTC_MIN]   = tm->tm_min & config->rtc_count_min_mask;
	data[RTC_HOUR]  = tm->tm_hour & config->rtc_count_hour_mask;
	data[RTC_DAY]   = tm->tm_mday & config->rtc_count_day_mask;
	data[RTC_MONTH] = MONTHS_TO_DA9063(tm->tm_mon) &
				config->rtc_count_month_mask;

	data[RTC_YEAR] &= ~config->rtc_count_year_mask;
	data[RTC_YEAR] |= YEARS_TO_DA9063(tm->tm_year) &
	data[RTC_YEAR]  = YEARS_TO_DA9063(tm->tm_year) &
				config->rtc_count_year_mask;
}

Loading