summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/clk-divider.c138
-rw-r--r--drivers/gpio/Kconfig2
-rw-r--r--drivers/hab/habv4.c4
-rw-r--r--drivers/net/cpsw.c16
-rw-r--r--drivers/serial/serial_ar933x.c1
-rw-r--r--drivers/usb/imx/Kconfig1
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