From d38df34e3f0ea1e65c7db5d33d132dc14da0009a Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 16 Apr 2015 12:43:34 -0700 Subject: hwmon: (ina2xx) replace ina226_avg_bits() with find_closest() Use find_closest() to locate the closest average in ina226_avg_tab. Signed-off-by: Bartosz Golaszewski Cc: Guenter Roeck Cc: Steven Rostedt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/ina2xx.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c index d1542b7d4bc3..4d2815079fc2 100644 --- a/drivers/hwmon/ina2xx.c +++ b/drivers/hwmon/ina2xx.c @@ -36,6 +36,7 @@ #include #include #include +#include #include @@ -141,19 +142,6 @@ static const struct ina2xx_config ina2xx_config[] = { */ static const int ina226_avg_tab[] = { 1, 4, 16, 64, 128, 256, 512, 1024 }; -static int ina226_avg_bits(int avg) -{ - int i; - - /* Get the closest average from the tab. */ - for (i = 0; i < ARRAY_SIZE(ina226_avg_tab) - 1; i++) { - if (avg <= (ina226_avg_tab[i] + ina226_avg_tab[i + 1]) / 2) - break; - } - - return i; /* Return 0b0111 for values greater than 1024. */ -} - static int ina226_reg_to_interval(u16 config) { int avg = ina226_avg_tab[INA226_READ_AVG(config)]; @@ -171,7 +159,8 @@ static u16 ina226_interval_to_reg(int interval, u16 config) avg = DIV_ROUND_CLOSEST(interval * 1000, INA226_TOTAL_CONV_TIME_DEFAULT); - avg_bits = ina226_avg_bits(avg); + avg_bits = find_closest(avg, ina226_avg_tab, + ARRAY_SIZE(ina226_avg_tab)); return (config & ~INA226_AVG_RD_MASK) | INA226_SHIFT_AVG(avg_bits); } -- cgit v1.2.3-58-ga151 From 0f3721c51ec5643e00f07dd3bbc5712c72fc62b2 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 16 Apr 2015 12:43:36 -0700 Subject: hwmon: (lm85) use find_closest() in x_TO_REG() functions Replace RANGE_TO_REG() and FREQ_TO_REG() implementations with calls to find_closest(). Signed-off-by: Bartosz Golaszewski Cc: Guenter Roeck Cc: Steven Rostedt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/lm85.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 2b4b419273fe..6ff773fcaefb 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -34,6 +34,7 @@ #include #include #include +#include /* Addresses to scan */ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; @@ -190,15 +191,7 @@ static const int lm85_range_map[] = { static int RANGE_TO_REG(long range) { - int i; - - /* Find the closest match */ - for (i = 0; i < 15; ++i) { - if (range <= (lm85_range_map[i] + lm85_range_map[i + 1]) / 2) - break; - } - - return i; + return find_closest(range, lm85_range_map, ARRAY_SIZE(lm85_range_map)); } #define RANGE_FROM_REG(val) lm85_range_map[(val) & 0x0f] @@ -209,16 +202,12 @@ static const int lm85_freq_map[8] = { /* 1 Hz */ static const int adm1027_freq_map[8] = { /* 1 Hz */ 11, 15, 22, 29, 35, 44, 59, 88 }; +#define FREQ_MAP_LEN 8 -static int FREQ_TO_REG(const int *map, unsigned long freq) +static int FREQ_TO_REG(const int *map, + unsigned int map_size, unsigned long freq) { - int i; - - /* Find the closest match */ - for (i = 0; i < 7; ++i) - if (freq <= (map[i] + map[i + 1]) / 2) - break; - return i; + return find_closest(freq, map, map_size); } static int FREQ_FROM_REG(const int *map, u8 reg) @@ -828,7 +817,8 @@ static ssize_t set_pwm_freq(struct device *dev, data->cfg5 &= ~ADT7468_HFPWM; lm85_write_value(client, ADT7468_REG_CFG5, data->cfg5); } else { /* Low freq. mode */ - data->pwm_freq[nr] = FREQ_TO_REG(data->freq_map, val); + data->pwm_freq[nr] = FREQ_TO_REG(data->freq_map, + FREQ_MAP_LEN, val); lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), (data->zone[nr].range << 4) | data->pwm_freq[nr]); -- cgit v1.2.3-58-ga151 From cdb1dc3f1ca5c5899e5fa186afe20390bd8c00dc Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 16 Apr 2015 12:43:39 -0700 Subject: hwmon: (w83795) use find_closest_descending() in pwm_freq_to_reg() Replace the loop iterating over pwm_freq_cksel0 with a call to find_closest_descending(). Signed-off-by: Bartosz Golaszewski Cc: Guenter Roeck Cc: Steven Rostedt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/w83795.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c index 21894131190f..49276bbdac3d 100644 --- a/drivers/hwmon/w83795.c +++ b/drivers/hwmon/w83795.c @@ -35,6 +35,7 @@ #include #include #include +#include /* Addresses to scan */ static const unsigned short normal_i2c[] = { @@ -308,11 +309,8 @@ static u8 pwm_freq_to_reg(unsigned long val, u16 clkin) unsigned long best0, best1; /* Best fit for cksel = 0 */ - for (reg0 = 0; reg0 < ARRAY_SIZE(pwm_freq_cksel0) - 1; reg0++) { - if (val > (pwm_freq_cksel0[reg0] + - pwm_freq_cksel0[reg0 + 1]) / 2) - break; - } + reg0 = find_closest_descending(val, pwm_freq_cksel0, + ARRAY_SIZE(pwm_freq_cksel0)); if (val < 375) /* cksel = 1 can't beat this */ return reg0; best0 = pwm_freq_cksel0[reg0]; -- cgit v1.2.3-58-ga151 From f766093ecb647f5a87bfa456715abbbccee547ce Mon Sep 17 00:00:00 2001 From: Javi Merino Date: Thu, 16 Apr 2015 12:43:45 -0700 Subject: kernel.h: implement DIV_ROUND_CLOSEST_ULL We have grown a number of different implementations of DIV_ROUND_CLOSEST_ULL throughout the kernel. Move the i915 one to kernel.h so that it can be reused. Signed-off-by: Javi Merino Reviewed-by: Jeff Epler Cc: Jani Nikula Cc: David Airlie Cc: Guenter Roeck Acked-by: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Alex Elder Cc: Antti Palosaari Cc: Javi Merino Cc: Mauro Carvalho Chehab Cc: Mel Gorman Cc: Mike Turquette Cc: Stephen Boyd Cc: Stephen Hemminger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/gpu/drm/i915/intel_drv.h | 3 --- drivers/gpu/drm/i915/intel_panel.c | 1 + include/linux/kernel.h | 12 ++++++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index eef79ccd0b7c..ba243db35840 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -36,9 +36,6 @@ #include #include -#define DIV_ROUND_CLOSEST_ULL(ll, d) \ -({ unsigned long long _tmp = (ll)+(d)/2; do_div(_tmp, d); _tmp; }) - /** * _wait_for - magic (register) wait macro * diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index d8686ce89160..08532d4ffe0a 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -30,6 +30,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include "intel_drv.h" diff --git a/include/linux/kernel.h b/include/linux/kernel.h index d6d630d31ef3..3a5b48e52a9e 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -103,6 +103,18 @@ (((__x) - ((__d) / 2)) / (__d)); \ } \ ) +/* + * Same as above but for u64 dividends. divisor must be a 32-bit + * number. + */ +#define DIV_ROUND_CLOSEST_ULL(x, divisor)( \ +{ \ + typeof(divisor) __d = divisor; \ + unsigned long long _tmp = (x) + (__d) / 2; \ + do_div(_tmp, __d); \ + _tmp; \ +} \ +) /* * Multiplies an integer by a fraction, while avoiding unnecessary -- cgit v1.2.3-58-ga151 From aa7762010a4340a12a87a54b7a402adcdce8cfa9 Mon Sep 17 00:00:00 2001 From: Javi Merino Date: Thu, 16 Apr 2015 12:43:48 -0700 Subject: clk: bcm/kona: use DIV_ROUND_CLOSEST_ULL() Now that the kernel provides DIV_ROUND_CLOSEST_ULL(), drop the internal implementation and use the kernel one. Signed-off-by: Javi Merino Cc: Mike Turquette Cc: Stephen Boyd Acked-by: Alex Elder Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/clk/bcm/clk-kona.c | 28 +++++++--------------------- drivers/clk/bcm/clk-kona.h | 1 - 2 files changed, 7 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c index 05abae89262e..a0ef4f75d457 100644 --- a/drivers/clk/bcm/clk-kona.c +++ b/drivers/clk/bcm/clk-kona.c @@ -15,6 +15,7 @@ #include "clk-kona.h" #include +#include /* * "Policies" affect the frequencies of bus clocks provided by a @@ -51,21 +52,6 @@ static inline u32 bitfield_replace(u32 reg_val, u32 shift, u32 width, u32 val) /* Divider and scaling helpers */ -/* - * Implement DIV_ROUND_CLOSEST() for 64-bit dividend and both values - * unsigned. Note that unlike do_div(), the remainder is discarded - * and the return value is the quotient (not the remainder). - */ -u64 do_div_round_closest(u64 dividend, unsigned long divisor) -{ - u64 result; - - result = dividend + ((u64)divisor >> 1); - (void)do_div(result, divisor); - - return result; -} - /* Convert a divider into the scaled divisor value it represents. */ static inline u64 scaled_div_value(struct bcm_clk_div *div, u32 reg_div) { @@ -87,7 +73,7 @@ u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value, u32 billionths) combined = (u64)div_value * BILLION + billionths; combined <<= div->u.s.frac_width; - return do_div_round_closest(combined, BILLION); + return DIV_ROUND_CLOSEST_ULL(combined, BILLION); } /* The scaled minimum divisor representable by a divider */ @@ -731,7 +717,7 @@ static unsigned long clk_recalc_rate(struct ccu_data *ccu, scaled_rate = scale_rate(pre_div, parent_rate); scaled_rate = scale_rate(div, scaled_rate); scaled_div = divider_read_scaled(ccu, pre_div); - scaled_parent_rate = do_div_round_closest(scaled_rate, + scaled_parent_rate = DIV_ROUND_CLOSEST_ULL(scaled_rate, scaled_div); } else { scaled_parent_rate = scale_rate(div, parent_rate); @@ -743,7 +729,7 @@ static unsigned long clk_recalc_rate(struct ccu_data *ccu, * rate. */ scaled_div = divider_read_scaled(ccu, div); - result = do_div_round_closest(scaled_parent_rate, scaled_div); + result = DIV_ROUND_CLOSEST_ULL(scaled_parent_rate, scaled_div); return (unsigned long)result; } @@ -790,7 +776,7 @@ static long round_rate(struct ccu_data *ccu, struct bcm_clk_div *div, scaled_rate = scale_rate(pre_div, parent_rate); scaled_rate = scale_rate(div, scaled_rate); scaled_pre_div = divider_read_scaled(ccu, pre_div); - scaled_parent_rate = do_div_round_closest(scaled_rate, + scaled_parent_rate = DIV_ROUND_CLOSEST_ULL(scaled_rate, scaled_pre_div); } else { scaled_parent_rate = scale_rate(div, parent_rate); @@ -802,7 +788,7 @@ static long round_rate(struct ccu_data *ccu, struct bcm_clk_div *div, * the best we can do. */ if (!divider_is_fixed(div)) { - best_scaled_div = do_div_round_closest(scaled_parent_rate, + best_scaled_div = DIV_ROUND_CLOSEST_ULL(scaled_parent_rate, rate); min_scaled_div = scaled_div_min(div); max_scaled_div = scaled_div_max(div); @@ -815,7 +801,7 @@ static long round_rate(struct ccu_data *ccu, struct bcm_clk_div *div, } /* OK, figure out the resulting rate */ - result = do_div_round_closest(scaled_parent_rate, best_scaled_div); + result = DIV_ROUND_CLOSEST_ULL(scaled_parent_rate, best_scaled_div); if (scaled_div) *scaled_div = best_scaled_div; diff --git a/drivers/clk/bcm/clk-kona.h b/drivers/clk/bcm/clk-kona.h index 2537b3072910..6849a64baf6d 100644 --- a/drivers/clk/bcm/clk-kona.h +++ b/drivers/clk/bcm/clk-kona.h @@ -503,7 +503,6 @@ extern struct clk_ops kona_peri_clk_ops; /* Externally visible functions */ -extern u64 do_div_round_closest(u64 dividend, unsigned long divisor); extern u64 scaled_div_max(struct bcm_clk_div *div); extern u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value, u32 billionths); -- cgit v1.2.3-58-ga151 From ee3c86f356b4dfc130442d0bd68ff2da2bd60538 Mon Sep 17 00:00:00 2001 From: Javi Merino Date: Thu, 16 Apr 2015 12:43:51 -0700 Subject: cpuidle: menu: use DIV_ROUND_CLOSEST_ULL() Now that the kernel provides DIV_ROUND_CLOSEST_ULL(), drop the internal implementation and use the kernel one. Signed-off-by: Javi Merino Acked-by: Rafael J. Wysocki Cc: Mel Gorman Cc: Stephen Hemminger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/cpuidle/governors/menu.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 40580794e23d..b8a5fa15ca24 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -190,12 +190,6 @@ static DEFINE_PER_CPU(struct menu_device, menu_devices); static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev); -/* This implements DIV_ROUND_CLOSEST but avoids 64 bit division */ -static u64 div_round64(u64 dividend, u32 divisor) -{ - return div_u64(dividend + (divisor / 2), divisor); -} - /* * Try detecting repeating patterns by keeping track of the last 8 * intervals, and checking if the standard deviation of that set @@ -317,7 +311,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) * operands are 32 bits. * Make sure to round up for half microseconds. */ - data->predicted_us = div_round64((uint64_t)data->next_timer_us * + data->predicted_us = DIV_ROUND_CLOSEST_ULL((uint64_t)data->next_timer_us * data->correction_factor[data->bucket], RESOLUTION * DECAY); -- cgit v1.2.3-58-ga151 From 512eb720c9892261d68f86ba880a55cdbb74710d Mon Sep 17 00:00:00 2001 From: Javi Merino Date: Thu, 16 Apr 2015 12:43:54 -0700 Subject: media: cxd2820r: use DIV_ROUND_CLOSEST_ULL() Now that the kernel provides DIV_ROUND_CLOSEST_ULL(), drop the internal implementation and use the kernel one. Signed-off-by: Javi Merino Cc: Mauro Carvalho Chehab Acked-by: Antti Palosaari Reviewed-by: Antti Palosaari Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/dvb-frontends/cxd2820r_c.c | 2 +- drivers/media/dvb-frontends/cxd2820r_core.c | 6 ------ drivers/media/dvb-frontends/cxd2820r_priv.h | 2 -- drivers/media/dvb-frontends/cxd2820r_t.c | 2 +- drivers/media/dvb-frontends/cxd2820r_t2.c | 2 +- 5 files changed, 3 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb-frontends/cxd2820r_c.c b/drivers/media/dvb-frontends/cxd2820r_c.c index 149fdca3fb44..72b0e2db3aab 100644 --- a/drivers/media/dvb-frontends/cxd2820r_c.c +++ b/drivers/media/dvb-frontends/cxd2820r_c.c @@ -79,7 +79,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe) num = if_freq / 1000; /* Hz => kHz */ num *= 0x4000; - if_ctl = 0x4000 - cxd2820r_div_u64_round_closest(num, 41000); + if_ctl = 0x4000 - DIV_ROUND_CLOSEST_ULL(num, 41000); buf[0] = (if_ctl >> 8) & 0x3f; buf[1] = (if_ctl >> 0) & 0xff; diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c index 422e84bbb008..490e090048ef 100644 --- a/drivers/media/dvb-frontends/cxd2820r_core.c +++ b/drivers/media/dvb-frontends/cxd2820r_core.c @@ -244,12 +244,6 @@ error: return ret; } -/* 64 bit div with round closest, like DIV_ROUND_CLOSEST but 64 bit */ -u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor) -{ - return div_u64(dividend + (divisor / 2), divisor); -} - static int cxd2820r_set_frontend(struct dvb_frontend *fe) { struct cxd2820r_priv *priv = fe->demodulator_priv; diff --git a/drivers/media/dvb-frontends/cxd2820r_priv.h b/drivers/media/dvb-frontends/cxd2820r_priv.h index 7ff5f60c83e1..4b428959b16e 100644 --- a/drivers/media/dvb-frontends/cxd2820r_priv.h +++ b/drivers/media/dvb-frontends/cxd2820r_priv.h @@ -64,8 +64,6 @@ int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val, int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val, int len); -u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor); - int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val, int len); diff --git a/drivers/media/dvb-frontends/cxd2820r_t.c b/drivers/media/dvb-frontends/cxd2820r_t.c index 51401d036530..008cb2ac8480 100644 --- a/drivers/media/dvb-frontends/cxd2820r_t.c +++ b/drivers/media/dvb-frontends/cxd2820r_t.c @@ -103,7 +103,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe) num = if_freq / 1000; /* Hz => kHz */ num *= 0x1000000; - if_ctl = cxd2820r_div_u64_round_closest(num, 41000); + if_ctl = DIV_ROUND_CLOSEST_ULL(num, 41000); buf[0] = ((if_ctl >> 16) & 0xff); buf[1] = ((if_ctl >> 8) & 0xff); buf[2] = ((if_ctl >> 0) & 0xff); diff --git a/drivers/media/dvb-frontends/cxd2820r_t2.c b/drivers/media/dvb-frontends/cxd2820r_t2.c index 9c0c4f42175c..35fe364c7182 100644 --- a/drivers/media/dvb-frontends/cxd2820r_t2.c +++ b/drivers/media/dvb-frontends/cxd2820r_t2.c @@ -120,7 +120,7 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe) num = if_freq / 1000; /* Hz => kHz */ num *= 0x1000000; - if_ctl = cxd2820r_div_u64_round_closest(num, 41000); + if_ctl = DIV_ROUND_CLOSEST_ULL(num, 41000); buf[0] = ((if_ctl >> 16) & 0xff); buf[1] = ((if_ctl >> 8) & 0xff); buf[2] = ((if_ctl >> 0) & 0xff); -- cgit v1.2.3-58-ga151 From b0c57b5941c4a42698d845ada6a76feeba2d1be9 Mon Sep 17 00:00:00 2001 From: Robert Kmiec Date: Thu, 16 Apr 2015 12:45:01 -0700 Subject: drivers/rtc/rtc-pcf8563.c: simplify return from function This commit does not change any logic here. It just makes the code easier to read. This is how it looked like: If err != 0 return err; else return 0; Signed-off-by: Robert Kmiec Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-pcf8563.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 96fb32e7d6f8..0ba7e59929be 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -246,7 +246,6 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) { struct pcf8563 *pcf8563 = i2c_get_clientdata(client); - int err; unsigned char buf[9]; dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " @@ -272,12 +271,8 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) buf[PCF8563_REG_DW] = tm->tm_wday & 0x07; - err = pcf8563_write_block_data(client, PCF8563_REG_SC, + return pcf8563_write_block_data(client, PCF8563_REG_SC, 9 - PCF8563_REG_SC, buf + PCF8563_REG_SC); - if (err) - return err; - - return 0; } #ifdef CONFIG_RTC_INTF_DEV -- cgit v1.2.3-58-ga151 From 7f48b21bdfede2c06e966258317a3bb4be3e4f25 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Thu, 16 Apr 2015 12:45:04 -0700 Subject: rtc: stmp3xxx: use optional crystal in low power states MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rtc's status register allows to determine if a 32k crystal is connected to keep the rtc running in low power states provided the corresponding fuse bits were blown correctly during production. (In case they were not, the right frequency can be stated in the device tree.) If there is no such crystal available force the 24 MHz XTAL clock to keep running to retain the right date and time. Otherwise use the crystal to save some power. It would be nice to only switch to the crystal when the XTAL clock is about to be disabled and keep the crystal off when unneeded because XTAL is always on while the chip is powered on. But as sudden power loss isn't detectable this is not save. Signed-off-by: Uwe Kleine-König Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- .../devicetree/bindings/rtc/stmp3xxx-rtc.txt | 5 ++ drivers/rtc/rtc-stmp3xxx.c | 66 ++++++++++++++++++++-- 2 files changed, 65 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt b/Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt index b800070fe6e9..fa6a94226669 100644 --- a/Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt +++ b/Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt @@ -7,6 +7,11 @@ Required properties: region. - interrupts: rtc alarm interrupt +Optional properties: +- stmp,crystal-freq: override crystal frequency as determined from fuse bits. + Only <32000> and <32768> are possible for the hardware. Use <0> for + "no crystal". + Example: rtc@80056000 { diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index 2939cdcb2688..eb09eddf39b8 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c @@ -42,6 +42,8 @@ #define STMP3XXX_RTC_STAT 0x10 #define STMP3XXX_RTC_STAT_STALE_SHIFT 16 #define STMP3XXX_RTC_STAT_RTC_PRESENT 0x80000000 +#define STMP3XXX_RTC_STAT_XTAL32000_PRESENT 0x10000000 +#define STMP3XXX_RTC_STAT_XTAL32768_PRESENT 0x08000000 #define STMP3XXX_RTC_SECONDS 0x30 @@ -52,9 +54,13 @@ #define STMP3XXX_RTC_PERSISTENT0 0x60 #define STMP3XXX_RTC_PERSISTENT0_SET 0x64 #define STMP3XXX_RTC_PERSISTENT0_CLR 0x68 -#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN 0x00000002 -#define STMP3XXX_RTC_PERSISTENT0_ALARM_EN 0x00000004 -#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE 0x00000080 +#define STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE (1 << 0) +#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN (1 << 1) +#define STMP3XXX_RTC_PERSISTENT0_ALARM_EN (1 << 2) +#define STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP (1 << 4) +#define STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP (1 << 5) +#define STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ (1 << 6) +#define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE (1 << 7) #define STMP3XXX_RTC_PERSISTENT1 0x70 /* missing bitmask in headers */ @@ -248,6 +254,9 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) { struct stmp3xxx_rtc_data *rtc_data; struct resource *r; + u32 rtc_stat; + u32 pers0_set, pers0_clr; + u32 crystalfreq = 0; int err; rtc_data = devm_kzalloc(&pdev->dev, sizeof(*rtc_data), GFP_KERNEL); @@ -268,8 +277,8 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) rtc_data->irq_alarm = platform_get_irq(pdev, 0); - if (!(readl(STMP3XXX_RTC_STAT + rtc_data->io) & - STMP3XXX_RTC_STAT_RTC_PRESENT)) { + rtc_stat = readl(rtc_data->io + STMP3XXX_RTC_STAT); + if (!(rtc_stat & STMP3XXX_RTC_STAT_RTC_PRESENT)) { dev_err(&pdev->dev, "no device onboard\n"); return -ENODEV; } @@ -282,9 +291,54 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) return err; } + /* + * Obviously the rtc needs a clock input to be able to run. + * This clock can be provided by an external 32k crystal. If that one is + * missing XTAL must not be disabled in suspend which consumes a + * lot of power. Normally the presence and exact frequency (supported + * are 32000 Hz and 32768 Hz) is detectable from fuses, but as reality + * proves these fuses are not blown correctly on all machines, so the + * frequency can be overridden in the device tree. + */ + if (rtc_stat & STMP3XXX_RTC_STAT_XTAL32000_PRESENT) + crystalfreq = 32000; + else if (rtc_stat & STMP3XXX_RTC_STAT_XTAL32768_PRESENT) + crystalfreq = 32768; + + of_property_read_u32(pdev->dev.of_node, "stmp,crystal-freq", + &crystalfreq); + + switch (crystalfreq) { + case 32000: + /* keep 32kHz crystal running in low-power mode */ + pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ | + STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP | + STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE; + pers0_clr = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP; + break; + case 32768: + /* keep 32.768kHz crystal running in low-power mode */ + pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP | + STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE; + pers0_clr = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP | + STMP3XXX_RTC_PERSISTENT0_XTAL32_FREQ; + break; + default: + dev_warn(&pdev->dev, + "invalid crystal-freq specified in device-tree. Assuming no crystal\n"); + /* fall-through */ + case 0: + /* keep XTAL on in low-power mode */ + pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP; + pers0_clr = STMP3XXX_RTC_PERSISTENT0_XTAL32KHZ_PWRUP | + STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE; + } + + writel(pers0_set, rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET); + writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN | STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN | - STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE, + STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE | pers0_clr, rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR); writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN | -- cgit v1.2.3-58-ga151 From e706974dc3e2f44891e736f4a96eb88b60356178 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Thu, 16 Apr 2015 12:45:07 -0700 Subject: drivers/rtc/rtc-em3027.c: add device tree support Set the of_match_table for this driver so that devices can be described in the device tree. This device is used in the Trimslice and is already defined in the Trimslice device tree. Signed-off-by: Peter Robinson Cc: Mike Rapoport Cc: Alessandro Zummo Cc: Grant Likely Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-em3027.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-em3027.c b/drivers/rtc/rtc-em3027.c index fccf36699245..4f4930a2004c 100644 --- a/drivers/rtc/rtc-em3027.c +++ b/drivers/rtc/rtc-em3027.c @@ -15,6 +15,7 @@ #include #include #include +#include /* Registers */ #define EM3027_REG_ON_OFF_CTRL 0x00 @@ -135,10 +136,20 @@ static struct i2c_device_id em3027_id[] = { { "em3027", 0 }, { } }; +MODULE_DEVICE_TABLE(i2c, em3027_id); + +#ifdef CONFIG_OF +static const struct of_device_id em3027_of_match[] = { + { .compatible = "emmicro,em3027", }, + {} +}; +MODULE_DEVICE_TABLE(of, em3027_of_match); +#endif static struct i2c_driver em3027_driver = { .driver = { .name = "rtc-em3027", + .of_match_table = of_match_ptr(em3027_of_match), }, .probe = &em3027_probe, .id_table = em3027_id, -- cgit v1.2.3-58-ga151 From 86e66604fca053e5ecb2427538aa233637119409 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Thu, 16 Apr 2015 12:45:09 -0700 Subject: drivers/rtc/rtc-x1205.c: use sign_extend32() for sign extension Despite its name, sign_extend32() is safe to use for 8 bit types too. (See https://lkml.org/lkml/2015/1/18/289). Signed-off-by: Martin Kepplinger Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-x1205.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index b1de58e0b3d0..5638b7ba8b06 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c @@ -22,6 +22,7 @@ #include #include #include +#include #define DRV_VERSION "1.0.8" @@ -366,8 +367,7 @@ static int x1205_get_atrim(struct i2c_client *client, int *trim) * perform sign extension. The formula is * Catr = (atr * 0.25pF) + 11.00pF. */ - if (atr & 0x20) - atr |= 0xC0; + atr = sign_extend32(atr, 5); dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __func__, atr, atr); -- cgit v1.2.3-58-ga151 From aed98b9a1be6fcf1685dfd37f0a3e78e92a21f7d Mon Sep 17 00:00:00 2001 From: Floris Bos Date: Thu, 16 Apr 2015 12:45:12 -0700 Subject: rtc: hctosys: do not treat lack of RTC device as error When using device trees on the ARM platform, it is not certain at compile time whether or not the system will have a RTC. If one enables CONFIG_HCTOSYS just in case the system booted has a RTC, and it turns out not to be, this will result in a big fat "unable to open rtc device" error being printed to console, even when "quiet" is set in the kernel cmdline. Fix this by outputting the message with loglevel info instead. Signed-off-by: Floris Bos Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/hctosys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c index 6c719f23520a..fb4251de7ce1 100644 --- a/drivers/rtc/hctosys.c +++ b/drivers/rtc/hctosys.c @@ -32,7 +32,7 @@ static int __init rtc_hctosys(void) struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); if (rtc == NULL) { - pr_err("%s: unable to open rtc device (%s)\n", + pr_info("%s: unable to open rtc device (%s)\n", __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); goto err_open; } -- cgit v1.2.3-58-ga151 From 24e1455493dae5ce4b15f83d6ad549befd15f980 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 16 Apr 2015 12:45:15 -0700 Subject: drivers/rtc/rtc-s3c.c: delete duplicate clock control The current functions in s3c-rtc driver execute clk_enable/disable() to control clocks and some functions execute s3c_rtc_alarm_clk_enable() unnecessarily. So this patch deletes the duplicate clock control and spilts s3c_rtc_alarm_clk_enable() out as s3c_rtc_enable_clk()/s3c_rtc_disable_clk() to improve readability. Signed-off-by: Chanwoo Choi Cc: Alessandro Zummo Cc: Kukjin Kim Cc: Inki Dae Cc: Kyungmin Park Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-s3c.c | 163 ++++++++++++-------------------------------------- 1 file changed, 39 insertions(+), 124 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index f4cf6851fae9..fb0c569765c6 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -39,7 +39,6 @@ struct s3c_rtc { void __iomem *base; struct clk *rtc_clk; struct clk *rtc_src_clk; - bool enabled; struct s3c_rtc_data *data; @@ -67,26 +66,25 @@ struct s3c_rtc_data { void (*disable) (struct s3c_rtc *info); }; -static void s3c_rtc_alarm_clk_enable(struct s3c_rtc *info, bool enable) +static void s3c_rtc_enable_clk(struct s3c_rtc *info) { unsigned long irq_flags; spin_lock_irqsave(&info->alarm_clk_lock, irq_flags); - if (enable) { - if (!info->enabled) { - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); - info->enabled = true; - } - } else { - if (info->enabled) { - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); - info->enabled = false; - } - } + clk_enable(info->rtc_clk); + if (info->data->needs_src_clk) + clk_enable(info->rtc_src_clk); + spin_unlock_irqrestore(&info->alarm_clk_lock, irq_flags); +} + +static void s3c_rtc_disable_clk(struct s3c_rtc *info) +{ + unsigned long irq_flags; + + spin_lock_irqsave(&info->alarm_clk_lock, irq_flags); + if (info->data->needs_src_clk) + clk_disable(info->rtc_src_clk); + clk_disable(info->rtc_clk); spin_unlock_irqrestore(&info->alarm_clk_lock, irq_flags); } @@ -119,20 +117,16 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled) dev_dbg(info->dev, "%s: aie=%d\n", __func__, enabled); - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); + s3c_rtc_enable_clk(info); + tmp = readb(info->base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; if (enabled) tmp |= S3C2410_RTCALM_ALMEN; writeb(tmp, info->base + S3C2410_RTCALM); - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); - s3c_rtc_alarm_clk_enable(info, enabled); + s3c_rtc_disable_clk(info); return 0; } @@ -143,18 +137,12 @@ static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq) if (!is_power_of_2(freq)) return -EINVAL; - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); spin_lock_irq(&info->pie_lock); if (info->data->set_freq) info->data->set_freq(info, freq); spin_unlock_irq(&info->pie_lock); - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); return 0; } @@ -165,9 +153,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) struct s3c_rtc *info = dev_get_drvdata(dev); unsigned int have_retried = 0; - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); + s3c_rtc_enable_clk(info); retry_get_time: rtc_tm->tm_min = readb(info->base + S3C2410_RTCMIN); @@ -194,6 +180,8 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon); rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year); + s3c_rtc_disable_clk(info); + rtc_tm->tm_year += 100; dev_dbg(dev, "read time %04d.%02d.%02d %02d:%02d:%02d\n", @@ -202,10 +190,6 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) rtc_tm->tm_mon -= 1; - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); - return rtc_valid_tm(rtc_tm); } @@ -225,9 +209,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) return -EINVAL; } - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); + s3c_rtc_enable_clk(info); writeb(bin2bcd(tm->tm_sec), info->base + S3C2410_RTCSEC); writeb(bin2bcd(tm->tm_min), info->base + S3C2410_RTCMIN); @@ -236,9 +218,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_RTCMON); writeb(bin2bcd(year), info->base + S3C2410_RTCYEAR); - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); + s3c_rtc_disable_clk(info); return 0; } @@ -249,9 +229,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) struct rtc_time *alm_tm = &alrm->time; unsigned int alm_en; - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); + s3c_rtc_enable_clk(info); alm_tm->tm_sec = readb(info->base + S3C2410_ALMSEC); alm_tm->tm_min = readb(info->base + S3C2410_ALMMIN); @@ -262,6 +240,8 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) alm_en = readb(info->base + S3C2410_RTCALM); + s3c_rtc_disable_clk(info); + alrm->enabled = (alm_en & S3C2410_RTCALM_ALMEN) ? 1 : 0; dev_dbg(dev, "read alarm %d, %04d.%02d.%02d %02d:%02d:%02d\n", @@ -269,9 +249,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) 1900 + alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec); - /* decode the alarm enable field */ - if (alm_en & S3C2410_RTCALM_SECEN) alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); else @@ -304,10 +282,6 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) else alm_tm->tm_year = -1; - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); - return 0; } @@ -317,15 +291,13 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) struct rtc_time *tm = &alrm->time; unsigned int alrm_en; - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); - dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", alrm->enabled, 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); + s3c_rtc_enable_clk(info); + alrm_en = readb(info->base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; writeb(0x00, info->base + S3C2410_RTCALM); @@ -348,11 +320,9 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) writeb(alrm_en, info->base + S3C2410_RTCALM); - s3c_rtc_setaie(dev, alrm->enabled); + s3c_rtc_disable_clk(info); - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); + s3c_rtc_setaie(dev, alrm->enabled); return 0; } @@ -361,16 +331,12 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) { struct s3c_rtc *info = dev_get_drvdata(dev); - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); + s3c_rtc_enable_clk(info); if (info->data->enable_tick) info->data->enable_tick(info, seq); - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); + s3c_rtc_disable_clk(info); return 0; } @@ -388,10 +354,6 @@ static void s3c24xx_rtc_enable(struct s3c_rtc *info) { unsigned int con, tmp; - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); - con = readw(info->base + S3C2410_RTCCON); /* re-enable the device, and check it is ok */ if ((con & S3C2410_RTCCON_RTCEN) == 0) { @@ -417,20 +379,12 @@ static void s3c24xx_rtc_enable(struct s3c_rtc *info) writew(tmp & ~S3C2410_RTCCON_CLKRST, info->base + S3C2410_RTCCON); } - - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); } static void s3c24xx_rtc_disable(struct s3c_rtc *info) { unsigned int con; - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); - con = readw(info->base + S3C2410_RTCCON); con &= ~S3C2410_RTCCON_RTCEN; writew(con, info->base + S3C2410_RTCCON); @@ -438,28 +392,16 @@ static void s3c24xx_rtc_disable(struct s3c_rtc *info) con = readb(info->base + S3C2410_TICNT); con &= ~S3C2410_TICNT_ENABLE; writeb(con, info->base + S3C2410_TICNT); - - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); } static void s3c6410_rtc_disable(struct s3c_rtc *info) { unsigned int con; - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); - con = readw(info->base + S3C2410_RTCCON); con &= ~S3C64XX_RTCCON_TICEN; con &= ~S3C2410_RTCCON_RTCEN; writew(con, info->base + S3C2410_RTCCON); - - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); } static int s3c_rtc_remove(struct platform_device *pdev) @@ -598,15 +540,16 @@ static int s3c_rtc_probe(struct platform_device *pdev) s3c_rtc_setfreq(info, 1); - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); + s3c_rtc_disable_clk(info); return 0; err_nortc: if (info->data->disable) info->data->disable(info); + + if (info->data->needs_src_clk) + clk_disable_unprepare(info->rtc_src_clk); clk_disable_unprepare(info->rtc_clk); return ret; @@ -618,9 +561,7 @@ static int s3c_rtc_suspend(struct device *dev) { struct s3c_rtc *info = dev_get_drvdata(dev); - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); + s3c_rtc_enable_clk(info); /* save TICNT for anyone using periodic interrupts */ if (info->data->save_tick_cnt) @@ -636,10 +577,6 @@ static int s3c_rtc_suspend(struct device *dev) dev_err(dev, "enable_irq_wake failed\n"); } - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); - return 0; } @@ -647,25 +584,19 @@ static int s3c_rtc_resume(struct device *dev) { struct s3c_rtc *info = dev_get_drvdata(dev); - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); - if (info->data->enable) info->data->enable(info); if (info->data->restore_tick_cnt) info->data->restore_tick_cnt(info); + s3c_rtc_disable_clk(info); + if (device_may_wakeup(dev) && info->wake_en) { disable_irq_wake(info->irq_alarm); info->wake_en = false; } - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); - return 0; } #endif @@ -673,29 +604,13 @@ static SIMPLE_DEV_PM_OPS(s3c_rtc_pm_ops, s3c_rtc_suspend, s3c_rtc_resume); static void s3c24xx_rtc_irq(struct s3c_rtc *info, int mask) { - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF); - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); - - s3c_rtc_alarm_clk_enable(info, false); } static void s3c6410_rtc_irq(struct s3c_rtc *info, int mask) { - clk_enable(info->rtc_clk); - if (info->data->needs_src_clk) - clk_enable(info->rtc_src_clk); rtc_update_irq(info->rtc, 1, RTC_AF | RTC_IRQF); writeb(mask, info->base + S3C2410_INTP); - if (info->data->needs_src_clk) - clk_disable(info->rtc_src_clk); - clk_disable(info->rtc_clk); - - s3c_rtc_alarm_clk_enable(info, false); } static void s3c2410_rtc_setfreq(struct s3c_rtc *info, int freq) -- cgit v1.2.3-58-ga151 From ac2a2726661a8f8f74af0d499cb16b3adf90d764 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 16 Apr 2015 12:45:18 -0700 Subject: drivers/rtc/rtc-ab-b5ze-s3.c: constify struct regmap_config The regmap_config struct may be const because it is not modified by the driver and regmap_init() accepts pointer to const. Signed-off-by: Krzysztof Kozlowski Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-ab-b5ze-s3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ab-b5ze-s3.c b/drivers/rtc/rtc-ab-b5ze-s3.c index cfc2ef98d393..b5cbc1bf5a3e 100644 --- a/drivers/rtc/rtc-ab-b5ze-s3.c +++ b/drivers/rtc/rtc-ab-b5ze-s3.c @@ -881,7 +881,7 @@ static const struct rtc_class_ops rtc_ops = { .alarm_irq_enable = abb5zes3_rtc_alarm_irq_enable, }; -static struct regmap_config abb5zes3_rtc_regmap_config = { +static const struct regmap_config abb5zes3_rtc_regmap_config = { .reg_bits = 8, .val_bits = 8, }; -- cgit v1.2.3-58-ga151 From 269812de8b1c28cd477a3f9cc9793047f0de530e Mon Sep 17 00:00:00 2001 From: Joshua Kinard Date: Thu, 16 Apr 2015 12:45:21 -0700 Subject: drivers/rtc/rtc-ds1685.c: remove .owner assignment from platform_driver The rtc driver core now sets the platform_driver 'owner' property, so remove the assignment from the DS1685 driver. Fixes: aaaf5fbf56f1: "rtc: add driver for DS1685 family of real time clocks" Signed-off-by: Joshua Kinard Reported-by: kbuild test robot Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-ds1685.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index 803869c7d7c2..7a7c8de7c92c 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -2139,7 +2139,6 @@ ds1685_rtc_remove(struct platform_device *pdev) static struct platform_driver ds1685_rtc_driver = { .driver = { .name = "rtc-ds1685", - .owner = THIS_MODULE, }, .probe = ds1685_rtc_probe, .remove = ds1685_rtc_remove, -- cgit v1.2.3-58-ga151 From 52ef84d566dc145b4d469f06667c5fa3118fdd44 Mon Sep 17 00:00:00 2001 From: Joshua Kinard Date: Thu, 16 Apr 2015 12:45:23 -0700 Subject: drivers/rtc/rtc-ds1685.c: fix sparse warnings Fix two minor sparse warnings: CHECK drivers/rtc/rtc-ds1685.c drivers/rtc/rtc-ds1685.c:2178:1: warning: function 'ds1685_rtc_poweroff' with external linkage has definition drivers/rtc/rtc-ds1685.c:802:23: warning: Using plain integer as NULL pointer Fixes: aaaf5fbf56f1 ("rtc: add driver for DS1685 family of real time clocks") Signed-off-by: Joshua Kinard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-ds1685.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index 7a7c8de7c92c..70202098a8ce 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -799,7 +799,7 @@ ds1685_rtc_proc(struct device *dev, struct seq_file *seq) struct platform_device *pdev = to_platform_device(dev); struct ds1685_priv *rtc = platform_get_drvdata(pdev); u8 ctrla, ctrlb, ctrlc, ctrld, ctrl4a, ctrl4b, ssn[8]; - char *model = '\0'; + char *model; #ifdef CONFIG_RTC_DS1685_PROC_REGS char bits[NUM_REGS][(NUM_BITS * NUM_SPACES) + NUM_BITS + 1]; #endif @@ -2174,7 +2174,7 @@ module_exit(ds1685_rtc_exit); * ds1685_rtc_poweroff - uses the RTC chip to power the system off. * @pdev: pointer to platform_device structure. */ -extern void __noreturn +void __noreturn ds1685_rtc_poweroff(struct platform_device *pdev) { u8 ctrla, ctrl4a, ctrl4b; -- cgit v1.2.3-58-ga151 From 03cc1625e1f2e9fc6910af4174c942d56292f556 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Thu, 16 Apr 2015 12:45:26 -0700 Subject: drivers/rtc/rtc-da9052.c: add extra reads with timeouts to avoid returning partially updated values The RTC is in a different clock domain so a quick read after write can retrieve a mangled value of the old/new values Signed-off-by: Adam Ward Tested-by: Adam Ward Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-da9052.c | 87 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c index 613c43b7e9ae..ead02fad2de5 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -23,6 +24,8 @@ #define rtc_err(rtc, fmt, ...) \ dev_err(rtc->da9052->dev, "%s: " fmt, __func__, ##__VA_ARGS__) +#define DA9052_GET_TIME_RETRIES 5 + struct da9052_rtc { struct rtc_device *rtc; struct da9052 *da9052; @@ -58,22 +61,43 @@ static irqreturn_t da9052_rtc_irq(int irq, void *data) static int da9052_read_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm) { int ret; - uint8_t v[5]; + uint8_t v[2][5]; + int idx = 1; + int timeout = DA9052_GET_TIME_RETRIES; - ret = da9052_group_read(rtc->da9052, DA9052_ALARM_MI_REG, 5, v); - if (ret != 0) { + ret = da9052_group_read(rtc->da9052, DA9052_ALARM_MI_REG, 5, &v[0][0]); + if (ret) { rtc_err(rtc, "Failed to group read ALM: %d\n", ret); return ret; } - rtc_tm->tm_year = (v[4] & DA9052_RTC_YEAR) + 100; - rtc_tm->tm_mon = (v[3] & DA9052_RTC_MONTH) - 1; - rtc_tm->tm_mday = v[2] & DA9052_RTC_DAY; - rtc_tm->tm_hour = v[1] & DA9052_RTC_HOUR; - rtc_tm->tm_min = v[0] & DA9052_RTC_MIN; + do { + ret = da9052_group_read(rtc->da9052, + DA9052_ALARM_MI_REG, 5, &v[idx][0]); + if (ret) { + rtc_err(rtc, "Failed to group read ALM: %d\n", ret); + return ret; + } - ret = rtc_valid_tm(rtc_tm); - return ret; + if (memcmp(&v[0][0], &v[1][0], 5) == 0) { + rtc_tm->tm_year = (v[0][4] & DA9052_RTC_YEAR) + 100; + rtc_tm->tm_mon = (v[0][3] & DA9052_RTC_MONTH) - 1; + rtc_tm->tm_mday = v[0][2] & DA9052_RTC_DAY; + rtc_tm->tm_hour = v[0][1] & DA9052_RTC_HOUR; + rtc_tm->tm_min = v[0][0] & DA9052_RTC_MIN; + + ret = rtc_valid_tm(rtc_tm); + return ret; + } + + idx = (1-idx); + msleep(20); + + } while (timeout--); + + rtc_err(rtc, "Timed out reading alarm time\n"); + + return -EIO; } static int da9052_set_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm) @@ -135,24 +159,45 @@ static int da9052_rtc_get_alarm_status(struct da9052_rtc *rtc) static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) { struct da9052_rtc *rtc = dev_get_drvdata(dev); - uint8_t v[6]; int ret; + uint8_t v[2][6]; + int idx = 1; + int timeout = DA9052_GET_TIME_RETRIES; - ret = da9052_group_read(rtc->da9052, DA9052_COUNT_S_REG, 6, v); - if (ret < 0) { + ret = da9052_group_read(rtc->da9052, DA9052_COUNT_S_REG, 6, &v[0][0]); + if (ret) { rtc_err(rtc, "Failed to read RTC time : %d\n", ret); return ret; } - rtc_tm->tm_year = (v[5] & DA9052_RTC_YEAR) + 100; - rtc_tm->tm_mon = (v[4] & DA9052_RTC_MONTH) - 1; - rtc_tm->tm_mday = v[3] & DA9052_RTC_DAY; - rtc_tm->tm_hour = v[2] & DA9052_RTC_HOUR; - rtc_tm->tm_min = v[1] & DA9052_RTC_MIN; - rtc_tm->tm_sec = v[0] & DA9052_RTC_SEC; + do { + ret = da9052_group_read(rtc->da9052, + DA9052_COUNT_S_REG, 6, &v[idx][0]); + if (ret) { + rtc_err(rtc, "Failed to read RTC time : %d\n", ret); + return ret; + } - ret = rtc_valid_tm(rtc_tm); - return ret; + if (memcmp(&v[0][0], &v[1][0], 6) == 0) { + rtc_tm->tm_year = (v[0][5] & DA9052_RTC_YEAR) + 100; + rtc_tm->tm_mon = (v[0][4] & DA9052_RTC_MONTH) - 1; + rtc_tm->tm_mday = v[0][3] & DA9052_RTC_DAY; + rtc_tm->tm_hour = v[0][2] & DA9052_RTC_HOUR; + rtc_tm->tm_min = v[0][1] & DA9052_RTC_MIN; + rtc_tm->tm_sec = v[0][0] & DA9052_RTC_SEC; + + ret = rtc_valid_tm(rtc_tm); + return ret; + } + + idx = (1-idx); + msleep(20); + + } while (timeout--); + + rtc_err(rtc, "Timed out reading time\n"); + + return -EIO; } static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm) -- cgit v1.2.3-58-ga151 From ae824c484c85d77e3f272515aafb410bbade13fa Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Thu, 16 Apr 2015 12:45:29 -0700 Subject: drivers/rtc/rtc-da9052.c: add constraints to set valid year Signed-off-by: Adam Ward Tested-by: Adam Ward Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-da9052.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c index ead02fad2de5..acc3e5a1f61a 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c @@ -206,6 +206,10 @@ static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm) uint8_t v[6]; int ret; + /* DA9052 only has 6 bits for year - to represent 2000-2063 */ + if ((tm->tm_year < 100) || (tm->tm_year > 163)) + return -EINVAL; + rtc = dev_get_drvdata(dev); v[0] = tm->tm_sec; @@ -243,6 +247,10 @@ static int da9052_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) struct rtc_time *tm = &alrm->time; struct da9052_rtc *rtc = dev_get_drvdata(dev); + /* DA9052 only has 6 bits for year - to represent 2000-2063 */ + if ((tm->tm_year < 100) || (tm->tm_year > 163)) + return -EINVAL; + ret = da9052_rtc_enable_alarm(rtc, 0); if (ret < 0) return ret; -- cgit v1.2.3-58-ga151 From d174a024007dd543fd066cffd8eb727806a62da6 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Thu, 16 Apr 2015 12:45:32 -0700 Subject: drivers/rtc/rtc-da9052.c: register ability of alarm to wake device from suspend Signed-off-by: Adam Ward Tested-by: Adam Ward Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-da9052.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c index acc3e5a1f61a..1ba4371cbc2d 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c @@ -309,6 +309,8 @@ static int da9052_rtc_probe(struct platform_device *pdev) return ret; } + device_init_wakeup(&pdev->dev, true); + rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &da9052_rtc_ops, THIS_MODULE); return PTR_ERR_OR_ZERO(rtc->rtc); -- cgit v1.2.3-58-ga151 From b3288a43b4dacd2b4d2b24726d7b469d8ade5120 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 16 Apr 2015 12:45:34 -0700 Subject: drivers/rtc/rtc-hym8563.c: return clock rate even when clock is disabled When the clock is disabled, do not return a rate of 0 but instead return the rate the clock will be running at after it gets enabled. This prevents problems when the core clock code is trying to determine a suitable rate, while the clock is still off. Signed-off-by: Heiko Stuebner Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-hym8563.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c index b936bb4096b5..d4a65619ef14 100644 --- a/drivers/rtc/rtc-hym8563.c +++ b/drivers/rtc/rtc-hym8563.c @@ -309,7 +309,7 @@ static unsigned long hym8563_clkout_recalc_rate(struct clk_hw *hw, struct i2c_client *client = hym8563->client; int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT); - if (ret < 0 || ret & HYM8563_CLKOUT_DISABLE) + if (ret < 0) return 0; ret &= HYM8563_CLKOUT_MASK; -- cgit v1.2.3-58-ga151 From ba17220878bf74b95ea24de568939e7b9e1b02db Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 16 Apr 2015 12:45:40 -0700 Subject: rtc: driver for Conexant Digicolor CX92755 on-chip RTC Add driver for the RTC hardware block on the Conexant CX92755 SoC, from the Digicolor series of SoCs. Tested on the Equinox evaluation board for the CX92755 chip. [akpm@linux-foundation.org: build command arrays at compile-time] Signed-off-by: Baruch Siach Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 10 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-digicolor.c | 227 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 238 insertions(+) create mode 100644 drivers/rtc/rtc-digicolor.c (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index b5b5c3d485d6..faeee2d2550b 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1111,6 +1111,16 @@ config RTC_DRV_DAVINCI This driver can also be built as a module. If so, the module will be called rtc-davinci. +config RTC_DRV_DIGICOLOR + tristate "Conexant Digicolor RTC" + depends on ARCH_DIGICOLOR + help + If you say yes here you get support for the RTC on Conexant + Digicolor platforms. This currently includes the CX92755 SoC. + + This driver can also be built as a module. If so, the module + will be called rtc-digicolor. + config RTC_DRV_IMXDI tristate "Freescale IMX DryIce Real Time Clock" depends on ARCH_MXC diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 69c87062b098..c31731c29762 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_RTC_DRV_DA9052) += rtc-da9052.o obj-$(CONFIG_RTC_DRV_DA9055) += rtc-da9055.o obj-$(CONFIG_RTC_DRV_DA9063) += rtc-da9063.o obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o +obj-$(CONFIG_RTC_DRV_DIGICOLOR) += rtc-digicolor.o obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o diff --git a/drivers/rtc/rtc-digicolor.c b/drivers/rtc/rtc-digicolor.c new file mode 100644 index 000000000000..8d05596a6765 --- /dev/null +++ b/drivers/rtc/rtc-digicolor.c @@ -0,0 +1,227 @@ +/* + * Real Time Clock driver for Conexant Digicolor + * + * Copyright (C) 2015 Paradox Innovation Ltd. + * + * Author: Baruch Siach + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DC_RTC_CONTROL 0x0 +#define DC_RTC_TIME 0x8 +#define DC_RTC_REFERENCE 0xc +#define DC_RTC_ALARM 0x10 +#define DC_RTC_INTFLAG_CLEAR 0x14 +#define DC_RTC_INTENABLE 0x16 + +#define DC_RTC_CMD_MASK 0xf +#define DC_RTC_GO_BUSY BIT(7) + +#define CMD_NOP 0 +#define CMD_RESET 1 +#define CMD_WRITE 3 +#define CMD_READ 4 + +#define CMD_DELAY_US (10*1000) +#define CMD_TIMEOUT_US (500*CMD_DELAY_US) + +struct dc_rtc { + struct rtc_device *rtc_dev; + void __iomem *regs; +}; + +static int dc_rtc_cmds(struct dc_rtc *rtc, const u8 *cmds, int len) +{ + u8 val; + int i, ret; + + for (i = 0; i < len; i++) { + writeb_relaxed((cmds[i] & DC_RTC_CMD_MASK) | DC_RTC_GO_BUSY, + rtc->regs + DC_RTC_CONTROL); + ret = readb_relaxed_poll_timeout( + rtc->regs + DC_RTC_CONTROL, val, + !(val & DC_RTC_GO_BUSY), CMD_DELAY_US, CMD_TIMEOUT_US); + if (ret < 0) + return ret; + } + + return 0; +} + +static int dc_rtc_read(struct dc_rtc *rtc, unsigned long *val) +{ + static const u8 read_cmds[] = {CMD_READ, CMD_NOP}; + u32 reference, time1, time2; + int ret; + + ret = dc_rtc_cmds(rtc, read_cmds, ARRAY_SIZE(read_cmds)); + if (ret < 0) + return ret; + + reference = readl_relaxed(rtc->regs + DC_RTC_REFERENCE); + time1 = readl_relaxed(rtc->regs + DC_RTC_TIME); + /* Read twice to ensure consistency */ + while (1) { + time2 = readl_relaxed(rtc->regs + DC_RTC_TIME); + if (time1 == time2) + break; + time1 = time2; + } + + *val = reference + time1; + return 0; +} + +static int dc_rtc_write(struct dc_rtc *rtc, u32 val) +{ + static const u8 write_cmds[] = {CMD_WRITE, CMD_NOP, CMD_RESET, CMD_NOP}; + + writel_relaxed(val, rtc->regs + DC_RTC_REFERENCE); + return dc_rtc_cmds(rtc, write_cmds, ARRAY_SIZE(write_cmds)); +} + +static int dc_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct dc_rtc *rtc = dev_get_drvdata(dev); + unsigned long now; + int ret; + + ret = dc_rtc_read(rtc, &now); + if (ret < 0) + return ret; + rtc_time64_to_tm(now, tm); + + return 0; +} + +static int dc_rtc_set_mmss(struct device *dev, unsigned long secs) +{ + struct dc_rtc *rtc = dev_get_drvdata(dev); + + return dc_rtc_write(rtc, secs); +} + +static int dc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct dc_rtc *rtc = dev_get_drvdata(dev); + u32 alarm_reg, reference; + unsigned long now; + int ret; + + alarm_reg = readl_relaxed(rtc->regs + DC_RTC_ALARM); + reference = readl_relaxed(rtc->regs + DC_RTC_REFERENCE); + rtc_time64_to_tm(reference + alarm_reg, &alarm->time); + + ret = dc_rtc_read(rtc, &now); + if (ret < 0) + return ret; + + alarm->pending = alarm_reg + reference > now; + alarm->enabled = readl_relaxed(rtc->regs + DC_RTC_INTENABLE); + + return 0; +} + +static int dc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct dc_rtc *rtc = dev_get_drvdata(dev); + time64_t alarm_time; + u32 reference; + + alarm_time = rtc_tm_to_time64(&alarm->time); + + reference = readl_relaxed(rtc->regs + DC_RTC_REFERENCE); + writel_relaxed(alarm_time - reference, rtc->regs + DC_RTC_ALARM); + + writeb_relaxed(!!alarm->enabled, rtc->regs + DC_RTC_INTENABLE); + + return 0; +} + +static int dc_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct dc_rtc *rtc = dev_get_drvdata(dev); + + writeb_relaxed(!!enabled, rtc->regs + DC_RTC_INTENABLE); + + return 0; +} + +static struct rtc_class_ops dc_rtc_ops = { + .read_time = dc_rtc_read_time, + .set_mmss = dc_rtc_set_mmss, + .read_alarm = dc_rtc_read_alarm, + .set_alarm = dc_rtc_set_alarm, + .alarm_irq_enable = dc_rtc_alarm_irq_enable, +}; + +static irqreturn_t dc_rtc_irq(int irq, void *dev_id) +{ + struct dc_rtc *rtc = dev_id; + + writeb_relaxed(1, rtc->regs + DC_RTC_INTFLAG_CLEAR); + rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); + + return IRQ_HANDLED; +} + +static int __init dc_rtc_probe(struct platform_device *pdev) +{ + struct resource *res; + struct dc_rtc *rtc; + int irq, ret; + + rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); + if (!rtc) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + rtc->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(rtc->regs)) + return PTR_ERR(rtc->regs); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + ret = devm_request_irq(&pdev->dev, irq, dc_rtc_irq, 0, pdev->name, rtc); + if (ret < 0) + return ret; + + platform_set_drvdata(pdev, rtc); + rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name, + &dc_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc->rtc_dev)) + return PTR_ERR(rtc->rtc_dev); + + return 0; +} + +static const struct of_device_id dc_dt_ids[] = { + { .compatible = "cnxt,cx92755-rtc" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, dc_dt_ids); + +static struct platform_driver dc_rtc_driver = { + .driver = { + .name = "digicolor_rtc", + .of_match_table = of_match_ptr(dc_dt_ids), + }, +}; +module_platform_driver_probe(dc_rtc_driver, dc_rtc_probe); + +MODULE_AUTHOR("Baruch Siach "); +MODULE_DESCRIPTION("Conexant Digicolor Realtime Clock Driver (RTC)"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-58-ga151 From 5281f94ae7f54d2d1a48dbc10223fd12d2aea716 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 16 Apr 2015 12:45:45 -0700 Subject: drivers/rtc/rtc-s5m.c: add support for S2MPS13 RTC The S2MPS13 RTC is almost the same as S2MPS14. The differences when updating alarm are: 1. Set WUDR+AUDR field instead of WUDR+RUDR. 2. Clear the AUDR field later (it is not auto-cleared). Signed-off-by: Krzysztof Kozlowski Cc: Alexandre Belloni Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-s5m.c | 20 +++++++++++++++++++- include/linux/mfd/samsung/rtc.h | 2 ++ 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index 4008b84246ca..f0cb0ecb3d8d 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c @@ -187,6 +187,7 @@ static inline int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info, val &= S5M_ALARM0_STATUS; break; case S2MPS14X: + case S2MPS13X: ret = regmap_read(info->s5m87xx->regmap_pmic, S2MPS14_REG_ST2, &val); val &= S2MPS_ALARM0_STATUS; @@ -252,6 +253,9 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info) case S2MPS14X: data |= S2MPS_RTC_RUDR_MASK; break; + case S2MPS13X: + data |= S2MPS13_RTC_AUDR_MASK; + break; default: return -EINVAL; } @@ -265,6 +269,11 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info) ret = s5m8767_wait_for_udr_update(info); + /* On S2MPS13 the AUDR is not auto-cleared */ + if (info->device_type == S2MPS13X) + regmap_update_bits(info->regmap, info->regs->rtc_udr_update, + S2MPS13_RTC_AUDR_MASK, 0); + return ret; } @@ -306,7 +315,7 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm) u8 data[info->regs->regs_count]; int ret; - if (info->device_type == S2MPS14X) { + if (info->device_type == S2MPS14X || info->device_type == S2MPS13X) { ret = regmap_update_bits(info->regmap, info->regs->rtc_udr_update, S2MPS_RTC_RUDR_MASK, S2MPS_RTC_RUDR_MASK); @@ -329,6 +338,7 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm) case S5M8767X: case S2MPS14X: + case S2MPS13X: s5m8767_data_to_tm(data, tm, info->rtc_24hr_mode); break; @@ -355,6 +365,7 @@ static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm) break; case S5M8767X: case S2MPS14X: + case S2MPS13X: ret = s5m8767_tm_to_data(tm, data); break; default: @@ -402,6 +413,7 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) case S5M8767X: case S2MPS14X: + case S2MPS13X: s5m8767_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); alrm->enabled = 0; for (i = 0; i < info->regs->regs_count; i++) { @@ -450,6 +462,7 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info) case S5M8767X: case S2MPS14X: + case S2MPS13X: for (i = 0; i < info->regs->regs_count; i++) data[i] &= ~ALARM_ENABLE_MASK; @@ -494,6 +507,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info) case S5M8767X: case S2MPS14X: + case S2MPS13X: data[RTC_SEC] |= ALARM_ENABLE_MASK; data[RTC_MIN] |= ALARM_ENABLE_MASK; data[RTC_HOUR] |= ALARM_ENABLE_MASK; @@ -533,6 +547,7 @@ static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) case S5M8767X: case S2MPS14X: + case S2MPS13X: s5m8767_tm_to_data(&alrm->time, data); break; @@ -615,6 +630,7 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info) break; case S2MPS14X: + case S2MPS13X: data[0] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); ret = regmap_write(info->regmap, info->regs->ctrl, data[0]); break; @@ -652,6 +668,7 @@ static int s5m_rtc_probe(struct platform_device *pdev) switch (pdata->device_type) { case S2MPS14X: + case S2MPS13X: regmap_cfg = &s2mps14_rtc_regmap_config; info->regs = &s2mps_rtc_regs; alarm_irq = S2MPS14_IRQ_RTCA0; @@ -772,6 +789,7 @@ static SIMPLE_DEV_PM_OPS(s5m_rtc_pm_ops, s5m_rtc_suspend, s5m_rtc_resume); static const struct platform_device_id s5m_rtc_id[] = { { "s5m-rtc", S5M8767X }, + { "s2mps13-rtc", S2MPS13X }, { "s2mps14-rtc", S2MPS14X }, { }, }; diff --git a/include/linux/mfd/samsung/rtc.h b/include/linux/mfd/samsung/rtc.h index b6401e7661c7..29c30ac36020 100644 --- a/include/linux/mfd/samsung/rtc.h +++ b/include/linux/mfd/samsung/rtc.h @@ -105,6 +105,8 @@ enum s2mps_rtc_reg { #define S5M_RTC_UDR_MASK (1 << S5M_RTC_UDR_SHIFT) #define S2MPS_RTC_WUDR_SHIFT 4 #define S2MPS_RTC_WUDR_MASK (1 << S2MPS_RTC_WUDR_SHIFT) +#define S2MPS13_RTC_AUDR_SHIFT 1 +#define S2MPS13_RTC_AUDR_MASK (1 << S2MPS13_RTC_AUDR_SHIFT) #define S2MPS_RTC_RUDR_SHIFT 0 #define S2MPS_RTC_RUDR_MASK (1 << S2MPS_RTC_RUDR_SHIFT) #define RTC_TCON_SHIFT 1 -- cgit v1.2.3-58-ga151 From 182683e955af4dd2324427129f3b90558d644066 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Thu, 16 Apr 2015 12:45:48 -0700 Subject: drivers/rtc/class.c: initialize rtc name early In some error cases RTC name is used before it is initialized: rtc-rs5c372 0-0032: clock needs to be set rtc-rs5c372 0-0032: rs5c372b found, 24hr, driver version 0.6 rtc (null): read_time: fail to read rtc-rs5c372 0-0032: rtc core: registered rtc-rs5c372 as rtc0 Fix by initializing the name early. Signed-off-by: Aaro Koskinen Acked-by: Alexandre Belloni Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/class.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index c29ba7e14304..ea2a315df6b7 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -221,15 +221,15 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, rtc->pie_timer.function = rtc_pie_update_irq; rtc->pie_enabled = 0; + strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); + dev_set_name(&rtc->dev, "rtc%d", id); + /* Check to see if there is an ALARM already set in hw */ err = __rtc_read_alarm(rtc, &alrm); if (!err && !rtc_valid_tm(&alrm.time)) rtc_initialize_alarm(rtc, &alrm); - strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); - dev_set_name(&rtc->dev, "rtc%d", id); - rtc_dev_prepare(rtc); err = device_register(&rtc->dev); -- cgit v1.2.3-58-ga151 From d0bddb512d9c8e1adefc7416ef6c71cba05d62c8 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Thu, 16 Apr 2015 12:45:51 -0700 Subject: drivers/rtc/interface.c: __rtc_read_time: reduce log level __rtc_read_time logs should be debug logs instead of error logs. For example, when the RTC clock is not set, it's not really useful to print a kernel error log every time someone tries to read the clock: ~ # hwclock -r [ 604.508263] rtc rtc0: read_time: fail to read hwclock: RTC_RD_TIME: Invalid argument If there's a real error, it's likely that lower level or higher level code will tell it anyway. Make these logs debug logs, and also print the error code for the read failure. Signed-off-by: Aaro Koskinen Acked-by: Alexandre Belloni Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/interface.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index d43ee409a5f2..166fc60d8b55 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -31,13 +31,14 @@ static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) memset(tm, 0, sizeof(struct rtc_time)); err = rtc->ops->read_time(rtc->dev.parent, tm); if (err < 0) { - dev_err(&rtc->dev, "read_time: fail to read\n"); + dev_dbg(&rtc->dev, "read_time: fail to read: %d\n", + err); return err; } err = rtc_valid_tm(tm); if (err < 0) - dev_err(&rtc->dev, "read_time: rtc_time isn't valid\n"); + dev_dbg(&rtc->dev, "read_time: rtc_time isn't valid\n"); } return err; } -- cgit v1.2.3-58-ga151 From 521fca18e828cddc94535a1ea5ac33460f1de679 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Thu, 16 Apr 2015 12:45:54 -0700 Subject: rtc: hctosys: use function name in the error log Use function name in the error log instead of __FILE__. Signed-off-by: Aaro Koskinen Cc: Alexandre Belloni Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/hctosys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c index fb4251de7ce1..91fb5f3c1051 100644 --- a/drivers/rtc/hctosys.c +++ b/drivers/rtc/hctosys.c @@ -33,7 +33,7 @@ static int __init rtc_hctosys(void) if (rtc == NULL) { pr_info("%s: unable to open rtc device (%s)\n", - __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); + __func__, CONFIG_RTC_HCTOSYS_DEVICE); goto err_open; } -- cgit v1.2.3-58-ga151 From 202fe4c27f427c48ca5660277d743ee8b43fc200 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 16 Apr 2015 12:45:57 -0700 Subject: drivers/rtc/rtc-s3c.c: fix failed first read of RTC time Initialize the device time (if it is wrong) before registering RTC device to fix following error message during rtc-s3c probe: [ 2.215414] rtc (null): read_time: fail to read [ 2.216322] s3c-rtc 10070000.rtc: rtc core: registered s3c as rtc1 Signed-off-by: Krzysztof Kozlowski Cc: Alessandro Zummo Cc: Alexandre Belloni Cc: Marek Szyprowski Reviewed-by: Chanwoo Choi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-s3c.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index fb0c569765c6..a313b9b5a27e 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -496,6 +496,22 @@ static int s3c_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); + /* Check RTC Time */ + s3c_rtc_gettime(&pdev->dev, &rtc_tm); + + if (rtc_valid_tm(&rtc_tm)) { + rtc_tm.tm_year = 100; + rtc_tm.tm_mon = 0; + rtc_tm.tm_mday = 1; + rtc_tm.tm_hour = 0; + rtc_tm.tm_min = 0; + rtc_tm.tm_sec = 0; + + s3c_rtc_settime(&pdev->dev, &rtc_tm); + + dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n"); + } + /* register RTC and exit */ info->rtc = devm_rtc_device_register(&pdev->dev, "s3c", &s3c_rtcops, THIS_MODULE); @@ -519,22 +535,6 @@ static int s3c_rtc_probe(struct platform_device *pdev) goto err_nortc; } - /* Check RTC Time */ - s3c_rtc_gettime(&pdev->dev, &rtc_tm); - - if (rtc_valid_tm(&rtc_tm)) { - rtc_tm.tm_year = 100; - rtc_tm.tm_mon = 0; - rtc_tm.tm_mday = 1; - rtc_tm.tm_hour = 0; - rtc_tm.tm_min = 0; - rtc_tm.tm_sec = 0; - - s3c_rtc_settime(&pdev->dev, &rtc_tm); - - dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n"); - } - if (info->data->select_tick_clk) info->data->select_tick_clk(info); -- cgit v1.2.3-58-ga151 From 9c28bd07c20776cc04aecf04ba5be53fa5fa6dd2 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Thu, 16 Apr 2015 12:46:00 -0700 Subject: drivers/rtc/rtc-omap.c: unlock and lock rtc registers before and after register writes RTC module contains a kicker mechanism to prevent any spurious writes from changing the register values. This mechanism requires two MMR writes to the KICK0 and KICK1 registers with exact data values before the kicker lock mechanism is released. Currently the driver release the lock in the probe and leaves it enabled until the rtc driver removal. This eliminates the idea of preventing spurious writes when RTC driver is loaded. So implement rtc lock and unlock functions before and after register writes. This is as advised by Paul to implement lock and unlock functions in the driver and not to unlock and leave it in probe. The same discussion can be seen here: http://www.mail-archive.com/linux-omap%40vger.kernel.org/msg111588.html Signed-off-by: Lokesh Vutla Acked-by: Alexandre Belloni Cc: Alessandro Zummo Cc: Paul Walmsley Cc: Tero Kristo Cc: Sekhar Nori Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-omap.c | 63 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 8e5851aa4369..a5ff00931360 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -118,12 +118,15 @@ #define KICK0_VALUE 0x83e70b13 #define KICK1_VALUE 0x95a4f1e0 +struct omap_rtc; + struct omap_rtc_device_type { bool has_32kclk_en; - bool has_kicker; bool has_irqwakeen; bool has_pmic_mode; bool has_power_up_reset; + void (*lock)(struct omap_rtc *rtc); + void (*unlock)(struct omap_rtc *rtc); }; struct omap_rtc { @@ -156,6 +159,26 @@ static inline void rtc_writel(struct omap_rtc *rtc, unsigned int reg, u32 val) writel(val, rtc->base + reg); } +static void am3352_rtc_unlock(struct omap_rtc *rtc) +{ + rtc_writel(rtc, OMAP_RTC_KICK0_REG, KICK0_VALUE); + rtc_writel(rtc, OMAP_RTC_KICK1_REG, KICK1_VALUE); +} + +static void am3352_rtc_lock(struct omap_rtc *rtc) +{ + rtc_writel(rtc, OMAP_RTC_KICK0_REG, 0); + rtc_writel(rtc, OMAP_RTC_KICK1_REG, 0); +} + +static void default_rtc_unlock(struct omap_rtc *rtc) +{ +} + +static void default_rtc_lock(struct omap_rtc *rtc) +{ +} + /* * We rely on the rtc framework to handle locking (rtc->ops_lock), * so the only other requirement is that register accesses which @@ -186,7 +209,9 @@ static irqreturn_t rtc_irq(int irq, void *dev_id) /* alarm irq? */ if (irq_data & OMAP_RTC_STATUS_ALARM) { + rtc->type->unlock(rtc); rtc_write(rtc, OMAP_RTC_STATUS_REG, OMAP_RTC_STATUS_ALARM); + rtc->type->lock(rtc); events |= RTC_IRQF | RTC_AF; } @@ -218,9 +243,11 @@ static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN; } rtc_wait_not_busy(rtc); + rtc->type->unlock(rtc); rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, reg); if (rtc->type->has_irqwakeen) rtc_write(rtc, OMAP_RTC_IRQWAKEEN, irqwake_reg); + rtc->type->lock(rtc); local_irq_enable(); return 0; @@ -293,12 +320,14 @@ static int omap_rtc_set_time(struct device *dev, struct rtc_time *tm) local_irq_disable(); rtc_wait_not_busy(rtc); + rtc->type->unlock(rtc); rtc_write(rtc, OMAP_RTC_YEARS_REG, tm->tm_year); rtc_write(rtc, OMAP_RTC_MONTHS_REG, tm->tm_mon); rtc_write(rtc, OMAP_RTC_DAYS_REG, tm->tm_mday); rtc_write(rtc, OMAP_RTC_HOURS_REG, tm->tm_hour); rtc_write(rtc, OMAP_RTC_MINUTES_REG, tm->tm_min); rtc_write(rtc, OMAP_RTC_SECONDS_REG, tm->tm_sec); + rtc->type->lock(rtc); local_irq_enable(); @@ -341,6 +370,7 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) local_irq_disable(); rtc_wait_not_busy(rtc); + rtc->type->unlock(rtc); rtc_write(rtc, OMAP_RTC_ALARM_YEARS_REG, alm->time.tm_year); rtc_write(rtc, OMAP_RTC_ALARM_MONTHS_REG, alm->time.tm_mon); rtc_write(rtc, OMAP_RTC_ALARM_DAYS_REG, alm->time.tm_mday); @@ -362,6 +392,7 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, reg); if (rtc->type->has_irqwakeen) rtc_write(rtc, OMAP_RTC_IRQWAKEEN, irqwake_reg); + rtc->type->lock(rtc); local_irq_enable(); @@ -391,6 +422,7 @@ static void omap_rtc_power_off(void) unsigned long now; u32 val; + rtc->type->unlock(rtc); /* enable pmic_power_en control */ val = rtc_readl(rtc, OMAP_RTC_PMIC_REG); rtc_writel(rtc, OMAP_RTC_PMIC_REG, val | OMAP_RTC_PMIC_POWER_EN_EN); @@ -423,6 +455,7 @@ static void omap_rtc_power_off(void) val = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG); rtc_writel(rtc, OMAP_RTC_INTERRUPTS_REG, val | OMAP_RTC_INTERRUPTS_IT_ALARM2); + rtc->type->lock(rtc); /* * Wait for alarm to trigger (within two seconds) and external PMIC to @@ -442,17 +475,21 @@ static struct rtc_class_ops omap_rtc_ops = { static const struct omap_rtc_device_type omap_rtc_default_type = { .has_power_up_reset = true, + .lock = default_rtc_lock, + .unlock = default_rtc_unlock, }; static const struct omap_rtc_device_type omap_rtc_am3352_type = { .has_32kclk_en = true, - .has_kicker = true, .has_irqwakeen = true, .has_pmic_mode = true, + .lock = am3352_rtc_lock, + .unlock = am3352_rtc_unlock, }; static const struct omap_rtc_device_type omap_rtc_da830_type = { - .has_kicker = true, + .lock = am3352_rtc_lock, + .unlock = am3352_rtc_unlock, }; static const struct platform_device_id omap_rtc_id_table[] = { @@ -527,10 +564,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); - if (rtc->type->has_kicker) { - rtc_writel(rtc, OMAP_RTC_KICK0_REG, KICK0_VALUE); - rtc_writel(rtc, OMAP_RTC_KICK1_REG, KICK1_VALUE); - } + rtc->type->unlock(rtc); /* * disable interrupts @@ -593,6 +627,8 @@ static int __init omap_rtc_probe(struct platform_device *pdev) if (reg != new_ctrl) rtc_write(rtc, OMAP_RTC_CTRL_REG, new_ctrl); + rtc->type->lock(rtc); + device_init_wakeup(&pdev->dev, true); rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, @@ -626,8 +662,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev) err: device_init_wakeup(&pdev->dev, false); - if (rtc->type->has_kicker) - rtc_writel(rtc, OMAP_RTC_KICK0_REG, 0); + rtc->type->lock(rtc); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); @@ -646,11 +681,11 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 0); + rtc->type->unlock(rtc); /* leave rtc running, but disable irqs */ rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0); - if (rtc->type->has_kicker) - rtc_writel(rtc, OMAP_RTC_KICK0_REG, 0); + rtc->type->lock(rtc); /* Disable the clock/module */ pm_runtime_put_sync(&pdev->dev); @@ -666,6 +701,7 @@ static int omap_rtc_suspend(struct device *dev) rtc->interrupts_reg = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG); + rtc->type->unlock(rtc); /* * FIXME: the RTC alarm is not currently acting as a wakeup event * source on some platforms, and in fact this enable() call is just @@ -675,6 +711,7 @@ static int omap_rtc_suspend(struct device *dev) enable_irq_wake(rtc->irq_alarm); else rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0); + rtc->type->lock(rtc); /* Disable the clock/module */ pm_runtime_put_sync(dev); @@ -689,10 +726,12 @@ static int omap_rtc_resume(struct device *dev) /* Enable the clock/module so that we can access the registers */ pm_runtime_get_sync(dev); + rtc->type->unlock(rtc); if (device_may_wakeup(dev)) disable_irq_wake(rtc->irq_alarm); else rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, rtc->interrupts_reg); + rtc->type->lock(rtc); return 0; } @@ -709,9 +748,11 @@ static void omap_rtc_shutdown(struct platform_device *pdev) * Keep the ALARM interrupt enabled to allow the system to power up on * alarm events. */ + rtc->type->unlock(rtc); mask = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG); mask &= OMAP_RTC_INTERRUPTS_IT_ALARM; rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, mask); + rtc->type->lock(rtc); } static struct platform_driver omap_rtc_driver = { -- cgit v1.2.3-58-ga151 From 8608976e2bc9c1df090e1b346c65ec1405e9d03d Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Thu, 16 Apr 2015 12:46:03 -0700 Subject: drivers/rtc/Kconfig: update Kconfig for OMAP RTC RTC is present in AM43xx and DRA7xx also. Updating the Kconfig to depend on ARCH_OMAP or ARCH_DAVINCI Signed-off-by: Lokesh Vutla Acked-by: Alexandre Belloni Cc: Alessandro Zummo Cc: Paul Walmsley Cc: Tero Kristo Cc: Sekhar Nori Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index faeee2d2550b..6149ae01e11f 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1131,11 +1131,11 @@ config RTC_DRV_IMXDI will be called "rtc-imxdi". config RTC_DRV_OMAP - tristate "TI OMAP1" - depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX || SOC_AM33XX + tristate "TI OMAP Real Time Clock" + depends on ARCH_OMAP || ARCH_DAVINCI help Say "yes" here to support the on chip real time clock - present on TI OMAP1, AM33xx and DA8xx/OMAP-L13x. + present on TI OMAP1, AM33xx, DA8xx/OMAP-L13x, AM43xx and DRA7xx. This driver can also be built as a module, if so, module will be called rtc-omap. -- cgit v1.2.3-58-ga151 From 5d9094b6c7fc87d1909143540c1e2fddde9129b3 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Thu, 16 Apr 2015 12:46:05 -0700 Subject: drivers/rtc/rtc-omap.c: use module_platform_driver module_platform_driver_probe() prevents driver from requesting probe deferral. So using module_platform_drive() to support probe deferral. Signed-off-by: Lokesh Vutla Acked-by: Alexandre Belloni Cc: Alessandro Zummo Cc: Paul Walmsley Cc: Tero Kristo Cc: Sekhar Nori Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-omap.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index a5ff00931360..8b6355ffaff9 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -521,7 +521,7 @@ static const struct of_device_id omap_rtc_of_match[] = { }; MODULE_DEVICE_TABLE(of, omap_rtc_of_match); -static int __init omap_rtc_probe(struct platform_device *pdev) +static int omap_rtc_probe(struct platform_device *pdev) { struct omap_rtc *rtc; struct resource *res; @@ -756,6 +756,7 @@ static void omap_rtc_shutdown(struct platform_device *pdev) } static struct platform_driver omap_rtc_driver = { + .probe = omap_rtc_probe, .remove = __exit_p(omap_rtc_remove), .shutdown = omap_rtc_shutdown, .driver = { @@ -766,7 +767,7 @@ static struct platform_driver omap_rtc_driver = { .id_table = omap_rtc_id_table, }; -module_platform_driver_probe(omap_rtc_driver, omap_rtc_probe); +module_platform_driver(omap_rtc_driver); MODULE_ALIAS("platform:omap_rtc"); MODULE_AUTHOR("George G. Davis (and others)"); -- cgit v1.2.3-58-ga151 From 492da68c8c3babc573208e057a9011d9489f2b5a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 16 Apr 2015 12:46:08 -0700 Subject: drivers/rtc/rtc-s3c.c: remove one superfluous rtc_valid_tm() check s3c_rtc_gettime() already returns the result of rtc_valid_tm() on the obtained time so get rid of another call to rtc_valid_tm(). Signed-off-by: Krzysztof Kozlowski Reviewed-by: Chanwoo Choi Cc: Alexandre Belloni Cc: Alessandro Zummo Cc: Marek Szyprowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-s3c.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index a313b9b5a27e..76cbad7a99d3 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -497,9 +497,7 @@ static int s3c_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); /* Check RTC Time */ - s3c_rtc_gettime(&pdev->dev, &rtc_tm); - - if (rtc_valid_tm(&rtc_tm)) { + if (s3c_rtc_gettime(&pdev->dev, &rtc_tm)) { rtc_tm.tm_year = 100; rtc_tm.tm_mon = 0; rtc_tm.tm_mday = 1; -- cgit v1.2.3-58-ga151 From f539a8acf1070557aef9c5df682751ba2af1005f Mon Sep 17 00:00:00 2001 From: Heiko Stübner Date: Thu, 16 Apr 2015 12:46:11 -0700 Subject: drivers/rtc/rtc-hym8563.c: fix swapped enable/disable of clockout control bit The hym8563 datasheet describes the clock output control-bit as "when set to logic 0, the square wave output is enable, when set to logic 1, the CLKOUT output is inhibited". But in reality the setting is exactly opposite. Before now, the clock output was not really used, but on the rk3288 soc this generated clock is used to supply the temperature sensor block and the swapped bit value prevented it from working. With the corrected value, the tsadc now reports correct values. Signed-off-by: Heiko Stuebner Acked-by: Alexandre Belloni Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-hym8563.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c index d4a65619ef14..0f710e98538f 100644 --- a/drivers/rtc/rtc-hym8563.c +++ b/drivers/rtc/rtc-hym8563.c @@ -66,7 +66,7 @@ #define HYM8563_ALM_BIT_DISABLE BIT(7) #define HYM8563_CLKOUT 0x0d -#define HYM8563_CLKOUT_DISABLE BIT(7) +#define HYM8563_CLKOUT_ENABLE BIT(7) #define HYM8563_CLKOUT_32768 0 #define HYM8563_CLKOUT_1024 1 #define HYM8563_CLKOUT_32 2 @@ -360,9 +360,9 @@ static int hym8563_clkout_control(struct clk_hw *hw, bool enable) return ret; if (enable) - ret &= ~HYM8563_CLKOUT_DISABLE; + ret |= HYM8563_CLKOUT_ENABLE; else - ret |= HYM8563_CLKOUT_DISABLE; + ret &= ~HYM8563_CLKOUT_ENABLE; return i2c_smbus_write_byte_data(client, HYM8563_CLKOUT, ret); } @@ -386,7 +386,7 @@ static int hym8563_clkout_is_prepared(struct clk_hw *hw) if (ret < 0) return ret; - return !(ret & HYM8563_CLKOUT_DISABLE); + return !!(ret & HYM8563_CLKOUT_ENABLE); } static const struct clk_ops hym8563_clkout_ops = { @@ -407,7 +407,7 @@ static struct clk *hym8563_clkout_register_clk(struct hym8563 *hym8563) int ret; ret = i2c_smbus_write_byte_data(client, HYM8563_CLKOUT, - HYM8563_CLKOUT_DISABLE); + 0); if (ret < 0) return ERR_PTR(ret); -- cgit v1.2.3-58-ga151 From a737e835e5769ef22897179ed7f82b1fc50bfa58 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 16 Apr 2015 12:46:14 -0700 Subject: rtc: use more standard kernel logging styles Neaten the logging a bit by adding #define pr_fmt Miscellanea: o Remove __FILE__/__func__ uses o Coalesce formats adding missing spaces o Align arguments o (rtc-cmos) Integrated 2 consecutive messages Signed-off-by: Joe Perches Acked-by: Alexandre Belloni Cc: Alessandro Zummo Cc: Joshua Kinard Cc: Chanwoo Choi Reviewed-by: Krzysztof Kozlowski Tested-by: Krzysztof Kozlowski Cc: Aaro Koskinen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/hctosys.c | 6 ++++-- drivers/rtc/rtc-cmos.c | 6 ++++-- drivers/rtc/rtc-ds1374.c | 8 +++++--- drivers/rtc/rtc-ds1685.c | 4 +++- drivers/rtc/rtc-ds3232.c | 6 ++++-- drivers/rtc/rtc-efi-platform.c | 3 +++ drivers/rtc/rtc-m41t80.c | 6 ++++-- drivers/rtc/rtc-max77686.c | 6 ++++-- drivers/rtc/rtc-max8997.c | 8 +++++--- drivers/rtc/rtc-msm6242.c | 4 +++- drivers/rtc/rtc-opal.c | 3 ++- drivers/rtc/rtc-s5m.c | 4 +++- drivers/rtc/rtc-twl.c | 9 +++++---- 13 files changed, 49 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c index 91fb5f3c1051..e1cfa06810ef 100644 --- a/drivers/rtc/hctosys.c +++ b/drivers/rtc/hctosys.c @@ -9,6 +9,8 @@ * published by the Free Software Foundation. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include /* IMPORTANT: the RTC only stores whole seconds. It is arbitrary @@ -32,8 +34,8 @@ static int __init rtc_hctosys(void) struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); if (rtc == NULL) { - pr_info("%s: unable to open rtc device (%s)\n", - __func__, CONFIG_RTC_HCTOSYS_DEVICE); + pr_info("unable to open rtc device (%s)\n", + CONFIG_RTC_HCTOSYS_DEVICE); goto err_open; } diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 87647f459198..a82556a0757a 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -28,6 +28,9 @@ * interrupts disabled, holding the global rtc_lock, to exclude those * other drivers and utilities on correctly configured systems. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -385,8 +388,7 @@ static bool alarm_disable_quirk; static int __init set_alarm_disable_quirk(const struct dmi_system_id *id) { alarm_disable_quirk = true; - pr_info("rtc-cmos: BIOS has alarm-disable quirk. "); - pr_info("RTC alarms disabled\n"); + pr_info("BIOS has alarm-disable quirk - RTC alarms disabled\n"); return 0; } diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 8605fde394b2..167783fa7ac1 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -18,6 +18,8 @@ * "Sending and receiving", using SMBus level communication is preferred. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -406,7 +408,7 @@ static int ds1374_wdt_settimeout(unsigned int timeout) /* Set new watchdog time */ ret = ds1374_write_rtc(save_client, timeout, DS1374_REG_WDALM0, 3); if (ret) { - pr_info("rtc-ds1374 - couldn't set new watchdog time\n"); + pr_info("couldn't set new watchdog time\n"); goto out; } @@ -539,12 +541,12 @@ static long ds1374_wdt_ioctl(struct file *file, unsigned int cmd, return -EFAULT; if (options & WDIOS_DISABLECARD) { - pr_info("rtc-ds1374: disable watchdog\n"); + pr_info("disable watchdog\n"); ds1374_wdt_disable(); } if (options & WDIOS_ENABLECARD) { - pr_info("rtc-ds1374: enable watchdog\n"); + pr_info("enable watchdog\n"); ds1374_wdt_settimeout(wdt_margin); ds1374_wdt_ping(); } diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index 70202098a8ce..818a3635a8c8 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -16,6 +16,8 @@ * published by the Free Software Foundation. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -2182,7 +2184,7 @@ ds1685_rtc_poweroff(struct platform_device *pdev) /* Check for valid RTC data, else, spin forever. */ if (unlikely(!pdev)) { - pr_emerg("rtc-ds1685: platform device data not available, spinning forever ...\n"); + pr_emerg("platform device data not available, spinning forever ...\n"); unreachable(); } else { /* Get the rtc data. */ diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index adaf06c41479..7e48e532214f 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -15,6 +15,8 @@ * "Sending and receiving", using SMBus level communication is preferred. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -373,8 +375,8 @@ static void ds3232_work(struct work_struct *work) if (stat & DS3232_REG_SR_A1F) { control = i2c_smbus_read_byte_data(client, DS3232_REG_CR); if (control < 0) { - pr_warn("Read DS3232 Control Register error." - "Disable IRQ%d.\n", client->irq); + pr_warn("Read Control Register error - Disable IRQ%d\n", + client->irq); } else { /* disable alarm1 interrupt */ control &= ~(DS3232_REG_CR_A1IE); diff --git a/drivers/rtc/rtc-efi-platform.c b/drivers/rtc/rtc-efi-platform.c index b40fbe332af4..1a7f1d1bc174 100644 --- a/drivers/rtc/rtc-efi-platform.c +++ b/drivers/rtc/rtc-efi-platform.c @@ -8,6 +8,9 @@ * Copyright (C) 1999-2000 VA Linux Systems * Copyright (C) 1999-2000 Walt Drummond */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 7ff7427c2e6a..a82937e2f824 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -13,6 +13,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -513,12 +515,12 @@ static int wdt_ioctl(struct file *file, unsigned int cmd, return -EFAULT; if (rv & WDIOS_DISABLECARD) { - pr_info("rtc-m41t80: disable watchdog\n"); + pr_info("disable watchdog\n"); wdt_disable(); } if (rv & WDIOS_ENABLECARD) { - pr_info("rtc-m41t80: enable watchdog\n"); + pr_info("enable watchdog\n"); wdt_ping(); } diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 9d71328e59b9..7632a87784c3 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -12,6 +12,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -103,8 +105,8 @@ static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data) data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0; if (tm->tm_year < 100) { - pr_warn("%s: MAX77686 RTC cannot handle the year %d." - "Assume it's 2000.\n", __func__, 1900 + tm->tm_year); + pr_warn("RTC cannot handle the year %d. Assume it's 2000.\n", + 1900 + tm->tm_year); return -EINVAL; } return 0; diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c index 67fbe559d535..9e02bcda0c09 100644 --- a/drivers/rtc/rtc-max8997.c +++ b/drivers/rtc/rtc-max8997.c @@ -12,6 +12,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -107,8 +109,8 @@ static int max8997_rtc_tm_to_data(struct rtc_time *tm, u8 *data) data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0; if (tm->tm_year < 100) { - pr_warn("%s: MAX8997 RTC cannot handle the year %d." - "Assume it's 2000.\n", __func__, 1900 + tm->tm_year); + pr_warn("RTC cannot handle the year %d. Assume it's 2000.\n", + 1900 + tm->tm_year); return -EINVAL; } return 0; @@ -424,7 +426,7 @@ static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable) val = 0; max8997_read_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, &val); - pr_info("%s: WTSR_SMPL(0x%02x)\n", __func__, val); + pr_info("WTSR_SMPL(0x%02x)\n", val); } static int max8997_rtc_init_reg(struct max8997_rtc_info *info) diff --git a/drivers/rtc/rtc-msm6242.c b/drivers/rtc/rtc-msm6242.c index 9bf877bdf836..c1c5c4e3b3b4 100644 --- a/drivers/rtc/rtc-msm6242.c +++ b/drivers/rtc/rtc-msm6242.c @@ -7,6 +7,8 @@ * Copyright (C) 1993 Hamish Macdonald */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -111,7 +113,7 @@ static void msm6242_lock(struct msm6242_priv *priv) } if (!cnt) - pr_warn("msm6242: timed out waiting for RTC (0x%x)\n", + pr_warn("timed out waiting for RTC (0x%x)\n", msm6242_read(priv, MSM6242_CD)); } diff --git a/drivers/rtc/rtc-opal.c b/drivers/rtc/rtc-opal.c index 95f652165fe9..7061dcae2b09 100644 --- a/drivers/rtc/rtc-opal.c +++ b/drivers/rtc/rtc-opal.c @@ -16,8 +16,9 @@ * along with this program. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #define DRVNAME "rtc-opal" -#define pr_fmt(fmt) DRVNAME ": " fmt #include #include diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index f0cb0ecb3d8d..64baad379174 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c @@ -15,6 +15,8 @@ * GNU General Public License for more details. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -146,7 +148,7 @@ static int s5m8767_tm_to_data(struct rtc_time *tm, u8 *data) data[RTC_YEAR1] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0; if (tm->tm_year < 100) { - pr_err("s5m8767 RTC cannot handle the year %d.\n", + pr_err("RTC cannot handle the year %d\n", 1900 + tm->tm_year); return -EINVAL; } else { diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index 5baea3f54926..2dc787dc06c1 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -18,6 +18,8 @@ * 2 of the License, or (at your option) any later version. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -145,8 +147,7 @@ static int twl_rtc_read_u8(u8 *data, u8 reg) ret = twl_i2c_read_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg])); if (ret < 0) - pr_err("twl_rtc: Could not read TWL" - "register %X - error %d\n", reg, ret); + pr_err("Could not read TWL register %X - error %d\n", reg, ret); return ret; } @@ -159,8 +160,8 @@ static int twl_rtc_write_u8(u8 data, u8 reg) ret = twl_i2c_write_u8(TWL_MODULE_RTC, data, (rtc_reg_map[reg])); if (ret < 0) - pr_err("twl_rtc: Could not write TWL" - "register %X - error %d\n", reg, ret); + pr_err("Could not write TWL register %X - error %d\n", + reg, ret); return ret; } -- cgit v1.2.3-58-ga151 From 8f7d3f0f1ed5dce6ea7b833ec19cabe61a6e7ff8 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 16 Apr 2015 12:48:29 -0700 Subject: bfs: bfad_worker cleanup This kthread is not loop at all due to break at the end of the loop. Make that function linear, with no while loop. And remove an unnecessary cast. Signed-off-by: Jiri Slaby Cc: Anil Gurumurthy Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/bfa/bfad.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index e90a3742f09d..cc3b9d3d6d40 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -1079,22 +1079,18 @@ bfad_start_ops(struct bfad_s *bfad) { int bfad_worker(void *ptr) { - struct bfad_s *bfad; - unsigned long flags; - - bfad = (struct bfad_s *)ptr; - - while (!kthread_should_stop()) { + struct bfad_s *bfad = ptr; + unsigned long flags; - /* Send event BFAD_E_INIT_SUCCESS */ - bfa_sm_send_event(bfad, BFAD_E_INIT_SUCCESS); + if (kthread_should_stop()) + return 0; - spin_lock_irqsave(&bfad->bfad_lock, flags); - bfad->bfad_tsk = NULL; - spin_unlock_irqrestore(&bfad->bfad_lock, flags); + /* Send event BFAD_E_INIT_SUCCESS */ + bfa_sm_send_event(bfad, BFAD_E_INIT_SUCCESS); - break; - } + spin_lock_irqsave(&bfad->bfad_lock, flags); + bfad->bfad_tsk = NULL; + spin_unlock_irqrestore(&bfad->bfad_lock, flags); return 0; } -- cgit v1.2.3-58-ga151 From 13f6b191aaa11c7fd718d35a0c565f3c16bc1d99 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 16 Apr 2015 12:48:35 -0700 Subject: memstick: mspro_block: add missing curly braces Using the indenting we can see the curly braces were obviously intended. This is a static checker fix, but my guess is that we don't read enough bytes, because we don't calculate "t_len" correctly. Fixes: f1d82698029b ('memstick: use fully asynchronous request processing') Signed-off-by: Dan Carpenter Cc: Alex Dubov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/memstick/core/mspro_block.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index fc145d202c46..922a750640e8 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -758,7 +758,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error) if (error || (card->current_mrq.tpc == MSPRO_CMD_STOP)) { if (msb->data_dir == READ) { - for (cnt = 0; cnt < msb->current_seg; cnt++) + for (cnt = 0; cnt < msb->current_seg; cnt++) { t_len += msb->req_sg[cnt].length / msb->page_size; @@ -766,6 +766,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error) t_len += msb->current_page - 1; t_len *= msb->page_size; + } } } else t_len = blk_rq_bytes(msb->block_req); -- cgit v1.2.3-58-ga151 From 11163348a23cdbcdca5fb42485418e75f8566a5c Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Thu, 16 Apr 2015 12:49:12 -0700 Subject: oprofile: reduce mmap_sem hold for mm->exe_file sync_buffer() needs the mmap_sem for two distinct operations, both only occurring upon user context switch handling: 1) Dealing with the exe_file. 2) Adding the dcookie data as we need to lookup the vma that backs it. This is done via add_sample() and add_data(). This patch isolates 1), for it will no longer need the mmap_sem for serialization. However, for now, make of the more standard get_mm_exe_file(), requiring only holding the mmap_sem to read the value, and relying on reference counting to make sure that the exe file won't dissappear underneath us while doing the get dcookie. As a consequence, for 2) we move the mmap_sem locking into where we really need it, in lookup_dcookie(). The benefits are twofold: reduce mmap_sem hold times, and cleaner code. [akpm@linux-foundation.org: export get_mm_exe_file for arch/x86/oprofile/oprofile.ko] Signed-off-by: Davidlohr Bueso Cc: Robert Richter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/oprofile/buffer_sync.c | 30 ++++++++++++++++-------------- kernel/fork.c | 1 + 2 files changed, 17 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index d93b2b6b1f7a..82f7000a285d 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -21,6 +21,7 @@ * objects. */ +#include #include #include #include @@ -224,10 +225,18 @@ static inline unsigned long fast_get_dcookie(struct path *path) static unsigned long get_exec_dcookie(struct mm_struct *mm) { unsigned long cookie = NO_COOKIE; + struct file *exe_file; - if (mm && mm->exe_file) - cookie = fast_get_dcookie(&mm->exe_file->f_path); + if (!mm) + goto done; + + exe_file = get_mm_exe_file(mm); + if (!exe_file) + goto done; + cookie = fast_get_dcookie(&exe_file->f_path); + fput(exe_file); +done: return cookie; } @@ -236,6 +245,8 @@ static unsigned long get_exec_dcookie(struct mm_struct *mm) * pair that can then be added to the global event buffer. We make * sure to do this lookup before a mm->mmap modification happens so * we don't lose track. + * + * The caller must ensure the mm is not nil (ie: not a kernel thread). */ static unsigned long lookup_dcookie(struct mm_struct *mm, unsigned long addr, off_t *offset) @@ -243,6 +254,7 @@ lookup_dcookie(struct mm_struct *mm, unsigned long addr, off_t *offset) unsigned long cookie = NO_COOKIE; struct vm_area_struct *vma; + down_read(&mm->mmap_sem); for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) { if (addr < vma->vm_start || addr >= vma->vm_end) @@ -262,6 +274,7 @@ lookup_dcookie(struct mm_struct *mm, unsigned long addr, off_t *offset) if (!vma) cookie = INVALID_COOKIE; + up_read(&mm->mmap_sem); return cookie; } @@ -402,20 +415,9 @@ static void release_mm(struct mm_struct *mm) { if (!mm) return; - up_read(&mm->mmap_sem); mmput(mm); } - -static struct mm_struct *take_tasks_mm(struct task_struct *task) -{ - struct mm_struct *mm = get_task_mm(task); - if (mm) - down_read(&mm->mmap_sem); - return mm; -} - - static inline int is_code(unsigned long val) { return val == ESCAPE_CODE; @@ -532,7 +534,7 @@ void sync_buffer(int cpu) new = (struct task_struct *)val; oldmm = mm; release_mm(oldmm); - mm = take_tasks_mm(new); + mm = get_task_mm(new); if (mm != oldmm) cookie = get_exec_dcookie(mm); add_user_ctx_switch(new, cookie); diff --git a/kernel/fork.c b/kernel/fork.c index 0d23e76a0c61..03c1eaaa6ef5 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -752,6 +752,7 @@ struct file *get_mm_exe_file(struct mm_struct *mm) rcu_read_unlock(); return exe_file; } +EXPORT_SYMBOL(get_mm_exe_file); /** * get_task_mm - acquire a reference to the task's mm -- cgit v1.2.3-58-ga151 From 94f919225890a1adb3d44bf5b31ff4cb21d8ee7e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 16 Apr 2015 12:49:27 -0700 Subject: drivers/rtc/rtc-s5m.c: allow usage on device type different than main MFD type The RTC driver supports two flavors of S5M devices: S5M8767-like and S2MPS14-like. On S2MPS13 and S2MPS14 devices the RTC module is the same so we want to re-use the existing support of S2MPS14. However device type was passed from parent MFD driver in platform data structure. This way for the S2MPS13 device the main MFD driver passed device type of 'S2MPS13X'. Instead decouple detecting of device type between main MFD and RTC driver. This allows adding support for other S2MPS14 variations (like S2MPS11 and S2MPS13) easily by adding to mfd/sec-core.c: static const struct mfd_cell s2mps13_devs[] = { { .name = "s2mps14-rtc", } }; Signed-off-by: Krzysztof Kozlowski Cc: Alessandro Zummo Cc: Kyungmin Park Cc: Marek Szyprowski Cc: Chanwoo Choi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-s5m.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index 64baad379174..8c70d785ba73 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c @@ -92,7 +92,7 @@ struct s5m_rtc_info { struct regmap *regmap; struct rtc_device *rtc_dev; int irq; - int device_type; + enum sec_device_type device_type; int rtc_24hr_mode; const struct s5m_rtc_reg_config *regs; }; @@ -668,7 +668,7 @@ static int s5m_rtc_probe(struct platform_device *pdev) if (!info) return -ENOMEM; - switch (pdata->device_type) { + switch (platform_get_device_id(pdev)->driver_data) { case S2MPS14X: case S2MPS13X: regmap_cfg = &s2mps14_rtc_regmap_config; @@ -686,7 +686,9 @@ static int s5m_rtc_probe(struct platform_device *pdev) alarm_irq = S5M8767_IRQ_RTCA1; break; default: - dev_err(&pdev->dev, "Device type is not supported by RTC driver\n"); + dev_err(&pdev->dev, + "Device type %lu is not supported by RTC driver\n", + platform_get_device_id(pdev)->driver_data); return -ENODEV; } @@ -706,7 +708,7 @@ static int s5m_rtc_probe(struct platform_device *pdev) info->dev = &pdev->dev; info->s5m87xx = s5m87xx; - info->device_type = s5m87xx->device_type; + info->device_type = platform_get_device_id(pdev)->driver_data; if (s5m87xx->irq_data) { info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq); -- cgit v1.2.3-58-ga151 From 6da7bb1e9cef9ab956e4223125090e4465f51fb2 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 16 Apr 2015 12:49:32 -0700 Subject: drivers/rtc/rtc-at91rm9200.c: make IO endian agnostic Change the __raw IO calls to readl/write_relaxed which makes the driver endian agnostic to run properly on big endian systems. Signed-off-by: Ben Dooks Cc: Alessandro Zummo Cc: Andrew Victor Acked-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-at91rm9200.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index b283a1a573b3..35efd3f75b18 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c @@ -37,9 +37,9 @@ #include "rtc-at91rm9200.h" #define at91_rtc_read(field) \ - __raw_readl(at91_rtc_regs + field) + readl_relaxed(at91_rtc_regs + field) #define at91_rtc_write(field, val) \ - __raw_writel((val), at91_rtc_regs + field) + writel_relaxed((val), at91_rtc_regs + field) #define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */ -- cgit v1.2.3-58-ga151