Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1398672
| From | David Wu <david.wu@rock-chips.com> |
|---|---|
| Newsgroups | linux.kernel |
| Subject | [PATCH v8 2/8] i2c: rk3x: use struct "rk3x_i2c_calced_timings" |
| Date | 2016-05-11 06:10 +0200 |
| Message-ID | <rxtDc-wb-13@gated-at.bofh.it> (permalink) |
| References | <rxtDc-wb-3@gated-at.bofh.it> |
| Organization | linux.* mail to news gateway |
The "div_high" and "div_low" values are always used together. Group them
into a structure to make it easier to pass them both around. This
structure also provides a place for future calculated timings.
Signed-off-by: David Wu <david.wu@rock-chips.com>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
Change in v8:
- add commit description.
drivers/i2c/busses/i2c-rk3x.c | 55 +++++++++++++++++++++++++------------------
1 file changed, 32 insertions(+), 23 deletions(-)
diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 7e45d51..1e2677a 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -75,6 +75,16 @@ enum {
#define WAIT_TIMEOUT 1000 /* ms */
#define DEFAULT_SCL_RATE (100 * 1000) /* Hz */
+/**
+ * struct rk3x_i2c_calced_timings:
+ * @div_low: Divider output for low
+ * @div_high: Divider output for high
+ */
+struct rk3x_i2c_calced_timings {
+ unsigned long div_low;
+ unsigned long div_high;
+};
+
enum rk3x_i2c_state {
STATE_IDLE,
STATE_START,
@@ -454,9 +464,8 @@ out:
* Calculate divider values for desired SCL frequency
*
* @clk_rate: I2C input clock rate
- * @t: Known I2C timing information.
- * @div_low: Divider output for low
- * @div_high: Divider output for high
+ * @t: Known I2C timing information
+ * @t_calc: Caculated rk3x private timings that would be written into regs
*
* Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case
* a best-effort divider value is returned in divs. If the target rate is
@@ -464,8 +473,7 @@ out:
*/
static int rk3x_i2c_calc_divs(unsigned long clk_rate,
struct i2c_timings *t,
- unsigned long *div_low,
- unsigned long *div_high)
+ struct rk3x_i2c_calced_timings *t_calc)
{
unsigned long spec_min_low_ns, spec_min_high_ns;
unsigned long spec_setup_start, spec_max_data_hold_ns;
@@ -572,8 +580,8 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
* Time needed to meet hold requirements is important.
* Just use that.
*/
- *div_low = min_low_div;
- *div_high = min_high_div;
+ t_calc->div_low = min_low_div;
+ t_calc->div_high = min_high_div;
} else {
/*
* We've got to distribute some time among the low and high
@@ -602,25 +610,25 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
/* Give low the "ideal" and give high whatever extra is left */
extra_low_div = ideal_low_div - min_low_div;
- *div_low = ideal_low_div;
- *div_high = min_high_div + (extra_div - extra_low_div);
+ t_calc->div_low = ideal_low_div;
+ t_calc->div_high = min_high_div + (extra_div - extra_low_div);
}
/*
* Adjust to the fact that the hardware has an implicit "+1".
* NOTE: Above calculations always produce div_low > 0 and div_high > 0.
*/
- *div_low = *div_low - 1;
- *div_high = *div_high - 1;
+ t_calc->div_low--;
+ t_calc->div_high--;
/* Maximum divider supported by hw is 0xffff */
- if (*div_low > 0xffff) {
- *div_low = 0xffff;
+ if (t_calc->div_low > 0xffff) {
+ t_calc->div_low = 0xffff;
ret = -EINVAL;
}
- if (*div_high > 0xffff) {
- *div_high = 0xffff;
+ if (t_calc->div_high > 0xffff) {
+ t_calc->div_high = 0xffff;
ret = -EINVAL;
}
@@ -630,19 +638,21 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
{
struct i2c_timings *t = &i2c->t;
- unsigned long div_low, div_high;
+ struct rk3x_i2c_calced_timings calc;
u64 t_low_ns, t_high_ns;
int ret;
- ret = rk3x_i2c_calc_divs(clk_rate, t, &div_low, &div_high);
+ ret = rk3x_i2c_calc_divs(clk_rate, t, &calc);
WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz);
clk_enable(i2c->clk);
- i2c_writel(i2c, (div_high << 16) | (div_low & 0xffff), REG_CLKDIV);
+ i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low & 0xffff),
+ REG_CLKDIV);
clk_disable(i2c->clk);
- t_low_ns = div_u64(((u64)div_low + 1) * 8 * 1000000000, clk_rate);
- t_high_ns = div_u64(((u64)div_high + 1) * 8 * 1000000000, clk_rate);
+ t_low_ns = div_u64(((u64)calc.div_low + 1) * 8 * 1000000000, clk_rate);
+ t_high_ns = div_u64(((u64)calc.div_high + 1) * 8 * 1000000000,
+ clk_rate);
dev_dbg(i2c->dev,
"CLK %lukhz, Req %uns, Act low %lluns high %lluns\n",
clk_rate / 1000,
@@ -672,12 +682,11 @@ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
{
struct clk_notifier_data *ndata = data;
struct rk3x_i2c *i2c = container_of(nb, struct rk3x_i2c, clk_rate_nb);
- unsigned long div_low, div_high;
+ struct rk3x_i2c_calced_timings calc;
switch (event) {
case PRE_RATE_CHANGE:
- if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t,
- &div_low, &div_high) != 0)
+ if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t, &calc) != 0)
return NOTIFY_STOP;
/* scale up */
--
1.9.1
Back to linux.kernel | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
[PATCH v8 0/8] add i2c driver supported for rk3399 David Wu <david.wu@rock-chips.com> - 2016-05-11 06:10 +0200
[PATCH v8 2/8] i2c: rk3x: use struct "rk3x_i2c_calced_timings" David Wu <david.wu@rock-chips.com> - 2016-05-11 06:10 +0200
[PATCH v8 1/8] i2c: rk3x: add documentation to fields in "struct rk3x_i2c" David Wu <david.wu@rock-chips.com> - 2016-05-11 06:10 +0200
Re: [PATCH v8 1/8] i2c: rk3x: add documentation to fields in "struct rk3x_i2c" Heiko Stuebner <heiko@sntech.de> - 2016-05-11 17:10 +0200
[PATCH v8 3/8] i2c: rk3x: Remove redundant rk3x_i2c_clean_ipd() David Wu <david.wu@rock-chips.com> - 2016-05-11 06:10 +0200
Re: [PATCH v8 3/8] i2c: rk3x: Remove redundant rk3x_i2c_clean_ipd() Heiko Stuebner <heiko@sntech.de> - 2016-05-11 20:30 +0200
Re: [PATCH v8 3/8] i2c: rk3x: Remove redundant rk3x_i2c_clean_ipd() "David.Wu" <david.wu@rock-chips.com> - 2016-05-12 03:20 +0200
[PATCH v8 4/8] i2c: rk3x: Change SoC data to not use array David Wu <david.wu@rock-chips.com> - 2016-05-11 06:10 +0200
[PATCH v8 5/8] i2c: rk3x: Move spec timing data to "static const" structs David Wu <david.wu@rock-chips.com> - 2016-05-11 06:10 +0200
[PATCH v8 8/8] i2c: rk3x: support fast-mode plus for rk3399 David Wu <david.wu@rock-chips.com> - 2016-05-11 06:20 +0200
Re: [PATCH v8 8/8] i2c: rk3x: support fast-mode plus for rk3399 Caesar Wang <caesar.upstream@gmail.com> - 2016-05-11 13:50 +0200
Re: [PATCH v8 8/8] i2c: rk3x: support fast-mode plus for rk3399 Heiko Stuebner <heiko@sntech.de> - 2016-05-11 23:20 +0200
Re: [PATCH v8 8/8] i2c: rk3x: support fast-mode plus for rk3399 Doug Anderson <dianders@chromium.org> - 2016-05-12 01:50 +0200
Re: [PATCH v8 8/8] i2c: rk3x: support fast-mode plus for rk3399 Heiko Stuebner <heiko@sntech.de> - 2016-05-12 10:40 +0200
csiph-web