summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/driver.c5
-rw-r--r--drivers/base/regmap/Makefile3
-rw-r--r--drivers/base/regmap/internal.h9
-rw-r--r--drivers/base/regmap/regmap-mmio.c271
-rw-r--r--drivers/clk/imx/clk-imx1.c2
-rw-r--r--drivers/clocksource/Kconfig2
-rw-r--r--drivers/clocksource/Makefile4
-rw-r--r--drivers/clocksource/arm_architected_timer.c (renamed from drivers/clocksource/armv8-timer.c)19
-rw-r--r--drivers/eeprom/at25.c2
-rw-r--r--drivers/gpio/gpiolib.c245
-rw-r--r--drivers/i2c/busses/i2c-tegra.c2
-rw-r--r--drivers/led/led-pwm.c10
-rw-r--r--drivers/mci/imx-esdhc-common.c2
-rw-r--r--drivers/mci/mci-core.c36
-rw-r--r--drivers/mci/stm32_sdmmc2.c7
-rw-r--r--drivers/mfd/syscon.c47
-rw-r--r--drivers/mtd/nand/Kconfig6
-rw-r--r--drivers/mtd/nand/Makefile1
-rw-r--r--drivers/mtd/nand/nand_imx.c118
-rw-r--r--drivers/mtd/nand/nand_imx_bbm.c219
-rw-r--r--drivers/net/designware_socfpga.c18
-rw-r--r--drivers/net/designware_stm32.c3
-rw-r--r--drivers/nvmem/ocotp.c11
-rw-r--r--drivers/pci/pci-layerscape.c130
-rw-r--r--drivers/pinctrl/imx-iomux-v3.c8
-rw-r--r--drivers/pinctrl/pinctrl-single.c81
-rw-r--r--drivers/pwm/pxa_pwm.c11
-rw-r--r--drivers/regulator/Kconfig2
-rw-r--r--drivers/regulator/fixed.c3
-rw-r--r--drivers/regulator/pfuze.c4
-rw-r--r--drivers/usb/core/hub.c3
-rw-r--r--drivers/usb/gadget/f_fastboot.c2
-rw-r--r--drivers/usb/gadget/fsl_udc.c15
-rw-r--r--drivers/usb/musb/musb_core.c5
-rw-r--r--drivers/usb/musb/musb_dsps.c55
-rw-r--r--drivers/usb/musb/phy-am335x-control.c25
-rw-r--r--drivers/usb/musb/phy-am335x.c22
-rw-r--r--drivers/usb/musb/phy-am335x.h6
-rw-r--r--drivers/video/backlight-pwm.c2
-rw-r--r--drivers/watchdog/dw_wdt.c13
-rw-r--r--drivers/watchdog/wd_core.c30
41 files changed, 920 insertions, 539 deletions
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index eec2a2d..456750e 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -36,6 +36,7 @@
#include <linux/err.h>
#include <complete.h>
#include <pinctrl.h>
+#include <linux/clk/clk-conf.h>
LIST_HEAD(device_list);
EXPORT_SYMBOL(device_list);
@@ -86,6 +87,7 @@ int device_probe(struct device_d *dev)
int ret;
pinctrl_select_state_default(dev);
+ of_clk_set_defaults(dev->device_node, false);
list_add(&dev->active, &active);
@@ -308,6 +310,9 @@ int register_driver(struct driver_d *drv)
{
struct device_d *dev = NULL;
+ if (!drv->name)
+ return -EINVAL;
+
debug("register_driver: %s\n", drv->name);
BUG_ON(!drv->bus);
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile
index 4dc3d8c..ab23870 100644
--- a/drivers/base/regmap/Makefile
+++ b/drivers/base/regmap/Makefile
@@ -1 +1,2 @@
-obj-y += regmap.o \ No newline at end of file
+obj-y += regmap.o
+obj-y += regmap-mmio.o
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 52df529..5b19459 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -1,5 +1,10 @@
+#ifndef REGMAP_INTERNAL_H_
+#define REGMAP_INTERNAL_H_
#include <linux/list.h>
+#include <driver.h>
+
+struct regmap_bus;
struct regmap {
struct device_d *dev;
@@ -15,4 +20,6 @@ struct regmap {
unsigned int max_register;
struct cdev cdev;
-}; \ No newline at end of file
+};
+
+#endif
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c
new file mode 100644
index 0000000..f8d2cda
--- /dev/null
+++ b/drivers/base/regmap/regmap-mmio.c
@@ -0,0 +1,271 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Register map access API - MMIO support
+//
+// Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <io.h>
+#include <regmap.h>
+
+#include "internal.h"
+
+struct regmap_mmio_context {
+ void __iomem *regs;
+ unsigned val_bytes;
+
+ struct clk *clk;
+
+ void (*reg_write)(struct regmap_mmio_context *ctx,
+ unsigned int reg, unsigned int val);
+ unsigned int (*reg_read)(struct regmap_mmio_context *ctx,
+ unsigned int reg);
+};
+
+static int regmap_mmio_regbits_check(size_t reg_bits)
+{
+ switch (reg_bits) {
+ case 8:
+ case 16:
+ case 32:
+#ifdef CONFIG_64BIT
+ case 64:
+#endif
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int regmap_mmio_get_min_stride(size_t val_bits)
+{
+ int min_stride;
+
+ switch (val_bits) {
+ case 8:
+ /* The core treats 0 as 1 */
+ min_stride = 0;
+ return 0;
+ case 16:
+ min_stride = 2;
+ break;
+ case 32:
+ min_stride = 4;
+ break;
+#ifdef CONFIG_64BIT
+ case 64:
+ min_stride = 8;
+ break;
+#endif
+ default:
+ return -EINVAL;
+ }
+
+ return min_stride;
+}
+
+static void regmap_mmio_write8(struct regmap_mmio_context *ctx,
+ unsigned int reg,
+ unsigned int val)
+{
+ writeb(val, ctx->regs + reg);
+}
+
+static void regmap_mmio_write16le(struct regmap_mmio_context *ctx,
+ unsigned int reg,
+ unsigned int val)
+{
+ writew(val, ctx->regs + reg);
+}
+
+static void regmap_mmio_write32le(struct regmap_mmio_context *ctx,
+ unsigned int reg,
+ unsigned int val)
+{
+ writel(val, ctx->regs + reg);
+}
+
+#ifdef CONFIG_64BIT
+static void regmap_mmio_write64le(struct regmap_mmio_context *ctx,
+ unsigned int reg,
+ unsigned int val)
+{
+ writeq(val, ctx->regs + reg);
+}
+#endif
+
+static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val)
+{
+ struct regmap_mmio_context *ctx = context;
+ int ret;
+
+ ret = clk_enable(ctx->clk);
+ if (ret < 0)
+ return ret;
+
+ ctx->reg_write(ctx, reg, val);
+
+ clk_disable(ctx->clk);
+
+ return 0;
+}
+
+static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx,
+ unsigned int reg)
+{
+ return readb(ctx->regs + reg);
+}
+
+static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx,
+ unsigned int reg)
+{
+ return readw(ctx->regs + reg);
+}
+
+static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx,
+ unsigned int reg)
+{
+ return readl(ctx->regs + reg);
+}
+
+#ifdef CONFIG_64BIT
+static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx,
+ unsigned int reg)
+{
+ return readq(ctx->regs + reg);
+}
+#endif
+
+static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct regmap_mmio_context *ctx = context;
+ int ret;
+
+ ret = clk_enable(ctx->clk);
+ if (ret < 0)
+ return ret;
+
+ *val = ctx->reg_read(ctx, reg);
+
+ clk_disable(ctx->clk);
+
+ return 0;
+}
+
+static const struct regmap_bus regmap_mmio = {
+ .reg_write = regmap_mmio_write,
+ .reg_read = regmap_mmio_read,
+};
+
+static struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs,
+ const struct regmap_config *config)
+{
+ struct regmap_mmio_context *ctx;
+ int min_stride;
+ int ret;
+
+ ret = regmap_mmio_regbits_check(config->reg_bits);
+ if (ret)
+ return ERR_PTR(ret);
+
+ if (config->pad_bits)
+ return ERR_PTR(-EINVAL);
+
+ min_stride = regmap_mmio_get_min_stride(config->val_bits);
+ if (min_stride < 0)
+ return ERR_PTR(min_stride);
+
+ if (config->reg_stride < min_stride)
+ return ERR_PTR(-EINVAL);
+
+ ctx = xzalloc(sizeof(*ctx));
+
+ ctx->regs = regs;
+ ctx->val_bytes = config->val_bits / 8;
+
+ switch (config->val_bits) {
+ case 8:
+ ctx->reg_read = regmap_mmio_read8;
+ ctx->reg_write = regmap_mmio_write8;
+ break;
+ case 16:
+ ctx->reg_read = regmap_mmio_read16le;
+ ctx->reg_write = regmap_mmio_write16le;
+ break;
+ case 32:
+ ctx->reg_read = regmap_mmio_read32le;
+ ctx->reg_write = regmap_mmio_write32le;
+ break;
+ default:
+ ret = -EINVAL;
+ goto err_free;
+ }
+
+ return ctx;
+
+err_free:
+ kfree(ctx);
+
+ return ERR_PTR(ret);
+}
+
+struct regmap *regmap_init_mmio_clk(struct device_d *dev,
+ const char *clk_id,
+ void __iomem *regs,
+ const struct regmap_config *config)
+{
+ struct regmap_mmio_context *ctx;
+
+ ctx = regmap_mmio_gen_context(regs, config);
+ if (IS_ERR(ctx))
+ return ERR_CAST(ctx);
+
+ if (clk_id) {
+ ctx->clk = clk_get(dev, clk_id);
+ if (IS_ERR(ctx->clk)) {
+ kfree(ctx);
+ return ERR_CAST(ctx->clk);
+ }
+ }
+
+ return regmap_init(dev, &regmap_mmio, ctx, config);
+}
+
+struct regmap *of_regmap_init_mmio_clk(struct device_node *np,
+ const char *clk_id,
+ void __iomem *regs,
+ const struct regmap_config *config)
+{
+ struct regmap_mmio_context *ctx;
+
+ ctx = regmap_mmio_gen_context(regs, config);
+ if (IS_ERR(ctx))
+ return ERR_CAST(ctx);
+
+ if (clk_id) {
+ ctx->clk = of_clk_get_by_name(np, clk_id);
+ if (IS_ERR(ctx->clk)) {
+ kfree(ctx);
+ return ERR_CAST(ctx->clk);
+ }
+ }
+
+ return regmap_init(NULL, &regmap_mmio, ctx, config);
+}
+
+int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk)
+{
+ struct regmap_mmio_context *ctx = map->bus_context;
+
+ ctx->clk = clk;
+
+ return 0;
+}
+
+void regmap_mmio_detach_clk(struct regmap *map)
+{
+ struct regmap_mmio_context *ctx = map->bus_context;
+
+ ctx->clk = NULL;
+}
diff --git a/drivers/clk/imx/clk-imx1.c b/drivers/clk/imx/clk-imx1.c
index 5f600a9..9a817c3 100644
--- a/drivers/clk/imx/clk-imx1.c
+++ b/drivers/clk/imx/clk-imx1.c
@@ -53,7 +53,7 @@ static const char *clko_sel_clks[] = {
"fclk",
};
-int __init mx1_clocks_init(void __iomem *regs, unsigned long fref)
+static int __init mx1_clocks_init(void __iomem *regs, unsigned long fref)
{
clks[dummy] = clk_fixed("dummy", 0);
clks[clk32] = clk_fixed("clk32", fref);
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 43c5bfc..39ddd15 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -70,7 +70,7 @@ config CLOCKSOURCE_ROCKCHIP
config CLOCKSOURCE_ATMEL_PIT
bool
-config CLOCKSOURCE_ARMV8_TIMER
+config CLOCKSOURCE_ARM_ARCHITECTED_TIMER
bool
default y
depends on ARM && (CPU_64v8 || CPU_V7)
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 8dbf91f..cba6344 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -11,9 +11,9 @@ obj-$(CONFIG_CLOCKSOURCE_ORION) += orion.o
obj-$(CONFIG_CLOCKSOURCE_UEMD) += uemd.o
obj-$(CONFIG_CLOCKSOURCE_ROCKCHIP)+= rk_timer.o
obj-$(CONFIG_CLOCKSOURCE_ATMEL_PIT) += timer-atmel-pit.o
-obj-$(CONFIG_CLOCKSOURCE_ARMV8_TIMER) += armv8-timer.o
+obj-$(CONFIG_CLOCKSOURCE_ARM_ARCHITECTED_TIMER) += arm_architected_timer.o
ifneq ($(CONFIG_CPU_V8),y)
-CFLAGS_armv8-timer.o := -march=armv7-a
+CFLAGS_arm_architected_timer.o := -march=armv7-a
endif
obj-$(CONFIG_CLOCKSOURCE_ARM_GLOBAL_TIMER) += arm_global_timer.o
obj-$(CONFIG_CLOCKSOURCE_IMX_GPT) += timer-imx-gpt.o
diff --git a/drivers/clocksource/armv8-timer.c b/drivers/clocksource/arm_architected_timer.c
index 3095f8c..3ca7dfd 100644
--- a/drivers/clocksource/armv8-timer.c
+++ b/drivers/clocksource/arm_architected_timer.c
@@ -20,34 +20,33 @@
#include <io.h>
#include <asm/system.h>
-static uint64_t armv8_clocksource_read(void)
+static uint64_t arm_arch_clocksource_read(void)
{
return get_cntpct();
}
static struct clocksource cs = {
- .read = armv8_clocksource_read,
+ .read = arm_arch_clocksource_read,
.mask = CLOCKSOURCE_MASK(64),
.shift = 0,
};
-static int armv8_timer_probe(struct device_d *dev)
+static int arm_arch_timer_probe(struct device_d *dev)
{
cs.mult = clocksource_hz2mult(get_cntfrq(), cs.shift);
return init_clock(&cs);
}
-static struct of_device_id armv8_timer_dt_ids[] = {
+static struct of_device_id arm_arch_timer_dt_ids[] = {
{ .compatible = "arm,armv7-timer", },
{ .compatible = "arm,armv8-timer", },
{ }
};
-static struct driver_d armv8_timer_driver = {
- .name = "armv8-timer",
- .probe = armv8_timer_probe,
- .of_compatible = DRV_OF_COMPAT(armv8_timer_dt_ids),
+static struct driver_d arm_arch_timer_driver = {
+ .name = "arm-architected-timer",
+ .probe = arm_arch_timer_probe,
+ .of_compatible = DRV_OF_COMPAT(arm_arch_timer_dt_ids),
};
-postcore_platform_driver(armv8_timer_driver);
-
+postcore_platform_driver(arm_arch_timer_driver);
diff --git a/drivers/eeprom/at25.c b/drivers/eeprom/at25.c
index 1c9ef12..56168c2 100644
--- a/drivers/eeprom/at25.c
+++ b/drivers/eeprom/at25.c
@@ -259,7 +259,7 @@ static int at25_np_to_chip(struct device_d *dev,
if (of_property_read_u32(np, "pagesize", &val) == 0 ||
of_property_read_u32(np, "at25,page-size", &val) == 0) {
- chip->page_size = (u16)val;
+ chip->page_size = val;
} else {
dev_err(dev, "Error: missing \"pagesize\" property\n");
return -ENODEV;
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 9764ddf..27674af 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -48,6 +48,11 @@ static struct gpio_info *gpio_to_desc(unsigned gpio)
return NULL;
}
+static unsigned gpioinfo_chip_offset(struct gpio_info *gi)
+{
+ return (gi - gpio_desc) - gi->chip->base;
+}
+
static int gpio_adjust_value(struct gpio_info *gi,
int value)
{
@@ -57,16 +62,10 @@ static int gpio_adjust_value(struct gpio_info *gi,
return !!value ^ gi->active_low;
}
-int gpio_request(unsigned gpio, const char *label)
+static int gpioinfo_request(struct gpio_info *gi, const char *label)
{
- struct gpio_info *gi = gpio_to_desc(gpio);
int ret;
- if (!gi) {
- ret = -ENODEV;
- goto done;
- }
-
if (gi->requested) {
ret = -EBUSY;
goto done;
@@ -75,7 +74,8 @@ int gpio_request(unsigned gpio, const char *label)
ret = 0;
if (gi->chip->ops->request) {
- ret = gi->chip->ops->request(gi->chip, gpio - gi->chip->base);
+ ret = gi->chip->ops->request(gi->chip,
+ gpioinfo_chip_offset(gi));
if (ret)
goto done;
}
@@ -86,8 +86,8 @@ int gpio_request(unsigned gpio, const char *label)
done:
if (ret)
- pr_err("_gpio_request: gpio-%d (%s) status %d\n",
- gpio, label ? : "?", ret);
+ pr_err("_gpio_request: gpio-%td (%s) status %d\n",
+ gi - gpio_desc, label ? : "?", ret);
return ret;
}
@@ -126,18 +126,26 @@ int gpio_find_by_name(const char *name)
return -ENOENT;
}
-void gpio_free(unsigned gpio)
+int gpio_request(unsigned gpio, const char *label)
{
struct gpio_info *gi = gpio_to_desc(gpio);
- if (!gi)
- return;
+ if (!gi) {
+ pr_err("_gpio_request: gpio-%d (%s) status %d\n",
+ gpio, label ? : "?", -ENODEV);
+ return -ENODEV;
+ }
+
+ return gpioinfo_request(gi, label);
+}
+static void gpioinfo_free(struct gpio_info *gi)
+{
if (!gi->requested)
return;
if (gi->chip->ops->free)
- gi->chip->ops->free(gi->chip, gpio - gi->chip->base);
+ gi->chip->ops->free(gi->chip, gpioinfo_chip_offset(gi));
gi->requested = false;
gi->active_low = false;
@@ -145,81 +153,21 @@ void gpio_free(unsigned gpio)
gi->label = NULL;
}
-/**
- * gpio_request_one - request a single GPIO with initial configuration
- * @gpio: the GPIO number
- * @flags: GPIO configuration as specified by GPIOF_*
- * @label: a literal description string of this GPIO
- */
-int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
+void gpio_free(unsigned gpio)
{
- int err;
struct gpio_info *gi = gpio_to_desc(gpio);
- /*
- * Not all of the flags below are mulit-bit, but, for the sake
- * of consistency, the code is written as if all of them were.
- */
- const bool active_low = (flags & GPIOF_ACTIVE_LOW) == GPIOF_ACTIVE_LOW;
- const bool dir_in = (flags & GPIOF_DIR_IN) == GPIOF_DIR_IN;
- const bool logical = (flags & GPIOF_LOGICAL) == GPIOF_LOGICAL;
- const bool init_active = (flags & GPIOF_INIT_ACTIVE) == GPIOF_INIT_ACTIVE;
- const bool init_high = (flags & GPIOF_INIT_HIGH) == GPIOF_INIT_HIGH;
-
- err = gpio_request(gpio, label);
- if (err)
- return err;
-
- gi->active_low = active_low;
-
- if (dir_in)
- err = gpio_direction_input(gpio);
- else if (logical)
- err = gpio_direction_active(gpio, init_active);
- else
- err = gpio_direction_output(gpio, init_high);
-
- if (err)
- gpio_free(gpio);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(gpio_request_one);
-
-/**
- * gpio_request_array - request multiple GPIOs in a single call
- * @array: array of the 'struct gpio'
- * @num: how many GPIOs in the array
- */
-int gpio_request_array(const struct gpio *array, size_t num)
-{
- int i, err;
-
- for (i = 0; i < num; i++, array++) {
- err = gpio_request_one(array->gpio, array->flags, array->label);
- if (err)
- goto err_free;
- }
- return 0;
+ if (!gi)
+ return;
-err_free:
- while (i--)
- gpio_free((--array)->gpio);
- return err;
+ gpioinfo_free(gi);
}
-EXPORT_SYMBOL_GPL(gpio_request_array);
-/**
- * gpio_free_array - release multiple GPIOs in a single call
- * @array: array of the 'struct gpio'
- * @num: how many GPIOs in the array
- */
-void gpio_free_array(const struct gpio *array, size_t num)
+static void gpioinfo_set_value(struct gpio_info *gi, int value)
{
- while (num--)
- gpio_free((array++)->gpio);
+ if (gi->chip->ops->set)
+ gi->chip->ops->set(gi->chip, gpioinfo_chip_offset(gi), value);
}
-EXPORT_SYMBOL_GPL(gpio_free_array);
void gpio_set_value(unsigned gpio, int value)
{
@@ -231,8 +179,7 @@ void gpio_set_value(unsigned gpio, int value)
if (gpio_ensure_requested(gi, gpio))
return;
- if (gi->chip->ops->set)
- gi->chip->ops->set(gi->chip, gpio - gi->chip->base, value);
+ gpioinfo_set_value(gi, value);
}
EXPORT_SYMBOL(gpio_set_value);
@@ -247,6 +194,14 @@ void gpio_set_active(unsigned gpio, bool value)
}
EXPORT_SYMBOL(gpio_set_active);
+static int gpioinfo_get_value(struct gpio_info *gi)
+{
+ if (!gi->chip->ops->get)
+ return -ENOSYS;
+
+ return gi->chip->ops->get(gi->chip, gpioinfo_chip_offset(gi));
+}
+
int gpio_get_value(unsigned gpio)
{
struct gpio_info *gi = gpio_to_desc(gpio);
@@ -259,9 +214,7 @@ int gpio_get_value(unsigned gpio)
if (ret)
return ret;
- if (!gi->chip->ops->get)
- return -ENOSYS;
- return gi->chip->ops->get(gi->chip, gpio - gi->chip->base);
+ return gpioinfo_get_value(gi);
}
EXPORT_SYMBOL(gpio_get_value);
@@ -276,6 +229,15 @@ int gpio_is_active(unsigned gpio)
}
EXPORT_SYMBOL(gpio_is_active);
+static int gpioinfo_direction_output(struct gpio_info *gi, int value)
+{
+ if (!gi->chip->ops->direction_output)
+ return -ENOSYS;
+
+ return gi->chip->ops->direction_output(gi->chip,
+ gpioinfo_chip_offset(gi), value);
+}
+
int gpio_direction_output(unsigned gpio, int value)
{
struct gpio_info *gi = gpio_to_desc(gpio);
@@ -288,13 +250,15 @@ int gpio_direction_output(unsigned gpio, int value)
if (ret)
return ret;
- if (!gi->chip->ops->direction_output)
- return -ENOSYS;
- return gi->chip->ops->direction_output(gi->chip, gpio - gi->chip->base,
- value);
+ return gpioinfo_direction_output(gi, value);
}
EXPORT_SYMBOL(gpio_direction_output);
+static int gpioinfo_direction_active(struct gpio_info *gi, bool value)
+{
+ return gpioinfo_direction_output(gi, gpio_adjust_value(gi, value));
+}
+
int gpio_direction_active(unsigned gpio, bool value)
{
struct gpio_info *gi = gpio_to_desc(gpio);
@@ -302,10 +266,19 @@ int gpio_direction_active(unsigned gpio, bool value)
if (!gi)
return -ENODEV;
- return gpio_direction_output(gpio, gpio_adjust_value(gi, value));
+ return gpioinfo_direction_active(gi, value);
}
EXPORT_SYMBOL(gpio_direction_active);
+static int gpioinfo_direction_input(struct gpio_info *gi)
+{
+ if (!gi->chip->ops->direction_input)
+ return -ENOSYS;
+
+ return gi->chip->ops->direction_input(gi->chip,
+ gpioinfo_chip_offset(gi));
+}
+
int gpio_direction_input(unsigned gpio)
{
struct gpio_info *gi = gpio_to_desc(gpio);
@@ -318,12 +291,96 @@ int gpio_direction_input(unsigned gpio)
if (ret)
return ret;
- if (!gi->chip->ops->direction_input)
- return -ENOSYS;
- return gi->chip->ops->direction_input(gi->chip, gpio - gi->chip->base);
+ return gpioinfo_direction_input(gi);
}
EXPORT_SYMBOL(gpio_direction_input);
+static int gpioinfo_request_one(struct gpio_info *gi, unsigned long flags,
+ const char *label)
+{
+ int err;
+
+ /*
+ * Not all of the flags below are mulit-bit, but, for the sake
+ * of consistency, the code is written as if all of them were.
+ */
+ const bool active_low = (flags & GPIOF_ACTIVE_LOW) == GPIOF_ACTIVE_LOW;
+ const bool dir_in = (flags & GPIOF_DIR_IN) == GPIOF_DIR_IN;
+ const bool logical = (flags & GPIOF_LOGICAL) == GPIOF_LOGICAL;
+ const bool init_active = (flags & GPIOF_INIT_ACTIVE) == GPIOF_INIT_ACTIVE;
+ const bool init_high = (flags & GPIOF_INIT_HIGH) == GPIOF_INIT_HIGH;
+
+ err = gpioinfo_request(gi, label);
+ if (err)
+ return err;
+
+ gi->active_low = active_low;
+
+ if (dir_in)
+ err = gpioinfo_direction_input(gi);
+ else if (logical)
+ err = gpioinfo_direction_active(gi, init_active);
+ else
+ err = gpioinfo_direction_output(gi, init_high);
+
+ if (err)
+ gpioinfo_free(gi);
+
+ return err;
+}
+
+/**
+ * gpio_request_one - request a single GPIO with initial configuration
+ * @gpio: the GPIO number
+ * @flags: GPIO configuration as specified by GPIOF_*
+ * @label: a literal description string of this GPIO
+ */
+int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
+{
+ struct gpio_info *gi = gpio_to_desc(gpio);
+
+ if (!gi)
+ return -ENODEV;
+
+ return gpioinfo_request_one(gi, flags, label);
+}
+EXPORT_SYMBOL_GPL(gpio_request_one);
+
+/**
+ * gpio_request_array - request multiple GPIOs in a single call
+ * @array: array of the 'struct gpio'
+ * @num: how many GPIOs in the array
+ */
+int gpio_request_array(const struct gpio *array, size_t num)
+{
+ int i, err;
+
+ for (i = 0; i < num; i++, array++) {
+ err = gpio_request_one(array->gpio, array->flags, array->label);
+ if (err)
+ goto err_free;
+ }
+ return 0;
+
+err_free:
+ while (i--)
+ gpio_free((--array)->gpio);
+ return err;
+}
+EXPORT_SYMBOL_GPL(gpio_request_array);
+
+/**
+ * gpio_free_array - release multiple GPIOs in a single call
+ * @array: array of the 'struct gpio'
+ * @num: how many GPIOs in the array
+ */
+void gpio_free_array(const struct gpio *array, size_t num)
+{
+ while (num--)
+ gpio_free((array++)->gpio);
+}
+EXPORT_SYMBOL_GPL(gpio_free_array);
+
static int gpiochip_find_base(int start, int ngpio)
{
int i;
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index d56c0de..94c982d 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -632,7 +632,7 @@ static int tegra_i2c_probe(struct device_d *dev)
i2c_dev->rst = reset_control_get(dev, "i2c");
if (IS_ERR(i2c_dev->rst)) {
- dev_err(dev, "missing controller reset");
+ dev_err(dev, "invalid controller reset");
return PTR_ERR(i2c_dev->rst);
}
diff --git a/drivers/led/led-pwm.c b/drivers/led/led-pwm.c
index 16d22b5..8a358dd 100644
--- a/drivers/led/led-pwm.c
+++ b/drivers/led/led-pwm.c
@@ -41,6 +41,9 @@ static void led_pwm_set(struct led *led, unsigned int brightness)
duty *= brightness;
do_div(duty, max);
+ if (pwmled->active_low)
+ duty = pwmled->period - duty;
+
pwm_config(pwmled->pwm, duty, pwmled->period);
}
@@ -54,16 +57,19 @@ static int led_pwm_of_probe(struct device_d *dev)
struct pwm_device *pwm;
pwm = of_pwm_request(child, NULL);
- if (pwm < 0)
+ if (IS_ERR(pwm))
continue;
pwmled = xzalloc(sizeof(*pwmled));
pwmled->led.name = xstrdup(child->name);
pwmled->pwm = pwm;
- of_property_read_u32(child, "max-brightness", &pwmled->led.max_value);
+ ret = of_property_read_u32(child, "max-brightness", &pwmled->led.max_value);
+ if (ret)
+ return ret;
pwmled->period = pwm_get_period(pwmled->pwm);
+ pwmled->active_low = of_property_read_bool(child, "active-low");
pwmled->led.set = led_pwm_set;
diff --git a/drivers/mci/imx-esdhc-common.c b/drivers/mci/imx-esdhc-common.c
index d0bef94..c9d5894 100644
--- a/drivers/mci/imx-esdhc-common.c
+++ b/drivers/mci/imx-esdhc-common.c
@@ -214,7 +214,7 @@ int __esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd,
SDHCI_INT_CMD_COMPLETE, SDHCI_INT_CMD_COMPLETE,
100 * MSECOND);
if (ret) {
- dev_err(host->dev, "timeout 1\n");
+ dev_dbg(host->dev, "timeout 1\n");
return -ETIMEDOUT;
}
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index dd163c3..34aaee5 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -668,10 +668,11 @@ retry_scr:
static void mci_set_ios(struct mci *mci)
{
struct mci_host *host = mci->host;
- struct mci_ios ios;
-
- ios.bus_width = host->bus_width;
- ios.clock = host->clock;
+ struct mci_ios ios = {
+ .bus_width = host->bus_width,
+ .clock = host->clock,
+ .timing = host->timing,
+ };
host->set_ios(host, &ios);
}
@@ -996,6 +997,9 @@ static int mci_startup_sd(struct mci *mci)
mci_set_bus_width(mci, MMC_BUS_WIDTH_4);
}
+ if (mci->tran_speed > 25000000)
+ mci->host->timing = MMC_TIMING_SD_HS;
+
mci_set_clock(mci, mci->tran_speed);
return 0;
@@ -1021,6 +1025,8 @@ static int mci_startup_mmc(struct mci *mci)
mci->tran_speed = 52000000;
else
mci->tran_speed = 26000000;
+
+ host->timing = MMC_TIMING_MMC_HS;
}
mci_set_clock(mci, mci->tran_speed);
@@ -1473,6 +1479,20 @@ static unsigned extract_mtd_year(struct mci *mci)
return year;
}
+static const char *mci_timing_tostr(unsigned timing)
+{
+ switch (timing) {
+ case MMC_TIMING_LEGACY:
+ return "legacy";
+ case MMC_TIMING_MMC_HS:
+ return "MMC HS";
+ case MMC_TIMING_SD_HS:
+ return "SD HS";
+ default:
+ return "unknown"; /* shouldn't happen */
+ }
+}
+
static void mci_print_caps(unsigned caps)
{
printf(" capabilities: %s%s%s%s%s\n",
@@ -1509,6 +1529,7 @@ static void mci_info(struct device_d *dev)
bw = 1;
printf(" current buswidth: %d\n", bw);
+ printf(" current timing: %s\n", mci_timing_tostr(host->timing));
mci_print_caps(host->host_caps);
printf("Card information:\n");
@@ -1801,6 +1822,7 @@ static int mci_detect(struct device_d *dev)
int mci_register(struct mci_host *host)
{
struct mci *mci;
+ struct param_d *param_probe;
int ret;
mci = xzalloc(sizeof(*mci));
@@ -1832,11 +1854,11 @@ int mci_register(struct mci_host *host)
dev_info(mci->host->hw_dev, "registered as %s\n", dev_name(&mci->dev));
- mci->param_probe = dev_add_param_bool(&mci->dev, "probe",
+ param_probe = dev_add_param_bool(&mci->dev, "probe",
mci_set_probe, NULL, &mci->probe, mci);
- if (IS_ERR(mci->param_probe) && PTR_ERR(mci->param_probe) != -ENOSYS) {
- ret = PTR_ERR(mci->param_probe);
+ if (IS_ERR(param_probe) && PTR_ERR(param_probe) != -ENOSYS) {
+ ret = PTR_ERR(param_probe);
dev_dbg(&mci->dev, "Failed to add 'probe' parameter to the MCI device\n");
goto err_unregister;
}
diff --git a/drivers/mci/stm32_sdmmc2.c b/drivers/mci/stm32_sdmmc2.c
index 44f7e62..0c26869 100644
--- a/drivers/mci/stm32_sdmmc2.c
+++ b/drivers/mci/stm32_sdmmc2.c
@@ -622,7 +622,7 @@ static int stm32_sdmmc2_probe(struct amba_device *adev,
priv->reset_ctl = reset_control_get(dev, NULL);
if (IS_ERR(priv->reset_ctl))
- priv->reset_ctl = NULL;
+ return PTR_ERR(priv->reset_ctl);
mci->f_min = 400000;
/* f_max is taken from kernel v5.3 variant_stm32_sdmmc */
@@ -631,6 +631,11 @@ static int stm32_sdmmc2_probe(struct amba_device *adev,
mci_of_parse(&priv->mci);
+ if (mci->f_max >= 26000000)
+ mci->host_caps |= MMC_CAP_MMC_HIGHSPEED;
+ if (mci->f_max >= 52000000)
+ mci->host_caps |= MMC_CAP_MMC_HIGHSPEED_52MHZ;
+
return mci_register(&priv->mci);
priv_free:
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index 8099419..f1e6559 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -19,6 +19,7 @@
#include <xfuncs.h>
#include <of_address.h>
#include <linux/err.h>
+#include <linux/clk.h>
#include <mfd/syscon.h>
@@ -31,34 +32,13 @@ struct syscon {
struct regmap *regmap;
};
-static int syscon_reg_write(void *context, unsigned int reg,
- unsigned int val)
-{
- struct syscon *syscon = context;
- writel(val, syscon->base + reg);
- return 0;
-}
-
-static int syscon_reg_read(void *context, unsigned int reg,
- unsigned int *val)
-{
- struct syscon *syscon = context;
- *val = readl(syscon->base + reg);
- return 0;
-}
-
-static const struct regmap_bus syscon_regmap_bus = {
- .reg_write = syscon_reg_write,
- .reg_read = syscon_reg_read,
-};
-
static const struct regmap_config syscon_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
};
-static struct syscon *of_syscon_register(struct device_node *np)
+static struct syscon *of_syscon_register(struct device_node *np, bool check_clk)
{
int ret;
struct syscon *syscon;
@@ -79,10 +59,23 @@ static struct syscon *of_syscon_register(struct device_node *np)
list_add_tail(&syscon->list, &syscon_list);
- syscon->regmap = regmap_init(NULL,
- &syscon_regmap_bus,
- syscon,
- &syscon_regmap_config);
+ syscon->regmap = of_regmap_init_mmio_clk(np, NULL, syscon->base,
+ &syscon_regmap_config);
+
+ if (check_clk) {
+ struct clk *clk = of_clk_get(np, 0);
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ /* clock is optional */
+ if (ret != -ENOENT)
+ goto err_map;
+ } else {
+ ret = regmap_mmio_attach_clk(syscon->regmap, clk);
+ if (ret)
+ goto err_map;
+ }
+ }
+
return syscon;
err_map:
@@ -101,7 +94,7 @@ static struct syscon *node_to_syscon(struct device_node *np)
}
if (!syscon)
- syscon = of_syscon_register(np);
+ syscon = of_syscon_register(np, true);
if (IS_ERR(syscon))
return ERR_CAST(syscon);
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index fadfe1f..3c5da4a 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -71,12 +71,6 @@ config NAND_IMX
prompt "i.MX NAND driver"
depends on ARCH_IMX
-config NAND_IMX_BBM
- bool
- depends on NAND_BBT
- depends on NAND_IMX
- prompt "i.MX NAND flash bbt creation command"
-
config NAND_MXS
bool
select NAND_BBT
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index a4066ba..274bc29 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -8,7 +8,6 @@ obj-$(CONFIG_NAND_BBT) += nand_bbt.o
obj-$(CONFIG_MTD_NAND_NOMADIK) += nomadik_nand.o
obj-$(CONFIG_NAND_IMX) += nand_imx.o
-obj-$(CONFIG_NAND_IMX_BBM) += nand_imx_bbm.o
obj-$(CONFIG_NAND_OMAP_GPMC) += nand_omap_gpmc.o nand_omap_bch_decoder.o
obj-$(CONFIG_MTD_NAND_OMAP_ELM) += omap_elm.o
obj-$(CONFIG_NAND_ORION) += nand_orion.o
diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c
index 1a065cb..d69a012 100644
--- a/drivers/mtd/nand/nand_imx.c
+++ b/drivers/mtd/nand/nand_imx.c
@@ -1072,7 +1072,7 @@ static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
static struct nand_bbt_descr bbt_main_descr = {
- .options = NAND_BBT_LASTBLOCK
+ .options = NAND_BBT_LASTBLOCK | NAND_BBT_WRITE
| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
.offs = 0,
.len = 4,
@@ -1082,7 +1082,7 @@ static struct nand_bbt_descr bbt_main_descr = {
};
static struct nand_bbt_descr bbt_mirror_descr = {
- .options = NAND_BBT_LASTBLOCK
+ .options = NAND_BBT_LASTBLOCK | NAND_BBT_WRITE
| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
.offs = 0,
.len = 4,
@@ -1117,6 +1117,106 @@ static int __init mxcnd_probe_dt(struct imx_nand_host *host)
}
/*
+ * The i.MX NAND controller has the problem that it handles the
+ * data in chunks of 512 bytes. It doesn't treat 2k NAND chips as
+ * 2048 byte data + 64 OOB, but instead:
+ *
+ * 512b data + 16b OOB +
+ * 512b data + 16b OOB +
+ * 512b data + 16b OOB +
+ * 512b data + 16b OOB
+ *
+ * This means that the factory provided bad block marker ends up
+ * in the page data at offset 2000 instead of in the OOB data.
+ *
+ * To preserve the factory bad block information we take the following
+ * strategy:
+ *
+ * - If the NAND driver detects that no flash BBT is present on 2k NAND
+ * chips it will not create one because it would do so based on the wrong
+ * BBM position
+ * - This command is used to create a flash BBT then.
+ *
+ * From this point on we can forget about the BBMs and rely completely
+ * on the flash BBT.
+ *
+ */
+static int checkbad(struct mtd_info *mtd, loff_t ofs)
+{
+ int ret;
+ uint8_t buf[mtd->writesize + mtd->oobsize];
+ struct mtd_oob_ops ops;
+
+ ops.mode = MTD_OPS_RAW;
+ ops.ooboffs = 0;
+ ops.datbuf = buf;
+ ops.len = mtd->writesize;
+ ops.oobbuf = buf + mtd->writesize;
+ ops.ooblen = mtd->oobsize;
+
+ ret = mtd_read_oob(mtd, ofs, &ops);
+ if (ret < 0)
+ return ret;
+
+ if (buf[2000] != 0xff)
+ return 1;
+
+ return 0;
+}
+
+static int imxnd_create_bbt(struct mtd_info *mtd)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ int len, i, numblocks, ret;
+ loff_t from = 0;
+ uint8_t *bbt;
+
+ len = mtd->size >> (chip->bbt_erase_shift + 2);
+
+ /* Allocate memory (2bit per block) and clear the memory bad block table */
+ bbt = kzalloc(len, GFP_KERNEL);
+ if (!bbt)
+ return -ENOMEM;
+
+ numblocks = mtd->size >> (chip->bbt_erase_shift - 1);
+
+ for (i = 0; i < numblocks;) {
+ ret = checkbad(mtd, from);
+ if (ret < 0)
+ goto out;
+
+ if (ret) {
+ bbt[i >> 3] |= 0x03 << (i & 0x6);
+ dev_info(mtd->parent, "Bad eraseblock %d at 0x%08x\n",
+ i >> 1, (unsigned int)from);
+ }
+
+ i += 2;
+ from += (1 << chip->bbt_erase_shift);
+ }
+
+ chip->bbt_td->options |= NAND_BBT_CREATE;
+ chip->bbt_md->options |= NAND_BBT_CREATE;
+
+ free(chip->bbt);
+ chip->bbt = bbt;
+
+ ret = nand_update_bbt(mtd, 0);
+ if (ret)
+ return ret;
+
+ ret = nand_default_bbt(mtd);
+ if (ret)
+ return ret;
+
+ ret = 0;
+out:
+ free(bbt);
+
+ return ret;
+}
+
+/*
* This function is called during the driver binding process.
*
* @param pdev the device structure used to store device specific
@@ -1312,8 +1412,8 @@ static int __init imxnd_probe(struct device_d *dev)
if (nfc_is_v21())
writew(NFC_V2_SPAS_SPARESIZE(64), host->regs + NFC_V2_SPAS);
} else {
- bbt_main_descr.options |= NAND_BBT_WRITE | NAND_BBT_CREATE;
- bbt_mirror_descr.options |= NAND_BBT_WRITE | NAND_BBT_CREATE;
+ bbt_main_descr.options |= NAND_BBT_CREATE;
+ bbt_mirror_descr.options |= NAND_BBT_CREATE;
if (nfc_is_v21())
writew(NFC_V2_SPAS_SPARESIZE(16), host->regs + NFC_V2_SPAS);
@@ -1329,10 +1429,12 @@ static int __init imxnd_probe(struct device_d *dev)
}
if (host->flash_bbt && this->bbt_td->pages[0] == -1 && this->bbt_md->pages[0] == -1) {
- dev_warn(dev, "no BBT found. create one using the imx_nand_bbm command\n");
- } else {
- bbt_main_descr.options |= NAND_BBT_WRITE | NAND_BBT_CREATE;
- bbt_mirror_descr.options |= NAND_BBT_WRITE | NAND_BBT_CREATE;
+ dev_info(dev, "no BBT found. creating one\n");
+ err = imxnd_create_bbt(mtd);
+ if (err)
+ dev_warn(dev, "Failed to create bbt: %s\n",
+ strerror(-err));
+ err = 0;
}
add_mtd_nand_device(mtd, "nand");
diff --git a/drivers/mtd/nand/nand_imx_bbm.c b/drivers/mtd/nand/nand_imx_bbm.c
deleted file mode 100644
index c005482..0000000
--- a/drivers/mtd/nand/nand_imx_bbm.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * imx_nand_bbm.c - create a flash bad block table for i.MX NAND
- *
- * Copyright (c) 2013 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <common.h>
-#include <command.h>
-#include <fs.h>
-#include <errno.h>
-#include <getopt.h>
-#include <fcntl.h>
-#include <malloc.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/err.h>
-
-/*
- * The i.MX NAND controller has the problem that it handles the
- * data in chunks of 512 bytes. It doesn't treat 2k NAND chips as
- * 2048 byte data + 64 OOB, but instead:
- *
- * 512b data + 16b OOB +
- * 512b data + 16b OOB +
- * 512b data + 16b OOB +
- * 512b data + 16b OOB
- *
- * This means that the factory provided bad block marker ends up
- * in the page data at offset 2000 instead of in the OOB data.
- *
- * To preserve the factory bad block information we take the following
- * strategy:
- *
- * - If the NAND driver detects that no flash BBT is present on 2k NAND
- * chips it will not create one because it would do so based on the wrong
- * BBM position
- * - This command is used to create a flash BBT then.
- *
- * From this point on we can forget about the BBMs and rely completely
- * on the flash BBT.
- *
- */
-static int checkbad(struct mtd_info *mtd, loff_t ofs)
-{
- int ret;
- uint8_t buf[mtd->writesize + mtd->oobsize];
- struct mtd_oob_ops ops;
-
- ops.mode = MTD_OPS_RAW;
- ops.ooboffs = 0;
- ops.datbuf = buf;
- ops.len = mtd->writesize;
- ops.oobbuf = buf + mtd->writesize;
- ops.ooblen = mtd->oobsize;
-
- ret = mtd_read_oob(mtd, ofs, &ops);
- if (ret < 0)
- return ret;
-
- if (buf[2000] != 0xff)
- return 1;
-
- return 0;
-}
-
-static void *create_bbt(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
- int len, i, numblocks, ret;
- loff_t from = 0;
- uint8_t *bbt;
-
- if ((chip->bbt_td && chip->bbt_td->pages[0] != -1) ||
- (chip->bbt_md && chip->bbt_md->pages[0] != -1)) {
- printf("Flash bbt already present\n");
- return ERR_PTR(-EEXIST);
- }
-
- len = mtd->size >> (chip->bbt_erase_shift + 2);
-
- /* Allocate memory (2bit per block) and clear the memory bad block table */
- bbt = kzalloc(len, GFP_KERNEL);
- if (!bbt)
- return ERR_PTR(-ENOMEM);
-
- numblocks = mtd->size >> (chip->bbt_erase_shift - 1);
-
- for (i = 0; i < numblocks;) {
- ret = checkbad(mtd, from);
- if (ret < 0)
- goto out;
-
- if (ret) {
- bbt[i >> 3] |= 0x03 << (i & 0x6);
- printf("Bad eraseblock %d at 0x%08x\n", i >> 1,
- (unsigned int)from);
- }
-
- i += 2;
- from += (1 << chip->bbt_erase_shift);
- }
-
- return bbt;
-
-out:
- free(bbt);
-
- return ERR_PTR(ret);
-}
-
-static int attach_bbt(struct mtd_info *mtd, void *bbt)
-{
- struct nand_chip *chip = mtd_to_nand(mtd);
-
- chip->bbt_td->options |= NAND_BBT_WRITE | NAND_BBT_CREATE;
- chip->bbt_md->options |= NAND_BBT_WRITE | NAND_BBT_CREATE;
- free(chip->bbt);
- chip->bbt = bbt;
-
- return nand_update_bbt(mtd, 0);
-}
-
-static int do_imx_nand_bbm(int argc, char *argv[])
-{
- int opt, ret;
- struct cdev *cdev;
- struct mtd_info *mtd;
- int yes = 0;
- void *bbt;
-
- while ((opt = getopt(argc, argv, "y")) > 0) {
- switch (opt) {
- case 'y':
- yes = 1;
- break;
- default:
- return COMMAND_ERROR_USAGE;
- }
- }
-
- cdev = cdev_open("nand0", O_RDWR);
- if (!cdev)
- return -ENOENT;
-
- mtd = cdev->mtd;
- if (!mtd)
- return -EINVAL;
-
- if (strcmp(mtd->name, "imx_nand")) {
- printf("This is not an i.MX nand but a %s\n", mtd->name);
- ret = -EINVAL;
- goto out;
- }
-
- switch (mtd->writesize) {
- case 512:
- printf("writesize is 512. This command is not needed\n");
- ret = 1;
- goto out;
- case 2048:
- break;
- default:
- printf("not implemented for writesize %d\n", mtd->writesize);
- ret = 1;
- goto out;
- }
-
- bbt = create_bbt(mtd);
- if (IS_ERR(bbt)) {
- ret = 1;
- goto out;
- }
-
- if (!yes) {
- int c;
-
- printf("create flash bbt (y/n)?");
- c = getchar();
- if (c == 'y')
- yes = 1;
- printf("\n");
- }
-
- if (!yes) {
- free(bbt);
- ret = 1;
-
- goto out;
- }
-
- ret = attach_bbt(mtd, bbt);
- if (!ret)
- printf("bbt successfully added\n");
- else
- free(bbt);
-
-out:
- cdev_close(cdev);
-
- return ret;
-}
-
-BAREBOX_CMD_START(imx_nand_bbm)
- .cmd = do_imx_nand_bbm,
- BAREBOX_CMD_DESC("create BBT for i.MX NAND")
- BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
-BAREBOX_CMD_END
diff --git a/drivers/net/designware_socfpga.c b/drivers/net/designware_socfpga.c
index ce3ac38..d6c28af 100644
--- a/drivers/net/designware_socfpga.c
+++ b/drivers/net/designware_socfpga.c
@@ -77,8 +77,7 @@ static int socfpga_gen5_set_phy_mode(struct socfpga_dwc_dev *dwc_dev)
}
/* Assert reset to the enet controller before changing the phy mode */
- if (eth_dev->rst)
- reset_control_assert(eth_dev->rst);
+ reset_control_assert(eth_dev->rst);
ctrl = readl(dwc_dev->sys_mgr_base + reg_offset);
ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift);
@@ -104,8 +103,7 @@ static int socfpga_gen5_set_phy_mode(struct socfpga_dwc_dev *dwc_dev)
/* Deassert reset for the phy configuration to be sampled by
* the enet controller, and operation to start in requested mode
*/
- if (eth_dev->rst)
- reset_control_deassert(eth_dev->rst);
+ reset_control_deassert(eth_dev->rst);
return 0;
}
@@ -124,8 +122,7 @@ static int socfpga_gen10_set_phy_mode(struct socfpga_dwc_dev *dwc_dev)
}
/* Assert reset to the enet controller before changing the phy mode */
- if (eth_dev->rst)
- reset_control_assert(eth_dev->rst);
+ reset_control_assert(eth_dev->rst);
ctrl = readl(dwc_dev->sys_mgr_base + reg_offset);
ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift);
@@ -151,8 +148,7 @@ static int socfpga_gen10_set_phy_mode(struct socfpga_dwc_dev *dwc_dev)
/* Deassert reset for the phy configuration to be sampled by
* the enet controller, and operation to start in requested mode
*/
- if (eth_dev->rst)
- reset_control_deassert(eth_dev->rst);
+ reset_control_deassert(eth_dev->rst);
return 0;
}
@@ -212,8 +208,10 @@ static int socfpga_dwc_ether_probe(struct device_d *dev)
return PTR_ERR(priv);
priv->rst = reset_control_get(dev, NULL);
- if (IS_ERR(priv->rst))
- dev_warn(dev, "No reset lines.\n");
+ if (IS_ERR(priv->rst)) {
+ dev_err(dev, "Invalid reset lines.\n");
+ return PTR_ERR(priv->rst);
+ }
dwc_dev->priv = priv;
diff --git a/drivers/net/designware_stm32.c b/drivers/net/designware_stm32.c
index 4c682a5..1e0cdfa 100644
--- a/drivers/net/designware_stm32.c
+++ b/drivers/net/designware_stm32.c
@@ -57,12 +57,11 @@ static inline struct eqos_stm32 *to_stm32(struct eqos *eqos)
return eqos->priv;
}
-enum { CLK_STMMACETH, CLK_MAX_RX, CLK_MAX_TX, CLK_SYSCFG, };
+enum { CLK_STMMACETH, CLK_MAX_RX, CLK_MAX_TX, };
static const struct clk_bulk_data stm32_clks[] = {
[CLK_STMMACETH] = { .id = "stmmaceth" },
[CLK_MAX_RX] = { .id = "mac-clk-rx" },
[CLK_MAX_TX] = { .id = "mac-clk-tx" },
- [CLK_SYSCFG] = { .id = "syscfg-clk" },
};
static unsigned long eqos_get_csr_clk_rate_stm32(struct eqos *eqos)
diff --git a/drivers/nvmem/ocotp.c b/drivers/nvmem/ocotp.c
index 79693e2..34e33de 100644
--- a/drivers/nvmem/ocotp.c
+++ b/drivers/nvmem/ocotp.c
@@ -712,6 +712,14 @@ static struct imx_ocotp_data imx6ul_ocotp_data = {
.format_mac = imx_ocotp_format_mac,
};
+static struct imx_ocotp_data imx6ull_ocotp_data = {
+ .num_regs = 256,
+ .addr_to_offset = imx6q_addr_to_offset,
+ .mac_offsets_num = 2,
+ .mac_offsets = { MAC_OFFSET_0, IMX6UL_MAC_OFFSET_1 },
+ .format_mac = imx_ocotp_format_mac,
+};
+
static struct imx_ocotp_data vf610_ocotp_data = {
.num_regs = 512,
.addr_to_offset = vf610_addr_to_offset,
@@ -742,6 +750,9 @@ static __maybe_unused struct of_device_id imx_ocotp_dt_ids[] = {
.compatible = "fsl,imx6ul-ocotp",
.data = &imx6ul_ocotp_data,
}, {
+ .compatible = "fsl,imx6ull-ocotp",
+ .data = &imx6ull_ocotp_data,
+ }, {
.compatible = "fsl,imx8mq-ocotp",
.data = &imx8mq_ocotp_data,
}, {
diff --git a/drivers/pci/pci-layerscape.c b/drivers/pci/pci-layerscape.c
index e20dd55..c4ed529 100644
--- a/drivers/pci/pci-layerscape.c
+++ b/drivers/pci/pci-layerscape.c
@@ -22,6 +22,8 @@
#include <of_address.h>
#include <of_pci.h>
#include <regmap.h>
+#include <magicvar.h>
+#include <globalvar.h>
#include <mfd/syscon.h>
#include <linux/pci.h>
#include <linux/phy/phy.h>
@@ -57,6 +59,13 @@ struct ls_pcie_drvdata {
const struct dw_pcie_ops *dw_pcie_ops;
};
+#define PCIE_LUT_ENTRY_COUNT 32
+
+struct ls_pcie_lut_entry {
+ int stream_id;
+ uint16_t devid;
+};
+
struct ls_pcie {
struct dw_pcie pci;
void __iomem *lut;
@@ -65,6 +74,7 @@ struct ls_pcie {
const struct ls_pcie_drvdata *drvdata;
int index;
int next_lut_index;
+ struct ls_pcie_lut_entry luts[PCIE_LUT_ENTRY_COUNT];
};
static struct ls_pcie *to_ls_pcie(struct dw_pcie *pci)
@@ -72,11 +82,6 @@ static struct ls_pcie *to_ls_pcie(struct dw_pcie *pci)
return container_of(pci, struct ls_pcie, pci);
}
-static u32 lut_readl(struct ls_pcie *pcie, unsigned int offset)
-{
- return in_be32(pcie->lut + offset);
-}
-
static void lut_writel(struct ls_pcie *pcie, unsigned int value,
unsigned int offset)
{
@@ -98,8 +103,6 @@ static int ls_pcie_next_streamid(struct ls_pcie *pcie)
return current;
}
-#define PCIE_LUT_ENTRY_COUNT 32
-
static int ls_pcie_next_lut_index(struct ls_pcie *pcie)
{
if (pcie->next_lut_index < PCIE_LUT_ENTRY_COUNT)
@@ -108,14 +111,6 @@ static int ls_pcie_next_lut_index(struct ls_pcie *pcie)
return -ENOSPC; /* LUT is full */
}
-static void ls_pcie_lut_set_mapping(struct ls_pcie *pcie, int index, u32 devid,
- u32 stream_id)
-{
- /* leave mask as all zeroes, want to match all bits */
- lut_writel(pcie, devid << 16, PCIE_LUT_UDR(index));
- lut_writel(pcie, stream_id | PCIE_LUT_ENABLE, PCIE_LUT_LDR(index));
-}
-
static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
{
struct dw_pcie *pci = &pcie->pci;
@@ -354,6 +349,24 @@ static phandle ls_pcie_get_iommu_handle(struct device_node *np, phandle *handle)
return 0;
}
+/*
+ * Normally every device gets its own stream_id. The stream_ids are communicated
+ * to the kernel in the device tree and are also configured in the controllers
+ * LUT table.
+ * This only works when all PCI devices are known in the bootloader which may not
+ * always be the case. For example, when a PCI device is a FPGA and its firmware
+ * is only loaded under Linux, then the device is not known to barebox and thus
+ * not assigned a stream_id.
+ *
+ * With ls_pcie_share_stream_id = true all devices on a host controller get the
+ * same stream_id assigned.
+ */
+static int ls_pcie_share_stream_id;
+
+BAREBOX_MAGICVAR_NAMED(global_ls_pcie_share_stream_id,
+ global.layerscape_pcie.share_stream_ids,
+ "If true, use a stream_id per host controller and not per device");
+
static int ls_pcie_of_fixup(struct device_node *root, void *ctx)
{
struct ls_pcie *pcie = ctx;
@@ -375,8 +388,6 @@ static int ls_pcie_of_fixup(struct device_node *root, void *ctx)
return -ENODEV;
} while (!of_device_is_compatible(np, pcie->compatible));
- nluts = pcie->next_lut_index;
-
ret = of_property_read_u32(np, "msi-parent", &phandle);
if (ret) {
dev_err(pcie->pci.dev, "Unable to get \"msi-parent\" phandle\n");
@@ -389,28 +400,56 @@ static int ls_pcie_of_fixup(struct device_node *root, void *ctx)
return ret;
}
- msi_map = xmalloc(nluts * sizeof(u32) * 4);
- iommu_map = xmalloc(nluts * sizeof(u32) * 4);
-
- for (i = 0; i < nluts; i++) {
- u32 udr = lut_readl(pcie, PCIE_LUT_UDR(i));
- u32 ldr = lut_readl(pcie, PCIE_LUT_LDR(i));
-
- if (!(ldr & PCIE_LUT_ENABLE))
- break;
-
- devid = udr >> 16;
- stream_id = ldr & 0x7fff;
-
- msi_map[i * 4] = devid;
- msi_map[i * 4 + 1] = phandle;
- msi_map[i * 4 + 2] = stream_id;
- msi_map[i * 4 + 3] = 1;
+ if (ls_pcie_share_stream_id) {
+ nluts = 1;
+ iommu_map = xmalloc(nluts * sizeof(u32) * 4);
+ msi_map = xmalloc(nluts * sizeof(u32) * 4);
+ stream_id = pcie->luts[0].stream_id;
+
+ dev_dbg(pcie->pci.dev, "Using stream_id %d\n", stream_id);
+
+ msi_map[0] = 0;
+ msi_map[1] = phandle;
+ msi_map[2] = stream_id;
+ msi_map[3] = 0x10000;
+
+ iommu_map[0] = 0;
+ iommu_map[1] = iommu_handle;
+ iommu_map[2] = stream_id;
+ iommu_map[3] = 0x10000;
+
+ lut_writel(pcie, 0xffff, PCIE_LUT_UDR(0));
+ lut_writel(pcie, pcie->luts[0].stream_id | PCIE_LUT_ENABLE, PCIE_LUT_LDR(0));
+ } else {
+ nluts = pcie->next_lut_index;
+ iommu_map = xmalloc(nluts * sizeof(u32) * 4);
+ msi_map = xmalloc(nluts * sizeof(u32) * 4);
+
+ for (i = 0; i < nluts; i++) {
+ devid = pcie->luts[i].devid;
+ stream_id = pcie->luts[i].stream_id;
+
+ dev_dbg(pcie->pci.dev, "Using stream_id %d for device 0x%04x\n",
+ stream_id, devid);
+
+ msi_map[i * 4] = devid;
+ msi_map[i * 4 + 1] = phandle;
+ msi_map[i * 4 + 2] = stream_id;
+ msi_map[i * 4 + 3] = 1;
+
+ iommu_map[i * 4] = devid;
+ iommu_map[i * 4 + 1] = iommu_handle;
+ iommu_map[i * 4 + 2] = stream_id;
+ iommu_map[i * 4 + 3] = 1;
+
+ lut_writel(pcie, pcie->luts[i].devid << 16, PCIE_LUT_UDR(i));
+ lut_writel(pcie, pcie->luts[i].stream_id | PCIE_LUT_ENABLE, PCIE_LUT_LDR(i));
+ }
+ }
- iommu_map[i * 4] = devid;
- iommu_map[i * 4 + 1] = iommu_handle;
- iommu_map[i * 4 + 2] = stream_id;
- iommu_map[i * 4 + 3] = 1;
+ for (i = nluts; i < PCIE_LUT_ENTRY_COUNT; i++) {
+ lut_writel(pcie, 0, PCIE_LUT_UDR(i));
+ lut_writel(pcie, 0, PCIE_LUT_LDR(i));
}
/*
@@ -448,6 +487,13 @@ static int __init ls_pcie_probe(struct device_d *dev)
struct resource *dbi_base;
const struct of_device_id *match;
int ret;
+ static int once;
+
+ if (!once) {
+ globalvar_add_simple_bool("layerscape_pcie.share_stream_ids",
+ &ls_pcie_share_stream_id);
+ once = 1;
+ }
pcie = xzalloc(sizeof(*pcie));
if (!pcie)
@@ -502,6 +548,7 @@ static void ls_pcie_fixup(struct pci_dev *pcidev)
struct dw_pcie *dwpcie = container_of(pp, struct dw_pcie, pp);
struct ls_pcie *lspcie = container_of(dwpcie, struct ls_pcie, pci);
int stream_id, index;
+ uint32_t devid;
int base_bus_num = 0;
stream_id = ls_pcie_next_streamid(lspcie);
@@ -513,9 +560,10 @@ static void ls_pcie_fixup(struct pci_dev *pcidev)
p = p->parent_bus;
}
- ls_pcie_lut_set_mapping(lspcie, index,
- (pcidev->bus->number - base_bus_num) << 8 | pcidev->devfn,
- stream_id);
+ devid = (pcidev->bus->number - base_bus_num) << 8 | pcidev->devfn;
+
+ lspcie->luts[index].devid = devid;
+ lspcie->luts[index].stream_id = stream_id;
}
DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ls_pcie_fixup);
diff --git a/drivers/pinctrl/imx-iomux-v3.c b/drivers/pinctrl/imx-iomux-v3.c
index 5fadc84..1d2b76d 100644
--- a/drivers/pinctrl/imx-iomux-v3.c
+++ b/drivers/pinctrl/imx-iomux-v3.c
@@ -216,11 +216,14 @@ static int imx_iomux_v3_probe(struct device_d *dev)
return ret;
}
+static struct imx_iomux_v3_data imx_iomux_imx6_snvs_data = {
+ .flags = ZERO_OFFSET_VALID,
+};
+
static struct imx_iomux_v3_data imx_iomux_imx7_lpsr_data = {
.flags = ZERO_OFFSET_VALID | IMX7_PINMUX_LPSR,
};
-
static __maybe_unused struct of_device_id imx_iomux_v3_dt_ids[] = {
{
.compatible = "fsl,imx25-iomuxc",
@@ -239,6 +242,9 @@ static __maybe_unused struct of_device_id imx_iomux_v3_dt_ids[] = {
}, {
.compatible = "fsl,imx6ul-iomuxc",
}, {
+ .compatible = "fsl,imx6ull-iomuxc-snvs",
+ .data = &imx_iomux_imx6_snvs_data,
+ }, {
.compatible = "fsl,imx6sl-iomuxc",
}, {
.compatible = "fsl,imx7d-iomuxc",
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 3c581ed..2cd58df 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -29,7 +29,13 @@ struct pinctrl_single {
struct pinctrl_device pinctrl;
unsigned (*read)(void __iomem *reg);
void (*write)(unsigned val, void __iomem *reg);
- unsigned width;
+ unsigned int width;
+ unsigned int fmask;
+ unsigned int fshift;
+ unsigned int fmax;
+
+ bool bits_per_mux;
+ unsigned int bits_per_pin;
};
static unsigned __maybe_unused pcs_readb(void __iomem *reg)
@@ -66,27 +72,47 @@ static int pcs_set_state(struct pinctrl_device *pdev, struct device_node *np)
{
struct pinctrl_single *pcs = container_of(pdev, struct pinctrl_single, pinctrl);
unsigned size = 0, index = 0;
+ unsigned int offset, val, rows, mask, reg, i;
const __be32 *mux;
dev_dbg(pcs->pinctrl.dev, "set state: %s\n", np->full_name);
-
- mux = of_get_property(np, "pinctrl-single,pins", &size);
-
- size /= sizeof(*mux); /* Number of elements in array */
-
- if (!mux || !size || (size & 1)) {
- dev_err(pcs->pinctrl.dev, "bad data for mux %s\n",
- np->full_name);
- return -EINVAL;
- }
-
- while (index < size) {
- unsigned offset, val;
-
- offset = be32_to_cpup(mux + index++);
- val = be32_to_cpup(mux + index++);
-
- pcs->write(val, pcs->base + offset);
+ if (pcs->bits_per_mux) {
+ mux = of_get_property(np, "pinctrl-single,bits", &size);
+ if (size % 3 != 0)
+ dev_err(pcs->pinctrl.dev,
+ "invalid args_count for spec: %u\n", size);
+
+ size /= sizeof(*mux); /* Number of elements in array */
+ rows = size / 3;
+
+ for (i = 0; i < rows; i++) {
+ offset = be32_to_cpup(mux + index++);
+ val = be32_to_cpup(mux + index++);
+ mask = be32_to_cpup(mux + index++);
+ reg = pcs->read(pcs->base + offset);
+ reg &= ~mask;
+ reg |= val;
+ pcs->write(reg, pcs->base + offset);
+ }
+ } else {
+ mux = of_get_property(np, "pinctrl-single,pins", &size);
+
+ size /= sizeof(*mux); /* Number of elements in array */
+
+ if (!mux || !size || (size & 1)) {
+ dev_err(pcs->pinctrl.dev, "bad data for mux %s\n",
+ np->full_name);
+ return -EINVAL;
+ }
+
+ while (index < size) {
+ unsigned int offset, val;
+
+ offset = be32_to_cpup(mux + index++);
+ val = be32_to_cpup(mux + index++);
+
+ pcs->write(val, pcs->base + offset);
+ }
}
return 0;
@@ -137,6 +163,23 @@ static int pcs_probe(struct device_d *dev)
goto out;
}
+ ret = of_property_read_u32(np, "pinctrl-single,function-mask",
+ &pcs->fmask);
+ if (!ret) {
+ pcs->fshift = __ffs(pcs->fmask);
+ pcs->fmax = pcs->fmask >> pcs->fshift;
+ } else {
+ /* If mask property doesn't exist, function mux is invalid. */
+ pcs->fmask = 0;
+ pcs->fshift = 0;
+ pcs->fmax = 0;
+ }
+
+ pcs->bits_per_mux =
+ of_property_read_bool(np, "pinctrl-single,bit-per-mux");
+ if (pcs->bits_per_mux)
+ pcs->bits_per_pin = fls(pcs->fmask);
+
ret = pinctrl_register(&pcs->pinctrl);
if (ret)
goto out;
diff --git a/drivers/pwm/pxa_pwm.c b/drivers/pwm/pxa_pwm.c
index c7130c2..4575817 100644
--- a/drivers/pwm/pxa_pwm.c
+++ b/drivers/pwm/pxa_pwm.c
@@ -34,8 +34,6 @@ struct pxa_pwm_chip {
struct pwm_chip chip;
void __iomem *iobase;
int id;
- int duty_ns;
- int period_ns;
};
static struct pxa_pwm_chip *to_pxa_pwm_chip(struct pwm_chip *chip)
@@ -72,15 +70,12 @@ static int pxa_pwm_config(struct pwm_chip *chip, int duty_ns, int period_ns)
else
dc = (pv + 1) * duty_ns / period_ns;
- pxa_pwm->duty_ns = duty_ns;
- pxa_pwm->period_ns = period_ns;
-
/* NOTE: the clock to PWM has to be enabled first
* before writing to the registers
*/
- __raw_writel(prescale, pxa_pwm->iobase + PWMCR);
- __raw_writel(dc, pxa_pwm->iobase + PWMDCR);
- __raw_writel(pv, pxa_pwm->iobase + PWMPCR);
+ writel(prescale, pxa_pwm->iobase + PWMCR);
+ writel(dc, pxa_pwm->iobase + PWMDCR);
+ writel(pv, pxa_pwm->iobase + PWMPCR);
return 0;
}
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 28bd69a..f47a115 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -19,7 +19,7 @@ config REGULATOR_BCM283X
config REGULATOR_PFUZE
bool "Freescale PFUZE100/200/3000 regulator driver"
depends on I2C
- depends on ARCH_IMX6
+ depends on ARCH_IMX6 || ARCH_IMX8MQ
config REGULATOR_STPMIC1
tristate "STMicroelectronics STPMIC1 PMIC Regulators"
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index cb5d785..78b8290 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -86,7 +86,8 @@ static int regulator_fixed_probe(struct device_d *dev)
fix->rdesc.ops = &fixed_ops;
fix->rdev.desc = &fix->rdesc;
- if (of_find_property(dev->device_node, "regulator-always-on", NULL)) {
+ if (of_find_property(dev->device_node, "regulator-always-on", NULL) ||
+ of_find_property(dev->device_node, "regulator-boot-on", NULL)) {
fix->always_on = 1;
regulator_fixed_enable(&fix->rdev);
}
diff --git a/drivers/regulator/pfuze.c b/drivers/regulator/pfuze.c
index 1950ffb..91aaec0 100644
--- a/drivers/regulator/pfuze.c
+++ b/drivers/regulator/pfuze.c
@@ -31,8 +31,6 @@
#define DRIVERNAME "pfuze"
-#define MC13XXX_NUMREGS 0x3f
-
#define PFUZE100_SW1ABMODE 0x23
#define PFUZE100_SW1CMODE 0x31
#define PFUZE100_SW2MODE 0x38
@@ -144,8 +142,6 @@ static void pfuze_power_off_prepare(struct poweroff_handler *handler)
regmap_write_bits(pfuze_dev->map, PFUZE100_VGEN6VOL,
PFUZE100_VGENxLPWR | PFUZE100_VGENxSTBY,
PFUZE100_VGENxSTBY);
-
- imx6_pm_stby_poweroff();
}
static struct regmap_bus regmap_pfuze_i2c_bus = {
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 8874775..466bbe5 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -406,6 +406,9 @@ static int usb_device_list_scan(void)
if (ret)
goto out;
}
+
+ /* Avoid hammering the HUB with port scans */
+ mdelay(25);
}
out:
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 96aecac..426ee9d 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -769,7 +769,7 @@ static void __maybe_unused cb_boot(struct f_fastboot *f_fb, const char *opt)
globalvar_set_match("linux.bootargs.dyn.", "");
globalvar_set_match("bootm.image", "");
- data.os_file = xstrdup(FASTBOOT_TMPFILE);
+ data.os_file = FASTBOOT_TMPFILE;
ret = bootm_boot(&data);
diff --git a/drivers/usb/gadget/fsl_udc.c b/drivers/usb/gadget/fsl_udc.c
index a44c7ab..c7160cd 100644
--- a/drivers/usb/gadget/fsl_udc.c
+++ b/drivers/usb/gadget/fsl_udc.c
@@ -1128,18 +1128,18 @@ out:
/* Fill in the dTD structure
* @req: request that the transfer belongs to
- * @length: return actually data length of the dTD
* @dma: return dma address of the dTD
* @is_last: return flag if it is the last dTD of the request
* return: pointer to the built dTD */
-static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
+static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req,
dma_addr_t *dma, int *is_last)
{
+ unsigned length;
u32 swap_temp;
struct ep_td_struct *dtd;
/* how big will this transfer be? */
- *length = min(req->req.length - req->req.actual,
+ length = min(req->req.length - req->req.actual,
(unsigned)EP_MAX_LENGTH_TRANSFER);
dtd = dma_alloc_coherent(sizeof(struct ep_td_struct),
@@ -1161,11 +1161,11 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
dtd->buff_ptr3 = cpu_to_le32(swap_temp + 0x3000);
dtd->buff_ptr4 = cpu_to_le32(swap_temp + 0x4000);
- req->req.actual += *length;
+ req->req.actual += length;
/* zlp is needed if req->req.zero is set */
if (req->req.zero) {
- if (*length == 0 || (*length % req->ep->ep.maxpacket) != 0)
+ if (length == 0 || (length % req->ep->ep.maxpacket) != 0)
*is_last = 1;
else
*is_last = 0;
@@ -1177,7 +1177,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
if ((*is_last) == 0)
VDBG("multi-dtd request!");
/* Fill in the transfer size; set active bit */
- swap_temp = ((*length << DTD_LENGTH_BIT_POS) | DTD_STATUS_ACTIVE);
+ swap_temp = ((length << DTD_LENGTH_BIT_POS) | DTD_STATUS_ACTIVE);
/* Enable interrupt for the last dtd of a request */
if (*is_last && !req->req.no_interrupt)
@@ -1193,14 +1193,13 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
/* Generate dtd chain for a request */
static int fsl_req_to_dtd(struct fsl_req *req)
{
- unsigned count;
int is_last;
int is_first =1;
struct ep_td_struct *last_dtd = NULL, *dtd;
dma_addr_t dma;
do {
- dtd = fsl_build_dtd(req, &count, &dma, &is_last);
+ dtd = fsl_build_dtd(req, &dma, &is_last);
if (dtd == NULL)
return -ENOMEM;
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 4c11e65..b84da55 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -1136,8 +1136,9 @@ fail2:
musb_platform_exit(musb);
fail1:
- dev_err(musb->controller,
- "musb_init_controller failed with status %d\n", status);
+ if (status != -EPROBE_DEFER)
+ dev_err(musb->controller,
+ "musb_init_controller failed with status %d\n", status);
musb_free(musb);
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 3b76b6c..d54a663 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -39,7 +39,6 @@
#include <linux/barebox-wrapper.h>
#include "musb_core.h"
-#include "phy-am335x.h"
static __maybe_unused struct of_device_id musb_dsps_dt_ids[];
@@ -217,10 +216,6 @@ static int dsps_musb_init(struct musb *musb)
const struct dsps_musb_wrapper *wrp = glue->wrp;
u32 rev, val, mode;
- musb->xceiv = am335x_get_usb_phy();
- if (IS_ERR(musb->xceiv))
- return PTR_ERR(musb->xceiv);
-
/* Returns zero if e.g. not clocked */
rev = dsps_readl(musb->ctrl_base, wrp->revision);
if (!rev)
@@ -319,11 +314,13 @@ static int dsps_set_mode(void *ctx, enum usb_dr_mode mode)
static int dsps_probe(struct device_d *dev)
{
- struct resource *iores;
+ struct resource *iores[2];
struct musb_hdrc_platform_data *pdata;
struct musb_hdrc_config *config;
struct device_node *dn = dev->device_node;
const struct dsps_musb_wrapper *wrp;
+ struct device_node *phy_node;
+ struct device_d *phy_dev;
struct dsps_glue *glue;
int ret;
@@ -337,6 +334,14 @@ static int dsps_probe(struct device_d *dev)
return -ENODEV;
}
+ phy_node = of_parse_phandle(dn, "phys", 0);
+ if (!phy_node)
+ return -ENODEV;
+
+ phy_dev = of_find_device_by_node(phy_node);
+ if (!phy_dev || !phy_dev->priv)
+ return -EPROBE_DEFER;
+
/* allocate glue */
glue = kzalloc(sizeof(*glue), GFP_KERNEL);
if (!glue) {
@@ -349,17 +354,22 @@ static int dsps_probe(struct device_d *dev)
pdata = &glue->pdata;
- iores = dev_request_mem_resource(dev, 0);
- if (IS_ERR(iores))
- return PTR_ERR(iores);
- glue->musb.mregs = IOMEM(iores->start);
+ iores[0] = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores[0])) {
+ ret = PTR_ERR(iores[0]);
+ goto free_glue;
+ }
+ glue->musb.mregs = IOMEM(iores[0]->start);
- iores = dev_request_mem_resource(dev, 1);
- if (IS_ERR(iores))
- return PTR_ERR(iores);
- glue->musb.ctrl_base = IOMEM(iores->start);
+ iores[1] = dev_request_mem_resource(dev, 1);
+ if (IS_ERR(iores[1])) {
+ ret = PTR_ERR(iores[1]);
+ goto release_iores0;
+ }
+ glue->musb.ctrl_base = IOMEM(iores[1]->start);
glue->musb.controller = dev;
+ glue->musb.xceiv = phy_dev->priv;
config = &glue->config;
@@ -377,11 +387,24 @@ static int dsps_probe(struct device_d *dev)
if (pdata->mode == MUSB_PORT_MODE_DUAL_ROLE) {
ret = usb_register_otg_device(dev, dsps_set_mode, glue);
if (ret)
- return ret;
+ goto release_iores1;
return 0;
}
- return musb_init_controller(&glue->musb, pdata);
+ ret = musb_init_controller(&glue->musb, pdata);
+ if (ret)
+ goto release_iores1;
+
+ return 0;
+
+release_iores1:
+ release_region(iores[1]);
+release_iores0:
+ release_region(iores[0]);
+free_glue:
+ free(glue);
+
+ return ret;
}
static const struct dsps_musb_wrapper am33xx_driver_data = {
diff --git a/drivers/usb/musb/phy-am335x-control.c b/drivers/usb/musb/phy-am335x-control.c
index c84525e..41a3689 100644
--- a/drivers/usb/musb/phy-am335x-control.c
+++ b/drivers/usb/musb/phy-am335x-control.c
@@ -109,15 +109,15 @@ struct phy_control *am335x_get_phy_control(struct device_d *dev)
node = of_parse_phandle(dev->device_node, "ti,ctrl_mod", 0);
if (!node)
- return NULL;
+ return ERR_PTR(-ENOENT);
dev = of_find_device_by_node(node);
if (!dev)
- return NULL;
+ return ERR_PTR(-EPROBE_DEFER);
ctrl_usb = dev->priv;
if (!ctrl_usb)
- return NULL;
+ return ERR_PTR(-EPROBE_DEFER);
return &ctrl_usb->phy_ctrl;
}
@@ -141,13 +141,17 @@ static int am335x_control_usb_probe(struct device_d *dev)
ctrl_usb->dev = dev;
iores = dev_request_mem_resource(dev, 0);
- if (IS_ERR(iores))
- return PTR_ERR(iores);
+ if (IS_ERR(iores)) {
+ ret = PTR_ERR(iores);
+ goto free_ctrl;
+ }
ctrl_usb->phy_reg = IOMEM(iores->start);
iores = dev_request_mem_resource(dev, 1);
- if (IS_ERR(iores))
- return PTR_ERR(iores);
+ if (IS_ERR(iores)) {
+ ret = PTR_ERR(iores);
+ goto release_resource;
+ }
ctrl_usb->wkup = IOMEM(iores->start);
spin_lock_init(&ctrl_usb->lock);
@@ -155,6 +159,13 @@ static int am335x_control_usb_probe(struct device_d *dev)
dev->priv = ctrl_usb;
return 0;
+
+release_resource:
+ release_region(iores);
+free_ctrl:
+ free(ctrl_usb);
+
+ return 0;
};
static struct driver_d am335x_control_driver = {
diff --git a/drivers/usb/musb/phy-am335x.c b/drivers/usb/musb/phy-am335x.c
index df31255..f2e870d 100644
--- a/drivers/usb/musb/phy-am335x.c
+++ b/drivers/usb/musb/phy-am335x.c
@@ -5,7 +5,6 @@
#include <linux/err.h>
#include "am35x-phy-control.h"
#include "musb_core.h"
-#include "phy-am335x.h"
struct am335x_usbphy {
void __iomem *base;
@@ -14,13 +13,6 @@ struct am335x_usbphy {
struct usb_phy phy;
};
-static struct am335x_usbphy *am_usbphy;
-
-struct usb_phy *am335x_get_usb_phy(void)
-{
- return &am_usbphy->phy;
-}
-
static int am335x_init(struct usb_phy *phy)
{
struct am335x_usbphy *am_usbphy = container_of(phy, struct am335x_usbphy, phy);
@@ -31,6 +23,7 @@ static int am335x_init(struct usb_phy *phy)
static int am335x_phy_probe(struct device_d *dev)
{
+ struct am335x_usbphy *am_usbphy;
struct resource *iores;
int ret;
@@ -44,22 +37,27 @@ static int am335x_phy_probe(struct device_d *dev)
am_usbphy->base = IOMEM(iores->start);
am_usbphy->phy_ctrl = am335x_get_phy_control(dev);
- if (!am_usbphy->phy_ctrl)
- return -ENODEV;
+ if (IS_ERR(am_usbphy->phy_ctrl)) {
+ ret = PTR_ERR(am_usbphy->phy_ctrl);
+ goto err_release;
+ }
am_usbphy->id = of_alias_get_id(dev->device_node, "phy");
if (am_usbphy->id < 0) {
dev_err(dev, "Missing PHY id: %d\n", am_usbphy->id);
- return am_usbphy->id;
+ ret = am_usbphy->id;
+ goto err_release;
}
am_usbphy->phy.init = am335x_init;
- dev->priv = am_usbphy;
+ dev->priv = &am_usbphy->phy;
dev_info(dev, "am_usbphy %p enabled\n", &am_usbphy->phy);
return 0;
+err_release:
+ release_region(iores);
err_free:
free(am_usbphy);
diff --git a/drivers/usb/musb/phy-am335x.h b/drivers/usb/musb/phy-am335x.h
deleted file mode 100644
index 27da2e3..0000000
--- a/drivers/usb/musb/phy-am335x.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _PHY_AM335x_H_
-#define _PHY_AM335x_H_
-
-struct usb_phy *am335x_get_usb_phy(void);
-
-#endif
diff --git a/drivers/video/backlight-pwm.c b/drivers/video/backlight-pwm.c
index 997235a..9111a42 100644
--- a/drivers/video/backlight-pwm.c
+++ b/drivers/video/backlight-pwm.c
@@ -204,8 +204,6 @@ static int backlight_pwm_of_probe(struct device_d *dev)
return PTR_ERR(pwm_backlight->power);
}
- pwm_backlight->period = pwm_get_period(pwm_backlight->pwm);
-
pwm_backlight->backlight.slew_time_ms = 100;
pwm_backlight->backlight.brightness_set = backlight_pwm_set;
pwm_backlight->backlight.node = dev->device_node;
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
index 85e810f..cb0d17e 100644
--- a/drivers/watchdog/dw_wdt.c
+++ b/drivers/watchdog/dw_wdt.c
@@ -72,9 +72,9 @@ static int dw_wdt_stop(struct watchdog *wdd)
{
struct dw_wdt *dw_wdt = to_dw_wdt(wdd);
- if (IS_ERR(dw_wdt->rst)) {
- dev_warn(dw_wdt->wdd.hwdev, "No reset line. Will not stop.\n");
- return PTR_ERR(dw_wdt->rst);
+ if (!dw_wdt->rst) {
+ dev_warn(dw_wdt->wdd.hwdev, "No reset line\n");
+ return -ENOSYS;
}
reset_control_assert(dw_wdt->rst);
@@ -153,7 +153,7 @@ static int dw_wdt_drv_probe(struct device_d *dev)
dw_wdt->rst = reset_control_get(dev, NULL);
if (IS_ERR(dw_wdt->rst))
- dev_warn(dev, "No reset lines. Will not be able to stop once started.\n");
+ return PTR_ERR(dw_wdt->rst);
wdd = &dw_wdt->wdd;
wdd->name = "dw_wdt";
@@ -171,8 +171,10 @@ static int dw_wdt_drv_probe(struct device_d *dev)
if (ret)
dev_warn(dev, "cannot register restart handler\n");
- if (!IS_ERR(dw_wdt->rst))
+ if (dw_wdt->rst)
reset_control_deassert(dw_wdt->rst);
+ else
+ dev_warn(dev, "No reset lines. Will not be able to stop once started.\n");
return 0;
@@ -187,6 +189,7 @@ static struct of_device_id dw_wdt_of_match[] = {
};
static struct driver_d dw_wdt_driver = {
+ .name = "dw-wdt",
.probe = dw_wdt_drv_probe,
.of_compatible = DRV_OF_COMPAT(dw_wdt_of_match),
};
diff --git a/drivers/watchdog/wd_core.c b/drivers/watchdog/wd_core.c
index b6e2a37..3404040 100644
--- a/drivers/watchdog/wd_core.c
+++ b/drivers/watchdog/wd_core.c
@@ -171,8 +171,10 @@ int watchdog_register(struct watchdog *wd)
return ret;
p = dev_add_param_tristate_ro(&wd->dev, "running", &wd->running);
- if (IS_ERR(p))
- return PTR_ERR(p);
+ if (IS_ERR(p)) {
+ ret = PTR_ERR(p);
+ goto error_unregister;
+ }
if (!wd->priority)
wd->priority = dev_get_watchdog_priority(wd->hwdev);
@@ -180,8 +182,10 @@ int watchdog_register(struct watchdog *wd)
p = dev_add_param_uint32(&wd->dev, "priority",
watchdog_set_priority, NULL,
&wd->priority, "%u", wd);
- if (IS_ERR(p))
- return PTR_ERR(p);
+ if (IS_ERR(p)) {
+ ret = PTR_ERR(p);
+ goto error_unregister;
+ }
/* set some default sane value */
if (!wd->timeout_max)
@@ -189,8 +193,10 @@ int watchdog_register(struct watchdog *wd)
p = dev_add_param_uint32_ro(&wd->dev, "timeout_max",
&wd->timeout_max, "%u");
- if (IS_ERR(p))
- return PTR_ERR(p);
+ if (IS_ERR(p)) {
+ ret = PTR_ERR(p);
+ goto error_unregister;
+ }
if (IS_ENABLED(CONFIG_WATCHDOG_POLLER)) {
if (!wd->poller_timeout_cur ||
@@ -199,12 +205,14 @@ int watchdog_register(struct watchdog *wd)
p = dev_add_param_uint32(&wd->dev, "timeout_cur", watchdog_set_cur,
NULL, &wd->poller_timeout_cur, "%u", wd);
- if (IS_ERR(p))
- return PTR_ERR(p);
+ if (IS_ERR(p)) {
+ ret = PTR_ERR(p);
+ goto error_unregister;
+ }
ret = watchdog_register_poller(wd);
if (ret)
- return ret;
+ goto error_unregister;
}
list_add_tail(&wd->list, &watchdog_list);
@@ -213,6 +221,10 @@ int watchdog_register(struct watchdog *wd)
wd->priority);
return 0;
+
+error_unregister:
+ unregister_device(&wd->dev);
+ return ret;
}
EXPORT_SYMBOL(watchdog_register);