mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 16:54:21 +00:00 
			
		
		
		
	drivers/rtc/rtc-m41t93.c: don't let get_time() reset M41T93_FLAG_OF
If the rtc reports the time might be invalid due to oscillator failure, M41T93_FLAG_OF flag must not be reset by get_time() as the read operation doesn't make the time valid. Without this patch, only the first get_time() reported an invalid time, the second get_time() reported a valid time althought the reported time is probably wrong due to oscillator failure. Instead of resetting in get_time(), with this patch M41T93_FLAG_OF is reset in set_time() when a valid time is to be written. Signed-off-by: Nikolaus Voss <n.voss@weinmann.de> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									eb86c3064b
								
							
						
					
					
						commit
						bcffb10f28
					
				
					 1 changed files with 27 additions and 19 deletions
				
			
		|  | @ -48,6 +48,7 @@ static inline int m41t93_set_reg(struct spi_device *spi, u8 addr, u8 data) | ||||||
| static int m41t93_set_time(struct device *dev, struct rtc_time *tm) | static int m41t93_set_time(struct device *dev, struct rtc_time *tm) | ||||||
| { | { | ||||||
| 	struct spi_device *spi = to_spi_device(dev); | 	struct spi_device *spi = to_spi_device(dev); | ||||||
|  | 	int tmp; | ||||||
| 	u8 buf[9] = {0x80};        /* write cmd + 8 data bytes */ | 	u8 buf[9] = {0x80};        /* write cmd + 8 data bytes */ | ||||||
| 	u8 * const data = &buf[1]; /* ptr to first data byte */ | 	u8 * const data = &buf[1]; /* ptr to first data byte */ | ||||||
| 
 | 
 | ||||||
|  | @ -62,6 +63,30 @@ static int m41t93_set_time(struct device *dev, struct rtc_time *tm) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	tmp = spi_w8r8(spi, M41T93_REG_FLAGS); | ||||||
|  | 	if (tmp < 0) | ||||||
|  | 		return tmp; | ||||||
|  | 
 | ||||||
|  | 	if (tmp & M41T93_FLAG_OF) { | ||||||
|  | 		dev_warn(&spi->dev, "OF bit is set, resetting.\n"); | ||||||
|  | 		m41t93_set_reg(spi, M41T93_REG_FLAGS, tmp & ~M41T93_FLAG_OF); | ||||||
|  | 
 | ||||||
|  | 		tmp = spi_w8r8(spi, M41T93_REG_FLAGS); | ||||||
|  | 		if (tmp < 0) { | ||||||
|  | 			return tmp; | ||||||
|  | 		} else if (tmp & M41T93_FLAG_OF) { | ||||||
|  | 			/* OF cannot be immediately reset: oscillator has to be
 | ||||||
|  | 			 * restarted. */ | ||||||
|  | 			u8 reset_osc = buf[M41T93_REG_ST_SEC] | M41T93_FLAG_ST; | ||||||
|  | 
 | ||||||
|  | 			dev_warn(&spi->dev, | ||||||
|  | 				 "OF bit is still set, kickstarting clock.\n"); | ||||||
|  | 			m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc); | ||||||
|  | 			reset_osc &= ~M41T93_FLAG_ST; | ||||||
|  | 			m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	data[M41T93_REG_SSEC]		= 0; | 	data[M41T93_REG_SSEC]		= 0; | ||||||
| 	data[M41T93_REG_ST_SEC]		= bin2bcd(tm->tm_sec); | 	data[M41T93_REG_ST_SEC]		= bin2bcd(tm->tm_sec); | ||||||
| 	data[M41T93_REG_MIN]		= bin2bcd(tm->tm_min); | 	data[M41T93_REG_MIN]		= bin2bcd(tm->tm_min); | ||||||
|  | @ -89,10 +114,7 @@ static int m41t93_get_time(struct device *dev, struct rtc_time *tm) | ||||||
| 	   1. halt bit (HT) is set: the clock is running but update of readout | 	   1. halt bit (HT) is set: the clock is running but update of readout | ||||||
| 	      registers has been disabled due to power failure. This is normal | 	      registers has been disabled due to power failure. This is normal | ||||||
| 	      case after poweron. Time is valid after resetting HT bit. | 	      case after poweron. Time is valid after resetting HT bit. | ||||||
| 	   2. oscillator fail bit (OF) is set. Oscillator has be stopped and | 	   2. oscillator fail bit (OF) is set: time is invalid. | ||||||
| 	      time is invalid: |  | ||||||
| 	      a) OF can be immeditely reset. |  | ||||||
| 	      b) OF cannot be immediately reset: oscillator has to be restarted. |  | ||||||
| 	*/ | 	*/ | ||||||
| 	tmp = spi_w8r8(spi, M41T93_REG_ALM_HOUR_HT); | 	tmp = spi_w8r8(spi, M41T93_REG_ALM_HOUR_HT); | ||||||
| 	if (tmp < 0) | 	if (tmp < 0) | ||||||
|  | @ -110,21 +132,7 @@ static int m41t93_get_time(struct device *dev, struct rtc_time *tm) | ||||||
| 
 | 
 | ||||||
| 	if (tmp & M41T93_FLAG_OF) { | 	if (tmp & M41T93_FLAG_OF) { | ||||||
| 		ret = -EINVAL; | 		ret = -EINVAL; | ||||||
| 		dev_warn(&spi->dev, "OF bit is set, resetting.\n"); | 		dev_warn(&spi->dev, "OF bit is set, write time to restart.\n"); | ||||||
| 		m41t93_set_reg(spi, M41T93_REG_FLAGS, tmp & ~M41T93_FLAG_OF); |  | ||||||
| 
 |  | ||||||
| 		tmp = spi_w8r8(spi, M41T93_REG_FLAGS); |  | ||||||
| 		if (tmp < 0) |  | ||||||
| 			return tmp; |  | ||||||
| 		else if (tmp & M41T93_FLAG_OF) { |  | ||||||
| 			u8 reset_osc = buf[M41T93_REG_ST_SEC] | M41T93_FLAG_ST; |  | ||||||
| 
 |  | ||||||
| 			dev_warn(&spi->dev, |  | ||||||
| 				 "OF bit is still set, kickstarting clock.\n"); |  | ||||||
| 			m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc); |  | ||||||
| 			reset_osc &= ~M41T93_FLAG_ST; |  | ||||||
| 			m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc); |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (tmp & M41T93_FLAG_BL) | 	if (tmp & M41T93_FLAG_BL) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Nikolaus Voss
						Nikolaus Voss