diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clk/clk-divider.c | 138 | ||||
-rw-r--r-- | drivers/gpio/Kconfig | 2 | ||||
-rw-r--r-- | drivers/hab/habv4.c | 4 | ||||
-rw-r--r-- | drivers/net/cpsw.c | 16 | ||||
-rw-r--r-- | drivers/serial/serial_ar933x.c | 1 | ||||
-rw-r--r-- | drivers/usb/imx/Kconfig | 1 |
6 files changed, 113 insertions, 49 deletions
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index d9d3407e75..78b4153171 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -22,8 +22,6 @@ #include <linux/log2.h> #include <asm-generic/div64.h> -#define div_mask(d) ((1 << ((d)->width)) - 1) - static unsigned int _get_table_maxdiv(const struct clk_div_table *table) { unsigned int maxdiv = 0; @@ -35,15 +33,16 @@ static unsigned int _get_table_maxdiv(const struct clk_div_table *table) return maxdiv; } -static unsigned int _get_maxdiv(struct clk_divider *divider) +static unsigned int _get_maxdiv(const struct clk_div_table *table, u8 width, + unsigned long flags) { - if (divider->flags & CLK_DIVIDER_ONE_BASED) - return div_mask(divider); - if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) - return 1 << div_mask(divider); - if (divider->table) - return _get_table_maxdiv(divider->table); - return div_mask(divider) + 1; + if (flags & CLK_DIVIDER_ONE_BASED) + return clk_div_mask(width); + if (flags & CLK_DIVIDER_POWER_OF_TWO) + return 1 << clk_div_mask(width); + if (table) + return _get_table_maxdiv(table); + return clk_div_mask(width) + 1; } static unsigned int _get_table_div(const struct clk_div_table *table, @@ -79,14 +78,15 @@ static unsigned int _get_table_val(const struct clk_div_table *table, return 0; } -static unsigned int _get_val(struct clk_divider *divider, unsigned int div) +static unsigned int _get_val(const struct clk_div_table *table, + unsigned int div, unsigned long flags) { - if (divider->flags & CLK_DIVIDER_ONE_BASED) + if (flags & CLK_DIVIDER_ONE_BASED) return div; - if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) + if (flags & CLK_DIVIDER_POWER_OF_TWO) return __ffs(div); - if (divider->table) - return _get_table_val(divider->table, div); + if (table) + return _get_table_val(table, div); return div - 1; } @@ -106,12 +106,10 @@ static unsigned long clk_divider_recalc_rate(struct clk *clk, unsigned long parent_rate) { struct clk_divider *divider = container_of(clk, struct clk_divider, clk); - unsigned int div, val; + unsigned int val; val = readl(divider->reg) >> divider->shift; - val &= div_mask(divider); - - div = _get_div(divider->table, val, divider->flags, divider->width); + val &= clk_div_mask(divider->width); return divider_recalc_rate(clk, parent_rate, val, divider->table, divider->flags, divider->width); @@ -134,19 +132,53 @@ static bool _is_valid_table_div(const struct clk_div_table *table, return false; } -static bool _is_valid_div(struct clk_divider *divider, unsigned int div) +static bool _is_valid_div(const struct clk_div_table *table, unsigned int div, + unsigned long flags) { - if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) + if (flags & CLK_DIVIDER_POWER_OF_TWO) return is_power_of_2(div); - if (divider->table) - return _is_valid_table_div(divider->table, div); + if (table) + return _is_valid_table_div(table, div); return true; } +static int _round_up_table(const struct clk_div_table *table, int div) +{ + const struct clk_div_table *clkt; + int up = _get_table_maxdiv(table); + + for (clkt = table; clkt->div; clkt++) { + if (clkt->div == div) + return clkt->div; + else if (clkt->div < div) + continue; + + if ((clkt->div - div) < (up - div)) + up = clkt->div; + } + + return up; +} + +static int _div_round_up(const struct clk_div_table *table, + unsigned long parent_rate, unsigned long rate, + unsigned long flags) +{ + int div = DIV_ROUND_UP(parent_rate, rate); + + if (flags & CLK_DIVIDER_POWER_OF_TWO) + div = __roundup_pow_of_two(div); + if (table) + div = _round_up_table(table, div); + + return div; +} + static int clk_divider_bestdiv(struct clk *clk, unsigned long rate, - unsigned long *best_parent_rate) + unsigned long *best_parent_rate, + const struct clk_div_table *table, u8 width, + unsigned long flags) { - struct clk_divider *divider = container_of(clk, struct clk_divider, clk); int i, bestdiv = 0; unsigned long parent_rate, best = 0, now, maxdiv; unsigned long parent_rate_saved = *best_parent_rate; @@ -154,11 +186,11 @@ static int clk_divider_bestdiv(struct clk *clk, unsigned long rate, if (!rate) rate = 1; - maxdiv = _get_maxdiv(divider); + maxdiv = _get_maxdiv(table, width, flags); if (!(clk->flags & CLK_SET_RATE_PARENT)) { parent_rate = *best_parent_rate; - bestdiv = DIV_ROUND_UP(parent_rate, rate); + bestdiv = _div_round_up(table, parent_rate, rate, flags); bestdiv = bestdiv == 0 ? 1 : bestdiv; bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv; return bestdiv; @@ -171,7 +203,7 @@ static int clk_divider_bestdiv(struct clk *clk, unsigned long rate, maxdiv = min(ULONG_MAX / rate, maxdiv); for (i = 1; i <= maxdiv; i++) { - if (!_is_valid_div(divider, i)) + if (!_is_valid_div(table, i, flags)) continue; if (rate * i == parent_rate_saved) { /* @@ -193,25 +225,50 @@ static int clk_divider_bestdiv(struct clk *clk, unsigned long rate, } if (!bestdiv) { - bestdiv = _get_maxdiv(divider); + bestdiv = _get_maxdiv(table, width, flags); *best_parent_rate = clk_round_rate(clk_get_parent(clk), 1); } return bestdiv; } +long divider_round_rate(struct clk *clk, unsigned long rate, + unsigned long *prate, const struct clk_div_table *table, + u8 width, unsigned long flags) +{ + int div; + + div = clk_divider_bestdiv(clk, rate, prate, table, width, flags); + + return DIV_ROUND_UP(*prate, div); +} + static long clk_divider_round_rate(struct clk *clk, unsigned long rate, - unsigned long *parent_rate) + unsigned long *prate) { struct clk_divider *divider = container_of(clk, struct clk_divider, clk); - int div; if (divider->flags & CLK_DIVIDER_READ_ONLY) - return clk_divider_recalc_rate(clk, *parent_rate); + return clk_divider_recalc_rate(clk, *prate); - div = clk_divider_bestdiv(clk, rate, parent_rate); + return divider_round_rate(clk, rate, prate, divider->table, + divider->width, divider->flags); +} - return *parent_rate / div; +int divider_get_val(unsigned long rate, unsigned long parent_rate, + const struct clk_div_table *table, u8 width, + unsigned long flags) +{ + unsigned int div, value; + + div = DIV_ROUND_UP(parent_rate, rate); + + if (!_is_valid_div(table, div, flags)) + return -EINVAL; + + value = _get_val(table, div, flags); + + return min_t(unsigned int, value, clk_div_mask(width)); } static int clk_divider_set_rate(struct clk *clk, unsigned long rate, @@ -226,23 +283,22 @@ static int clk_divider_set_rate(struct clk *clk, unsigned long rate, if (clk->flags & CLK_SET_RATE_PARENT) { unsigned long best_parent_rate = parent_rate; - div = clk_divider_bestdiv(clk, rate, &best_parent_rate); + div = clk_divider_bestdiv(clk, rate, &best_parent_rate, + divider->table, divider->width, divider->flags); clk_set_rate(clk_get_parent(clk), best_parent_rate); } else { div = DIV_ROUND_UP(parent_rate, rate); } - value = _get_val(divider, div); - - if (value > div_mask(divider)) - value = div_mask(divider); + value = divider_get_val(rate, parent_rate, divider->table, + divider->width, divider->flags); val = readl(divider->reg); - val &= ~(div_mask(divider) << divider->shift); + val &= ~(clk_div_mask(divider->width) << divider->shift); val |= value << divider->shift; if (clk->flags & CLK_DIVIDER_HIWORD_MASK) - val |= div_mask(divider) << (divider->shift + 16); + val |= clk_div_mask(divider->width) << (divider->shift + 16); writel(val, divider->reg); diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 6a4de7fbc8..7a1503198b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -101,7 +101,7 @@ config GPIO_PCA953X config GPIO_PCF857X tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders" depends on I2C - depends on CONFIG_OF + depends on OFDEVICE help Say yes here to provide access to most "quasi-bidirectional" I2C GPIO expanders used for additional digital outputs or inputs. diff --git a/drivers/hab/habv4.c b/drivers/hab/habv4.c index 496fbe3ccd..6a60be6853 100644 --- a/drivers/hab/habv4.c +++ b/drivers/hab/habv4.c @@ -419,7 +419,7 @@ static bool is_known_rng_fail_event(const uint8_t *data, size_t len) int i; for (i = 0; i < ARRAY_SIZE(habv4_known_rng_fail_events); i++) { if (memcmp(data, habv4_known_rng_fail_events[i], - min(len, (uint32_t)RNG_FAIL_EVENT_SIZE)) == 0) { + min_t(size_t, len, RNG_FAIL_EVENT_SIZE)) == 0) { return true; } } @@ -469,6 +469,7 @@ static int habv4_get_status(const struct habv4_rvt *rvt) } len = sizeof(data); + index = 0; while (rvt->report_event(HAB_STATUS_FAILURE, index, data, &len) == HAB_STATUS_SUCCESS) { pr_err("-------- HAB failure Event %d --------\n", index); pr_err("event data:\n"); @@ -480,6 +481,7 @@ static int habv4_get_status(const struct habv4_rvt *rvt) /* Check reason for stopping */ len = sizeof(data); + index = 0; if (rvt->report_event(HAB_STATUS_ANY, index, NULL, &len) == HAB_STATUS_SUCCESS) pr_err("ERROR: Recompile with larger event data buffer (at least %d bytes)\n\n", len); diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c index 65f71c6fce..df8981d02e 100644 --- a/drivers/net/cpsw.c +++ b/drivers/net/cpsw.c @@ -993,8 +993,13 @@ static int cpsw_phy_sel_init(struct cpsw_priv *priv, struct device_node *np) phy_sel_addr = (void *)addr; - if (of_property_read_bool(np, "rmii-clock-ext")) - rmii_clock_external = true; + /* + * As of Linux-5.1 this is set to true in am33xx-l4.dtsi and not + * overwritten by any board. This is set to false in am437x-l4.dtsi + * though, so once we support this SoC we have to configure this from + * the device tree. + */ + rmii_clock_external = true; return 0; } @@ -1062,11 +1067,10 @@ static int cpsw_probe_dt(struct cpsw_priv *priv) priv->slaves = xzalloc(sizeof(struct cpsw_slave) * priv->num_slaves); - physel = of_parse_phandle(dev->device_node, "cpsw-phy-sel", 0); + physel = of_find_compatible_node(NULL, NULL, "ti,am3352-phy-gmii-sel"); if (!physel) { - physel = of_get_child_by_name(dev->device_node, "cpsw-phy-sel"); - if (!physel) - dev_err(dev, "Phy mode node not found\n"); + dev_err(dev, "Cannot find ti,am3352-phy-gmii-sel node\n"); + return -EINVAL; } ret = cpsw_phy_sel_init(priv, physel); if (ret) diff --git a/drivers/serial/serial_ar933x.c b/drivers/serial/serial_ar933x.c index 676b9fadf8..dda604652b 100644 --- a/drivers/serial/serial_ar933x.c +++ b/drivers/serial/serial_ar933x.c @@ -175,6 +175,7 @@ static int ar933x_serial_probe(struct device_d *dev) cdev->putc = ar933x_serial_putc; cdev->getc = ar933x_serial_getc; cdev->setbrg = ar933x_serial_setbaudrate; + cdev->linux_console_name = "ttyATH"; priv->clk = clk_get(dev, NULL); if (IS_ERR(priv->clk)) { diff --git a/drivers/usb/imx/Kconfig b/drivers/usb/imx/Kconfig index 07ca41b63a..05f17fbd2f 100644 --- a/drivers/usb/imx/Kconfig +++ b/drivers/usb/imx/Kconfig @@ -18,3 +18,4 @@ config USB_IMX_PHY bool default y if (ARCH_IMX6 || ARCH_VF610) && GENERIC_PHY select STMP_DEVICE + select MFD_SYSCON |