mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	rtc: pcf2127: add support for accessing internal static RAM
The PCF2127 has 512 bytes of internal static RAM and this patch expands the driver to access this memory. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
This commit is contained in:
		
							parent
							
								
									cd7f3a249d
								
							
						
					
					
						commit
						d6c3029f32
					
				
					 1 changed files with 62 additions and 6 deletions
				
			
		| 
						 | 
				
			
			@ -36,6 +36,11 @@
 | 
			
		|||
#define PCF2127_REG_MO          (0x08)
 | 
			
		||||
#define PCF2127_REG_YR          (0x09)
 | 
			
		||||
 | 
			
		||||
/* the pcf2127 has 512 bytes nvmem, pcf2129 doesn't */
 | 
			
		||||
#define PCF2127_REG_RAM_addr_MSB       0x1a
 | 
			
		||||
#define PCF2127_REG_RAM_wrt_cmd        0x1c
 | 
			
		||||
#define PCF2127_REG_RAM_rd_cmd         0x1d
 | 
			
		||||
 | 
			
		||||
#define PCF2127_OSF             BIT(7)  /* Oscillator Fail flag */
 | 
			
		||||
 | 
			
		||||
struct pcf2127 {
 | 
			
		||||
| 
						 | 
				
			
			@ -183,10 +188,47 @@ static const struct rtc_class_ops pcf2127_rtc_ops = {
 | 
			
		|||
	.set_time	= pcf2127_rtc_set_time,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int pcf2127_nvmem_read(void *priv, unsigned int offset,
 | 
			
		||||
			      void *val, size_t bytes)
 | 
			
		||||
{
 | 
			
		||||
	struct pcf2127 *pcf2127 = priv;
 | 
			
		||||
	int ret;
 | 
			
		||||
	unsigned char offsetbuf[] = { offset >> 8, offset };
 | 
			
		||||
 | 
			
		||||
	ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_addr_MSB,
 | 
			
		||||
				offsetbuf, 2);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_rd_cmd,
 | 
			
		||||
			       val, bytes);
 | 
			
		||||
 | 
			
		||||
	return ret ?: bytes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int pcf2127_nvmem_write(void *priv, unsigned int offset,
 | 
			
		||||
			       void *val, size_t bytes)
 | 
			
		||||
{
 | 
			
		||||
	struct pcf2127 *pcf2127 = priv;
 | 
			
		||||
	int ret;
 | 
			
		||||
	unsigned char offsetbuf[] = { offset >> 8, offset };
 | 
			
		||||
 | 
			
		||||
	ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_addr_MSB,
 | 
			
		||||
				offsetbuf, 2);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_wrt_cmd,
 | 
			
		||||
				val, bytes);
 | 
			
		||||
 | 
			
		||||
	return ret ?: bytes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 | 
			
		||||
			const char *name)
 | 
			
		||||
			const char *name, bool has_nvmem)
 | 
			
		||||
{
 | 
			
		||||
	struct pcf2127 *pcf2127;
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
 | 
			
		||||
	dev_dbg(dev, "%s\n", __func__);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -200,8 +242,21 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 | 
			
		|||
 | 
			
		||||
	pcf2127->rtc = devm_rtc_device_register(dev, name, &pcf2127_rtc_ops,
 | 
			
		||||
						THIS_MODULE);
 | 
			
		||||
	if (IS_ERR(pcf2127->rtc))
 | 
			
		||||
		return PTR_ERR(pcf2127->rtc);
 | 
			
		||||
 | 
			
		||||
	return PTR_ERR_OR_ZERO(pcf2127->rtc);
 | 
			
		||||
	if (has_nvmem) {
 | 
			
		||||
		struct nvmem_config nvmem_cfg = {
 | 
			
		||||
			.priv = pcf2127,
 | 
			
		||||
			.reg_read = pcf2127_nvmem_read,
 | 
			
		||||
			.reg_write = pcf2127_nvmem_write,
 | 
			
		||||
			.size = 512,
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		ret = rtc_nvmem_register(pcf2127->rtc, &nvmem_cfg);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_OF
 | 
			
		||||
| 
						 | 
				
			
			@ -309,11 +364,11 @@ static int pcf2127_i2c_probe(struct i2c_client *client,
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	return pcf2127_probe(&client->dev, regmap,
 | 
			
		||||
				pcf2127_i2c_driver.driver.name);
 | 
			
		||||
			     pcf2127_i2c_driver.driver.name, id->driver_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct i2c_device_id pcf2127_i2c_id[] = {
 | 
			
		||||
	{ "pcf2127", 0 },
 | 
			
		||||
	{ "pcf2127", 1 },
 | 
			
		||||
	{ "pcf2129", 0 },
 | 
			
		||||
	{ }
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -372,11 +427,12 @@ static int pcf2127_spi_probe(struct spi_device *spi)
 | 
			
		|||
		return PTR_ERR(regmap);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return pcf2127_probe(&spi->dev, regmap, pcf2127_spi_driver.driver.name);
 | 
			
		||||
	return pcf2127_probe(&spi->dev, regmap, pcf2127_spi_driver.driver.name,
 | 
			
		||||
			     spi_get_device_id(spi)->driver_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct spi_device_id pcf2127_spi_id[] = {
 | 
			
		||||
	{ "pcf2127", 0 },
 | 
			
		||||
	{ "pcf2127", 1 },
 | 
			
		||||
	{ "pcf2129", 0 },
 | 
			
		||||
	{ }
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue