[v2,2/2] rtc: ds1307: Add support for Epson RX8111
Commit Message
From: Mike Looijmans <mike.looijmans@topic.nl>
The rx_8111 is quite similar to the rx_8030. This adds support for this
chip to the ds1307 driver. Date/time and alarm registers are in the
usual places. The nvmem is located at 0x40. Time stamping is not
supported.
Signed-off-by: Mike Looijmans <mike.looijmans@topic.nl>
---
Changes in v2:
Add "_REG" in register names
Add interrupt/alarm handling (different from rx8030)
drivers/rtc/rtc-ds1307.c | 308 ++++++++++++++++++++++++++++++++++++---
1 file changed, 285 insertions(+), 23 deletions(-)
Comments
Hi,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on abelloni/rtc-next]
[also build test ERROR on linus/master v6.1-rc3 next-20221101]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/glazveze-delta-nl/dt-bindings-rtc-ds1307-Add-support-for-Epson-RX8111/20221101-180204
base: https://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git rtc-next
patch link: https://lore.kernel.org/r/20221101083123.11695-2-glazveze%40delta.nl
patch subject: [PATCH v2 2/2] rtc: ds1307: Add support for Epson RX8111
config: powerpc-allmodconfig
compiler: powerpc-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/aa40485d8590c106bf51d00bcbee26aab0f389b8
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review glazveze-delta-nl/dt-bindings-rtc-ds1307-Add-support-for-Epson-RX8111/20221101-180204
git checkout aa40485d8590c106bf51d00bcbee26aab0f389b8
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=powerpc SHELL=/bin/bash drivers/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
drivers/rtc/rtc-ds1307.c: In function 'ds1307_probe':
>> drivers/rtc/rtc-ds1307.c:2220:28: error: 'struct rtc_device' has no member named 'uie_unsupported'
2220 | ds1307->rtc->uie_unsupported = 1;
| ^~
vim +2220 drivers/rtc/rtc-ds1307.c
1970
1971 static int ds1307_probe(struct i2c_client *client,
1972 const struct i2c_device_id *id)
1973 {
1974 struct ds1307 *ds1307;
1975 const void *match;
1976 int err = -ENODEV;
1977 int tmp;
1978 const struct chip_desc *chip;
1979 bool want_irq;
1980 bool ds1307_can_wakeup_device = false;
1981 unsigned char regs[8];
1982 struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
1983 u8 trickle_charger_setup = 0;
1984
1985 ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL);
1986 if (!ds1307)
1987 return -ENOMEM;
1988
1989 dev_set_drvdata(&client->dev, ds1307);
1990 ds1307->dev = &client->dev;
1991 ds1307->name = client->name;
1992
1993 ds1307->regmap = devm_regmap_init_i2c(client, ®map_config);
1994 if (IS_ERR(ds1307->regmap)) {
1995 dev_err(ds1307->dev, "regmap allocation failed\n");
1996 return PTR_ERR(ds1307->regmap);
1997 }
1998
1999 i2c_set_clientdata(client, ds1307);
2000
2001 match = device_get_match_data(&client->dev);
2002 if (match) {
2003 ds1307->type = (enum ds_type)match;
2004 chip = &chips[ds1307->type];
2005 } else if (id) {
2006 chip = &chips[id->driver_data];
2007 ds1307->type = id->driver_data;
2008 } else {
2009 return -ENODEV;
2010 }
2011
2012 want_irq = client->irq > 0 && chip->alarm;
2013
2014 if (!pdata)
2015 trickle_charger_setup = ds1307_trickle_init(ds1307, chip);
2016 else if (pdata->trickle_charger_setup)
2017 trickle_charger_setup = pdata->trickle_charger_setup;
2018
2019 if (trickle_charger_setup && chip->trickle_charger_reg) {
2020 dev_dbg(ds1307->dev,
2021 "writing trickle charger info 0x%x to 0x%x\n",
2022 trickle_charger_setup, chip->trickle_charger_reg);
2023 regmap_write(ds1307->regmap, chip->trickle_charger_reg,
2024 trickle_charger_setup);
2025 }
2026
2027 /*
2028 * For devices with no IRQ directly connected to the SoC, the RTC chip
2029 * can be forced as a wakeup source by stating that explicitly in
2030 * the device's .dts file using the "wakeup-source" boolean property.
2031 * If the "wakeup-source" property is set, don't request an IRQ.
2032 * This will guarantee the 'wakealarm' sysfs entry is available on the device,
2033 * if supported by the RTC.
2034 */
2035 if (chip->alarm && device_property_read_bool(&client->dev, "wakeup-source"))
2036 ds1307_can_wakeup_device = true;
2037
2038 switch (ds1307->type) {
2039 case ds_1337:
2040 case ds_1339:
2041 case ds_1341:
2042 case ds_3231:
2043 /* get registers that the "rtc" read below won't read... */
2044 err = regmap_bulk_read(ds1307->regmap, DS1337_REG_CONTROL,
2045 regs, 2);
2046 if (err) {
2047 dev_dbg(ds1307->dev, "read error %d\n", err);
2048 goto exit;
2049 }
2050
2051 /* oscillator off? turn it on, so clock can tick. */
2052 if (regs[0] & DS1337_BIT_nEOSC)
2053 regs[0] &= ~DS1337_BIT_nEOSC;
2054
2055 /*
2056 * Using IRQ or defined as wakeup-source?
2057 * Disable the square wave and both alarms.
2058 * For some variants, be sure alarms can trigger when we're
2059 * running on Vbackup (BBSQI/BBSQW)
2060 */
2061 if (want_irq || ds1307_can_wakeup_device) {
2062 regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit;
2063 regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE);
2064 }
2065
2066 regmap_write(ds1307->regmap, DS1337_REG_CONTROL,
2067 regs[0]);
2068
2069 /* oscillator fault? clear flag, and warn */
2070 if (regs[1] & DS1337_BIT_OSF) {
2071 regmap_write(ds1307->regmap, DS1337_REG_STATUS,
2072 regs[1] & ~DS1337_BIT_OSF);
2073 dev_warn(ds1307->dev, "SET TIME!\n");
2074 }
2075 break;
2076
2077 case rx_8025:
2078 err = regmap_bulk_read(ds1307->regmap,
2079 RX8025_REG_CTRL1 << 4 | 0x08, regs, 2);
2080 if (err) {
2081 dev_dbg(ds1307->dev, "read error %d\n", err);
2082 goto exit;
2083 }
2084
2085 /* oscillator off? turn it on, so clock can tick. */
2086 if (!(regs[1] & RX8025_BIT_XST)) {
2087 regs[1] |= RX8025_BIT_XST;
2088 regmap_write(ds1307->regmap,
2089 RX8025_REG_CTRL2 << 4 | 0x08,
2090 regs[1]);
2091 dev_warn(ds1307->dev,
2092 "oscillator stop detected - SET TIME!\n");
2093 }
2094
2095 if (regs[1] & RX8025_BIT_PON) {
2096 regs[1] &= ~RX8025_BIT_PON;
2097 regmap_write(ds1307->regmap,
2098 RX8025_REG_CTRL2 << 4 | 0x08,
2099 regs[1]);
2100 dev_warn(ds1307->dev, "power-on detected\n");
2101 }
2102
2103 if (regs[1] & RX8025_BIT_VDET) {
2104 regs[1] &= ~RX8025_BIT_VDET;
2105 regmap_write(ds1307->regmap,
2106 RX8025_REG_CTRL2 << 4 | 0x08,
2107 regs[1]);
2108 dev_warn(ds1307->dev, "voltage drop detected\n");
2109 }
2110
2111 /* make sure we are running in 24hour mode */
2112 if (!(regs[0] & RX8025_BIT_2412)) {
2113 u8 hour;
2114
2115 /* switch to 24 hour mode */
2116 regmap_write(ds1307->regmap,
2117 RX8025_REG_CTRL1 << 4 | 0x08,
2118 regs[0] | RX8025_BIT_2412);
2119
2120 err = regmap_bulk_read(ds1307->regmap,
2121 RX8025_REG_CTRL1 << 4 | 0x08,
2122 regs, 2);
2123 if (err) {
2124 dev_dbg(ds1307->dev, "read error %d\n", err);
2125 goto exit;
2126 }
2127
2128 /* correct hour */
2129 hour = bcd2bin(regs[DS1307_REG_HOUR]);
2130 if (hour == 12)
2131 hour = 0;
2132 if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
2133 hour += 12;
2134
2135 regmap_write(ds1307->regmap,
2136 DS1307_REG_HOUR << 4 | 0x08, hour);
2137 }
2138 break;
2139 case rx_8111:
2140 /* Use memory as user RAM */
2141 regmap_write(ds1307->regmap, RX8111_REG_TIME_STAMP_BUF_CTRL, 0);
2142 /* Disable timer, events, frequency output */
2143 regmap_write(ds1307->regmap, RX8111_REG_EXTENSION, 0xc8);
2144 break;
2145 case ds_1388:
2146 err = regmap_read(ds1307->regmap, DS1388_REG_CONTROL, &tmp);
2147 if (err) {
2148 dev_dbg(ds1307->dev, "read error %d\n", err);
2149 goto exit;
2150 }
2151
2152 /* oscillator off? turn it on, so clock can tick. */
2153 if (tmp & DS1388_BIT_nEOSC) {
2154 tmp &= ~DS1388_BIT_nEOSC;
2155 regmap_write(ds1307->regmap, DS1388_REG_CONTROL, tmp);
2156 }
2157 break;
2158 default:
2159 break;
2160 }
2161
2162 /* read RTC registers */
2163 err = regmap_bulk_read(ds1307->regmap, chip->offset, regs,
2164 sizeof(regs));
2165 if (err) {
2166 dev_dbg(ds1307->dev, "read error %d\n", err);
2167 goto exit;
2168 }
2169
2170 if (ds1307->type == mcp794xx &&
2171 !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) {
2172 regmap_write(ds1307->regmap, DS1307_REG_WDAY,
2173 regs[DS1307_REG_WDAY] |
2174 MCP794XX_BIT_VBATEN);
2175 }
2176
2177 tmp = regs[DS1307_REG_HOUR];
2178 switch (ds1307->type) {
2179 case ds_1340:
2180 case m41t0:
2181 case m41t00:
2182 case m41t11:
2183 /*
2184 * NOTE: ignores century bits; fix before deploying
2185 * systems that will run through year 2100.
2186 */
2187 break;
2188 case rx_8025:
2189 break;
2190 default:
2191 if (!(tmp & DS1307_BIT_12HR))
2192 break;
2193
2194 /*
2195 * Be sure we're in 24 hour mode. Multi-master systems
2196 * take note...
2197 */
2198 tmp = bcd2bin(tmp & 0x1f);
2199 if (tmp == 12)
2200 tmp = 0;
2201 if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
2202 tmp += 12;
2203 regmap_write(ds1307->regmap, chip->offset + DS1307_REG_HOUR,
2204 bin2bcd(tmp));
2205 }
2206
2207 ds1307->rtc = devm_rtc_allocate_device(ds1307->dev);
2208 if (IS_ERR(ds1307->rtc))
2209 return PTR_ERR(ds1307->rtc);
2210
2211 if (want_irq || ds1307_can_wakeup_device)
2212 device_set_wakeup_capable(ds1307->dev, true);
2213 else
2214 clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
2215
2216 if (ds1307_can_wakeup_device && !want_irq) {
2217 dev_info(ds1307->dev,
2218 "'wakeup-source' is set, request for an IRQ is disabled!\n");
2219 /* We cannot support UIE mode if we do not have an IRQ line */
> 2220 ds1307->rtc->uie_unsupported = 1;
2221 }
2222
2223 if (want_irq) {
2224 err = devm_request_threaded_irq(ds1307->dev, client->irq, NULL,
2225 chip->irq_handler ?: ds1307_irq,
2226 IRQF_SHARED | IRQF_ONESHOT,
2227 ds1307->name, ds1307);
2228 if (err) {
2229 client->irq = 0;
2230 device_set_wakeup_capable(ds1307->dev, false);
2231 clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
2232 dev_err(ds1307->dev, "unable to request IRQ!\n");
2233 } else {
2234 dev_dbg(ds1307->dev, "got IRQ %d\n", client->irq);
2235 }
2236 }
2237
2238 ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops;
2239 err = ds1307_add_frequency_test(ds1307);
2240 if (err)
2241 return err;
2242
2243 err = devm_rtc_register_device(ds1307->rtc);
2244 if (err)
2245 return err;
2246
2247 if (chip->nvram_size) {
2248 struct nvmem_config nvmem_cfg = {
2249 .name = "ds1307_nvram",
2250 .word_size = 1,
2251 .stride = 1,
2252 .size = chip->nvram_size,
2253 .reg_read = ds1307_nvram_read,
2254 .reg_write = ds1307_nvram_write,
2255 .priv = ds1307,
2256 };
2257
2258 devm_rtc_nvmem_register(ds1307->rtc, &nvmem_cfg);
2259 }
2260
2261 ds1307_hwmon_register(ds1307);
2262 ds1307_clks_register(ds1307);
2263 ds1307_wdt_register(ds1307);
2264
2265 return 0;
2266
2267 exit:
2268 return err;
2269 }
2270
Hi,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on abelloni/rtc-next]
[also build test ERROR on linus/master v6.1-rc3 next-20221101]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/glazveze-delta-nl/dt-bindings-rtc-ds1307-Add-support-for-Epson-RX8111/20221101-180204
base: https://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git rtc-next
patch link: https://lore.kernel.org/r/20221101083123.11695-2-glazveze%40delta.nl
patch subject: [PATCH v2 2/2] rtc: ds1307: Add support for Epson RX8111
config: hexagon-randconfig-r045-20221101
compiler: clang version 16.0.0 (https://github.com/llvm/llvm-project 791a7ae1ba3efd6bca96338e10ffde557ba83920)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/aa40485d8590c106bf51d00bcbee26aab0f389b8
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review glazveze-delta-nl/dt-bindings-rtc-ds1307-Add-support-for-Epson-RX8111/20221101-180204
git checkout aa40485d8590c106bf51d00bcbee26aab0f389b8
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash drivers/rtc/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
In file included from drivers/rtc/rtc-ds1307.c:12:
In file included from include/linux/i2c.h:19:
In file included from include/linux/regulator/consumer.h:35:
In file included from include/linux/suspend.h:5:
In file included from include/linux/swap.h:9:
In file included from include/linux/memcontrol.h:13:
In file included from include/linux/cgroup.h:26:
In file included from include/linux/kernel_stat.h:9:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/hexagon/include/asm/io.h:334:
include/asm-generic/io.h:547:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
val = __raw_readb(PCI_IOBASE + addr);
~~~~~~~~~~ ^
include/asm-generic/io.h:560:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
~~~~~~~~~~ ^
include/uapi/linux/byteorder/little_endian.h:37:51: note: expanded from macro '__le16_to_cpu'
#define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
^
In file included from drivers/rtc/rtc-ds1307.c:12:
In file included from include/linux/i2c.h:19:
In file included from include/linux/regulator/consumer.h:35:
In file included from include/linux/suspend.h:5:
In file included from include/linux/swap.h:9:
In file included from include/linux/memcontrol.h:13:
In file included from include/linux/cgroup.h:26:
In file included from include/linux/kernel_stat.h:9:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/hexagon/include/asm/io.h:334:
include/asm-generic/io.h:573:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
~~~~~~~~~~ ^
include/uapi/linux/byteorder/little_endian.h:35:51: note: expanded from macro '__le32_to_cpu'
#define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
^
In file included from drivers/rtc/rtc-ds1307.c:12:
In file included from include/linux/i2c.h:19:
In file included from include/linux/regulator/consumer.h:35:
In file included from include/linux/suspend.h:5:
In file included from include/linux/swap.h:9:
In file included from include/linux/memcontrol.h:13:
In file included from include/linux/cgroup.h:26:
In file included from include/linux/kernel_stat.h:9:
In file included from include/linux/interrupt.h:11:
In file included from include/linux/hardirq.h:11:
In file included from ./arch/hexagon/include/generated/asm/hardirq.h:1:
In file included from include/asm-generic/hardirq.h:17:
In file included from include/linux/irq.h:20:
In file included from include/linux/io.h:13:
In file included from arch/hexagon/include/asm/io.h:334:
include/asm-generic/io.h:584:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
__raw_writeb(value, PCI_IOBASE + addr);
~~~~~~~~~~ ^
include/asm-generic/io.h:594:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
__raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
~~~~~~~~~~ ^
include/asm-generic/io.h:604:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
__raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
~~~~~~~~~~ ^
>> drivers/rtc/rtc-ds1307.c:2220:16: error: no member named 'uie_unsupported' in 'struct rtc_device'
ds1307->rtc->uie_unsupported = 1;
~~~~~~~~~~~ ^
6 warnings and 1 error generated.
vim +2220 drivers/rtc/rtc-ds1307.c
1970
1971 static int ds1307_probe(struct i2c_client *client,
1972 const struct i2c_device_id *id)
1973 {
1974 struct ds1307 *ds1307;
1975 const void *match;
1976 int err = -ENODEV;
1977 int tmp;
1978 const struct chip_desc *chip;
1979 bool want_irq;
1980 bool ds1307_can_wakeup_device = false;
1981 unsigned char regs[8];
1982 struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
1983 u8 trickle_charger_setup = 0;
1984
1985 ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL);
1986 if (!ds1307)
1987 return -ENOMEM;
1988
1989 dev_set_drvdata(&client->dev, ds1307);
1990 ds1307->dev = &client->dev;
1991 ds1307->name = client->name;
1992
1993 ds1307->regmap = devm_regmap_init_i2c(client, ®map_config);
1994 if (IS_ERR(ds1307->regmap)) {
1995 dev_err(ds1307->dev, "regmap allocation failed\n");
1996 return PTR_ERR(ds1307->regmap);
1997 }
1998
1999 i2c_set_clientdata(client, ds1307);
2000
2001 match = device_get_match_data(&client->dev);
2002 if (match) {
2003 ds1307->type = (enum ds_type)match;
2004 chip = &chips[ds1307->type];
2005 } else if (id) {
2006 chip = &chips[id->driver_data];
2007 ds1307->type = id->driver_data;
2008 } else {
2009 return -ENODEV;
2010 }
2011
2012 want_irq = client->irq > 0 && chip->alarm;
2013
2014 if (!pdata)
2015 trickle_charger_setup = ds1307_trickle_init(ds1307, chip);
2016 else if (pdata->trickle_charger_setup)
2017 trickle_charger_setup = pdata->trickle_charger_setup;
2018
2019 if (trickle_charger_setup && chip->trickle_charger_reg) {
2020 dev_dbg(ds1307->dev,
2021 "writing trickle charger info 0x%x to 0x%x\n",
2022 trickle_charger_setup, chip->trickle_charger_reg);
2023 regmap_write(ds1307->regmap, chip->trickle_charger_reg,
2024 trickle_charger_setup);
2025 }
2026
2027 /*
2028 * For devices with no IRQ directly connected to the SoC, the RTC chip
2029 * can be forced as a wakeup source by stating that explicitly in
2030 * the device's .dts file using the "wakeup-source" boolean property.
2031 * If the "wakeup-source" property is set, don't request an IRQ.
2032 * This will guarantee the 'wakealarm' sysfs entry is available on the device,
2033 * if supported by the RTC.
2034 */
2035 if (chip->alarm && device_property_read_bool(&client->dev, "wakeup-source"))
2036 ds1307_can_wakeup_device = true;
2037
2038 switch (ds1307->type) {
2039 case ds_1337:
2040 case ds_1339:
2041 case ds_1341:
2042 case ds_3231:
2043 /* get registers that the "rtc" read below won't read... */
2044 err = regmap_bulk_read(ds1307->regmap, DS1337_REG_CONTROL,
2045 regs, 2);
2046 if (err) {
2047 dev_dbg(ds1307->dev, "read error %d\n", err);
2048 goto exit;
2049 }
2050
2051 /* oscillator off? turn it on, so clock can tick. */
2052 if (regs[0] & DS1337_BIT_nEOSC)
2053 regs[0] &= ~DS1337_BIT_nEOSC;
2054
2055 /*
2056 * Using IRQ or defined as wakeup-source?
2057 * Disable the square wave and both alarms.
2058 * For some variants, be sure alarms can trigger when we're
2059 * running on Vbackup (BBSQI/BBSQW)
2060 */
2061 if (want_irq || ds1307_can_wakeup_device) {
2062 regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit;
2063 regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE);
2064 }
2065
2066 regmap_write(ds1307->regmap, DS1337_REG_CONTROL,
2067 regs[0]);
2068
2069 /* oscillator fault? clear flag, and warn */
2070 if (regs[1] & DS1337_BIT_OSF) {
2071 regmap_write(ds1307->regmap, DS1337_REG_STATUS,
2072 regs[1] & ~DS1337_BIT_OSF);
2073 dev_warn(ds1307->dev, "SET TIME!\n");
2074 }
2075 break;
2076
2077 case rx_8025:
2078 err = regmap_bulk_read(ds1307->regmap,
2079 RX8025_REG_CTRL1 << 4 | 0x08, regs, 2);
2080 if (err) {
2081 dev_dbg(ds1307->dev, "read error %d\n", err);
2082 goto exit;
2083 }
2084
2085 /* oscillator off? turn it on, so clock can tick. */
2086 if (!(regs[1] & RX8025_BIT_XST)) {
2087 regs[1] |= RX8025_BIT_XST;
2088 regmap_write(ds1307->regmap,
2089 RX8025_REG_CTRL2 << 4 | 0x08,
2090 regs[1]);
2091 dev_warn(ds1307->dev,
2092 "oscillator stop detected - SET TIME!\n");
2093 }
2094
2095 if (regs[1] & RX8025_BIT_PON) {
2096 regs[1] &= ~RX8025_BIT_PON;
2097 regmap_write(ds1307->regmap,
2098 RX8025_REG_CTRL2 << 4 | 0x08,
2099 regs[1]);
2100 dev_warn(ds1307->dev, "power-on detected\n");
2101 }
2102
2103 if (regs[1] & RX8025_BIT_VDET) {
2104 regs[1] &= ~RX8025_BIT_VDET;
2105 regmap_write(ds1307->regmap,
2106 RX8025_REG_CTRL2 << 4 | 0x08,
2107 regs[1]);
2108 dev_warn(ds1307->dev, "voltage drop detected\n");
2109 }
2110
2111 /* make sure we are running in 24hour mode */
2112 if (!(regs[0] & RX8025_BIT_2412)) {
2113 u8 hour;
2114
2115 /* switch to 24 hour mode */
2116 regmap_write(ds1307->regmap,
2117 RX8025_REG_CTRL1 << 4 | 0x08,
2118 regs[0] | RX8025_BIT_2412);
2119
2120 err = regmap_bulk_read(ds1307->regmap,
2121 RX8025_REG_CTRL1 << 4 | 0x08,
2122 regs, 2);
2123 if (err) {
2124 dev_dbg(ds1307->dev, "read error %d\n", err);
2125 goto exit;
2126 }
2127
2128 /* correct hour */
2129 hour = bcd2bin(regs[DS1307_REG_HOUR]);
2130 if (hour == 12)
2131 hour = 0;
2132 if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
2133 hour += 12;
2134
2135 regmap_write(ds1307->regmap,
2136 DS1307_REG_HOUR << 4 | 0x08, hour);
2137 }
2138 break;
2139 case rx_8111:
2140 /* Use memory as user RAM */
2141 regmap_write(ds1307->regmap, RX8111_REG_TIME_STAMP_BUF_CTRL, 0);
2142 /* Disable timer, events, frequency output */
2143 regmap_write(ds1307->regmap, RX8111_REG_EXTENSION, 0xc8);
2144 break;
2145 case ds_1388:
2146 err = regmap_read(ds1307->regmap, DS1388_REG_CONTROL, &tmp);
2147 if (err) {
2148 dev_dbg(ds1307->dev, "read error %d\n", err);
2149 goto exit;
2150 }
2151
2152 /* oscillator off? turn it on, so clock can tick. */
2153 if (tmp & DS1388_BIT_nEOSC) {
2154 tmp &= ~DS1388_BIT_nEOSC;
2155 regmap_write(ds1307->regmap, DS1388_REG_CONTROL, tmp);
2156 }
2157 break;
2158 default:
2159 break;
2160 }
2161
2162 /* read RTC registers */
2163 err = regmap_bulk_read(ds1307->regmap, chip->offset, regs,
2164 sizeof(regs));
2165 if (err) {
2166 dev_dbg(ds1307->dev, "read error %d\n", err);
2167 goto exit;
2168 }
2169
2170 if (ds1307->type == mcp794xx &&
2171 !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) {
2172 regmap_write(ds1307->regmap, DS1307_REG_WDAY,
2173 regs[DS1307_REG_WDAY] |
2174 MCP794XX_BIT_VBATEN);
2175 }
2176
2177 tmp = regs[DS1307_REG_HOUR];
2178 switch (ds1307->type) {
2179 case ds_1340:
2180 case m41t0:
2181 case m41t00:
2182 case m41t11:
2183 /*
2184 * NOTE: ignores century bits; fix before deploying
2185 * systems that will run through year 2100.
2186 */
2187 break;
2188 case rx_8025:
2189 break;
2190 default:
2191 if (!(tmp & DS1307_BIT_12HR))
2192 break;
2193
2194 /*
2195 * Be sure we're in 24 hour mode. Multi-master systems
2196 * take note...
2197 */
2198 tmp = bcd2bin(tmp & 0x1f);
2199 if (tmp == 12)
2200 tmp = 0;
2201 if (regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
2202 tmp += 12;
2203 regmap_write(ds1307->regmap, chip->offset + DS1307_REG_HOUR,
2204 bin2bcd(tmp));
2205 }
2206
2207 ds1307->rtc = devm_rtc_allocate_device(ds1307->dev);
2208 if (IS_ERR(ds1307->rtc))
2209 return PTR_ERR(ds1307->rtc);
2210
2211 if (want_irq || ds1307_can_wakeup_device)
2212 device_set_wakeup_capable(ds1307->dev, true);
2213 else
2214 clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
2215
2216 if (ds1307_can_wakeup_device && !want_irq) {
2217 dev_info(ds1307->dev,
2218 "'wakeup-source' is set, request for an IRQ is disabled!\n");
2219 /* We cannot support UIE mode if we do not have an IRQ line */
> 2220 ds1307->rtc->uie_unsupported = 1;
2221 }
2222
2223 if (want_irq) {
2224 err = devm_request_threaded_irq(ds1307->dev, client->irq, NULL,
2225 chip->irq_handler ?: ds1307_irq,
2226 IRQF_SHARED | IRQF_ONESHOT,
2227 ds1307->name, ds1307);
2228 if (err) {
2229 client->irq = 0;
2230 device_set_wakeup_capable(ds1307->dev, false);
2231 clear_bit(RTC_FEATURE_ALARM, ds1307->rtc->features);
2232 dev_err(ds1307->dev, "unable to request IRQ!\n");
2233 } else {
2234 dev_dbg(ds1307->dev, "got IRQ %d\n", client->irq);
2235 }
2236 }
2237
2238 ds1307->rtc->ops = chip->rtc_ops ?: &ds13xx_rtc_ops;
2239 err = ds1307_add_frequency_test(ds1307);
2240 if (err)
2241 return err;
2242
2243 err = devm_rtc_register_device(ds1307->rtc);
2244 if (err)
2245 return err;
2246
2247 if (chip->nvram_size) {
2248 struct nvmem_config nvmem_cfg = {
2249 .name = "ds1307_nvram",
2250 .word_size = 1,
2251 .stride = 1,
2252 .size = chip->nvram_size,
2253 .reg_read = ds1307_nvram_read,
2254 .reg_write = ds1307_nvram_write,
2255 .priv = ds1307,
2256 };
2257
2258 devm_rtc_nvmem_register(ds1307->rtc, &nvmem_cfg);
2259 }
2260
2261 ds1307_hwmon_register(ds1307);
2262 ds1307_clks_register(ds1307);
2263 ds1307_wdt_register(ds1307);
2264
2265 return 0;
2266
2267 exit:
2268 return err;
2269 }
2270
@@ -46,6 +46,7 @@ enum ds_type {
m41t11,
mcp794xx,
rx_8025,
+ rx_8111,
rx_8130,
last_ds_type /* always last */
/* rs5c372 too? different address... */
@@ -113,6 +114,24 @@ enum ds_type {
# define RX8025_BIT_VDET 0x40
# define RX8025_BIT_XST 0x20
+#define RX8111_REG_EXTENSION 0x1d
+# define RX8111_REG_EXTENSION_WADA BIT(3)
+#define RX8111_REG_FLAG 0x1e
+# define RX8111_REG_FLAG_VLF BIT(1)
+# define RX8111_REG_FLAG_EVF BIT(2)
+# define RX8111_REG_FLAG_AF BIT(3)
+# define RX8111_REG_FLAG_TF BIT(4)
+# define RX8111_REG_FLAG_UF BIT(5)
+#define RX8111_REG_CONTROL 0x1e
+# define RX8111_REG_CONTROL_EIE BIT(2)
+# define RX8111_REG_CONTROL_AIE BIT(3)
+# define RX8111_REG_CONTROL_TIE BIT(4)
+# define RX8111_REG_CONTROL_UIE BIT(5)
+#define RX8111_REG_PWR_SWITCH_CTRL 0x32
+# define RX8111_PSC_SMP_INIEN BIT(6)
+# define RX8111_PSC_SMP_CHGEN BIT(7)
+#define RX8111_REG_TIME_STAMP_BUF_CTRL 0x34
+
#define RX8130_REG_ALARM_MIN 0x17
#define RX8130_REG_ALARM_HOUR 0x18
#define RX8130_REG_ALARM_WEEK_OR_DAY 0x19
@@ -205,6 +224,68 @@ struct chip_desc {
static const struct chip_desc chips[last_ds_type];
+static int ds1307_check_voltage_lost(struct ds1307 *ds1307)
+{
+ int ret;
+ unsigned int reg;
+ unsigned int mask;
+ unsigned int regflag;
+
+ switch (ds1307->type) {
+ case rx_8111:
+ reg = RX8111_REG_FLAG;
+ mask = RX8111_REG_FLAG_VLF;
+ break;
+ case rx_8130:
+ reg = RX8130_REG_FLAG;
+ mask = RX8130_REG_FLAG_VLF;
+ break;
+ default:
+ return 0;
+ }
+
+ ret = regmap_read(ds1307->regmap, reg, ®flag);
+ if (ret) {
+ dev_err(ds1307->dev, "%s error %d\n", "read", ret);
+ return ret;
+ }
+
+ if (regflag & mask) {
+ dev_warn_once(ds1307->dev, "oscillator failed, set time!\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ds1307_clear_voltage_lost(struct ds1307 *ds1307)
+{
+ int ret;
+ unsigned int reg;
+ unsigned int mask;
+
+ switch (ds1307->type) {
+ case rx_8111:
+ reg = RX8111_REG_FLAG;
+ mask = (unsigned int)~RX8111_REG_FLAG_VLF;
+ break;
+ case rx_8130:
+ reg = RX8130_REG_FLAG;
+ mask = (unsigned int)~RX8130_REG_FLAG_VLF;
+ break;
+ default:
+ return 0;
+ }
+
+ ret = regmap_write(ds1307->regmap, reg, mask);
+ if (ret) {
+ dev_err(ds1307->dev, "%s error %d\n", "write", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
static int ds1307_get_time(struct device *dev, struct rtc_time *t)
{
struct ds1307 *ds1307 = dev_get_drvdata(dev);
@@ -212,19 +293,9 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
const struct chip_desc *chip = &chips[ds1307->type];
u8 regs[7];
- if (ds1307->type == rx_8130) {
- unsigned int regflag;
- ret = regmap_read(ds1307->regmap, RX8130_REG_FLAG, ®flag);
- if (ret) {
- dev_err(dev, "%s error %d\n", "read", ret);
- return ret;
- }
-
- if (regflag & RX8130_REG_FLAG_VLF) {
- dev_warn_once(dev, "oscillator failed, set time!\n");
- return -EINVAL;
- }
- }
+ ret = ds1307_check_voltage_lost(ds1307);
+ if (ret)
+ return ret;
/* read the RTC date and time registers all at once */
ret = regmap_bulk_read(ds1307->regmap, chip->offset, regs,
@@ -397,15 +468,9 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
return result;
}
- if (ds1307->type == rx_8130) {
- /* clear Voltage Loss Flag as data is available now */
- result = regmap_write(ds1307->regmap, RX8130_REG_FLAG,
- ~(u8)RX8130_REG_FLAG_VLF);
- if (result) {
- dev_err(dev, "%s error %d\n", "write", result);
- return result;
- }
- }
+ result = ds1307_clear_voltage_lost(ds1307);
+ if (result)
+ return result;
return 0;
}
@@ -541,6 +606,174 @@ static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, u32 ohms, bool diode)
return setup;
}
+static u8 do_trickle_setup_rx8111(struct ds1307 *ds1307, u32 ohms, bool diode)
+{
+ /* make sure that the backup battery is enabled */
+ u8 setup = RX8111_PSC_SMP_INIEN;
+
+ if (diode)
+ setup |= RX8111_PSC_SMP_CHGEN;
+
+ return setup;
+}
+
+static irqreturn_t rx8111_irq(int irq, void *dev_id)
+{
+ struct ds1307 *ds1307 = dev_id;
+ irqreturn_t result = IRQ_NONE;
+ int ret;
+ u8 ctl[2];
+ u8 flags = 0;
+
+ rtc_lock(ds1307->rtc);
+
+ /* Read flag and control registers. */
+ ret = regmap_bulk_read(ds1307->regmap, RX8111_REG_FLAG, ctl,
+ sizeof(ctl));
+ if (ret < 0)
+ goto out;
+
+ if (ctl[0] & RX8111_REG_FLAG_AF) {
+ result = IRQ_HANDLED;
+ flags |= RTC_AF; /* Alarm */
+ ctl[1] &= ~RX8111_REG_CONTROL_AIE;
+ }
+ /*
+ * If an interrupt occurred that we cannot process, we'll have to turn
+ * it off, otherwise we'd be called again and again.
+ */
+ if (ctl[0] & RX8111_REG_FLAG_UF) {
+ result = IRQ_HANDLED;
+ ctl[1] &= ~RX8111_REG_CONTROL_UIE;
+ }
+ if (ctl[0] & RX8111_REG_FLAG_TF) {
+ result = IRQ_HANDLED;
+ ctl[1] &= ~RX8111_REG_CONTROL_TIE;
+ }
+ if (ctl[0] & RX8111_REG_FLAG_EVF) {
+ result = IRQ_HANDLED;
+ ctl[1] &= ~RX8111_REG_CONTROL_EIE;
+ }
+ /* Clear all flags */
+ ctl[0] &= ~(RX8111_REG_FLAG_UF | RX8111_REG_FLAG_TF |
+ RX8111_REG_FLAG_AF | RX8111_REG_FLAG_EVF);
+
+ ret = regmap_bulk_write(ds1307->regmap, RX8111_REG_FLAG, ctl,
+ sizeof(ctl));
+ if (ret < 0)
+ goto out;
+
+ rtc_update_irq(ds1307->rtc, 1, flags | RTC_IRQF);
+
+out:
+ rtc_unlock(ds1307->rtc);
+
+ return result;
+}
+
+static int rx8111_read_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+ struct ds1307 *ds1307 = dev_get_drvdata(dev);
+ u8 ald[3], ctl[2];
+ int ret;
+
+ /* Read alarm registers. */
+ ret = regmap_bulk_read(ds1307->regmap, RX8130_REG_ALARM_MIN, ald,
+ sizeof(ald));
+ if (ret < 0)
+ return ret;
+
+ /* Read flag and control registers. */
+ ret = regmap_bulk_read(ds1307->regmap, RX8111_REG_FLAG, ctl,
+ sizeof(ctl));
+ if (ret < 0)
+ return ret;
+
+ t->enabled = !!(ctl[1] & RX8111_REG_CONTROL_AIE);
+ t->pending = !!(ctl[0] & RX8111_REG_FLAG_AF);
+
+ /* Report alarm 0 time assuming 24-hour and day-of-month modes. */
+ t->time.tm_sec = -1;
+ t->time.tm_min = bcd2bin(ald[0] & 0x7f);
+ t->time.tm_hour = bcd2bin(ald[1] & 0x7f);
+ t->time.tm_wday = -1;
+ t->time.tm_mday = bcd2bin(ald[2] & 0x7f);
+ t->time.tm_mon = -1;
+ t->time.tm_year = -1;
+ t->time.tm_yday = -1;
+ t->time.tm_isdst = -1;
+
+ dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d enabled=%d\n",
+ __func__, t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
+ t->time.tm_wday, t->time.tm_mday, t->time.tm_mon, t->enabled);
+
+ return 0;
+}
+
+static int rx8111_set_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+ struct ds1307 *ds1307 = dev_get_drvdata(dev);
+ u8 ald[3], ctl[3];
+ int ret;
+
+ dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d "
+ "enabled=%d pending=%d\n", __func__,
+ t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
+ t->time.tm_wday, t->time.tm_mday, t->time.tm_mon,
+ t->enabled, t->pending);
+
+ /* Read control registers. */
+ ret = regmap_bulk_read(ds1307->regmap, RX8111_REG_EXTENSION, ctl,
+ sizeof(ctl));
+ if (ret < 0)
+ return ret;
+
+ ctl[0] &= RX8111_REG_EXTENSION_WADA;
+ ctl[1] &= ~RX8111_REG_FLAG_AF;
+ ctl[2] &= ~RX8111_REG_CONTROL_AIE;
+
+ ret = regmap_bulk_write(ds1307->regmap, RX8111_REG_EXTENSION, ctl,
+ sizeof(ctl));
+ if (ret < 0)
+ return ret;
+
+ /* Hardware alarm precision is 1 minute! */
+ ald[0] = bin2bcd(t->time.tm_min);
+ ald[1] = bin2bcd(t->time.tm_hour);
+ ald[2] = bin2bcd(t->time.tm_mday);
+
+ ret = regmap_bulk_write(ds1307->regmap, RX8130_REG_ALARM_MIN, ald,
+ sizeof(ald));
+ if (ret < 0)
+ return ret;
+
+ if (!t->enabled)
+ return 0;
+
+ ctl[2] |= RX8111_REG_CONTROL_AIE;
+
+ return regmap_write(ds1307->regmap, RX8111_REG_CONTROL, ctl[2]);
+}
+
+static int rx8111_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct ds1307 *ds1307 = dev_get_drvdata(dev);
+ int ret, reg;
+
+ ret = regmap_read(ds1307->regmap, RX8111_REG_CONTROL, ®);
+ if (ret < 0)
+ return ret;
+
+ if (enabled)
+ reg |= RX8111_REG_CONTROL_AIE;
+ else
+ reg &= ~RX8111_REG_CONTROL_AIE;
+
+ dev_dbg(dev, "%s, enable=%u, reg=0x%x\n", __func__, enabled, reg);
+
+ return regmap_write(ds1307->regmap, RX8111_REG_CONTROL, reg);
+}
+
static u8 do_trickle_setup_rx8130(struct ds1307 *ds1307, u32 ohms, bool diode)
{
/* make sure that the backup battery is enabled */
@@ -943,6 +1176,14 @@ static const struct rtc_class_ops rx8130_rtc_ops = {
.alarm_irq_enable = rx8130_alarm_irq_enable,
};
+static const struct rtc_class_ops rx8111_rtc_ops = {
+ .read_time = ds1307_get_time,
+ .set_time = ds1307_set_time,
+ .read_alarm = rx8111_read_alarm,
+ .set_alarm = rx8111_set_alarm,
+ .alarm_irq_enable = rx8111_alarm_irq_enable,
+};
+
static const struct rtc_class_ops mcp794xx_rtc_ops = {
.read_time = ds1307_get_time,
.set_time = ds1307_set_time,
@@ -1012,6 +1253,16 @@ static const struct chip_desc chips[last_ds_type] = {
.century_bit = DS1337_BIT_CENTURY,
.bbsqi_bit = DS3231_BIT_BBSQW,
},
+ [rx_8111] = {
+ .alarm = 1,
+ .nvram_offset = 0x40,
+ .nvram_size = 0x40, /* 0x40 .. 0x7F is user RAM */
+ .offset = 0x10,
+ .irq_handler = rx8111_irq,
+ .rtc_ops = &rx8111_rtc_ops,
+ .trickle_charger_reg = RX8111_REG_PWR_SWITCH_CTRL,
+ .do_trickle_setup = &do_trickle_setup_rx8111,
+ },
[rx_8130] = {
.alarm = 1,
/* this is battery backed SRAM */
@@ -1063,6 +1314,7 @@ static const struct i2c_device_id ds1307_id[] = {
{ "pt7c4338", ds_1307 },
{ "rx8025", rx_8025 },
{ "isl12057", ds_1337 },
+ { "rx8111", rx_8111 },
{ "rx8130", rx_8130 },
{ }
};
@@ -1137,6 +1389,10 @@ static const struct of_device_id ds1307_of_match[] = {
.compatible = "isil,isl12057",
.data = (void *)ds_1337
},
+ {
+ .compatible = "epson,rx8111",
+ .data = (void *)rx_8111
+ },
{
.compatible = "epson,rx8130",
.data = (void *)rx_8130
@@ -1880,6 +2136,12 @@ static int ds1307_probe(struct i2c_client *client,
DS1307_REG_HOUR << 4 | 0x08, hour);
}
break;
+ case rx_8111:
+ /* Use memory as user RAM */
+ regmap_write(ds1307->regmap, RX8111_REG_TIME_STAMP_BUF_CTRL, 0);
+ /* Disable timer, events, frequency output */
+ regmap_write(ds1307->regmap, RX8111_REG_EXTENSION, 0xc8);
+ break;
case ds_1388:
err = regmap_read(ds1307->regmap, DS1388_REG_CONTROL, &tmp);
if (err) {
@@ -1955,7 +2217,7 @@ static int ds1307_probe(struct i2c_client *client,
dev_info(ds1307->dev,
"'wakeup-source' is set, request for an IRQ is disabled!\n");
/* We cannot support UIE mode if we do not have an IRQ line */
- clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, ds1307->rtc->features);
+ ds1307->rtc->uie_unsupported = 1;
}
if (want_irq) {