summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/aiodev/Kconfig6
-rw-r--r--drivers/aiodev/Makefile1
-rw-r--r--drivers/aiodev/st_gyro.c122
-rw-r--r--drivers/base/driver.c46
-rw-r--r--drivers/base/platform.c2
-rw-r--r--drivers/base/power.c24
-rw-r--r--drivers/base/regmap/regmap-i2c.c37
-rw-r--r--drivers/base/resource.c2
-rw-r--r--drivers/block/Kconfig21
-rw-r--r--drivers/block/Makefile2
-rw-r--r--drivers/block/efi-block-io.c5
-rw-r--r--drivers/ddr/imx8m/ddr_init.c33
-rw-r--r--drivers/ddr/imx8m/ddrphy_train.c74
-rw-r--r--drivers/efi/efi-device.c3
-rw-r--r--drivers/firmware/arm_scmi/driver.c9
-rw-r--r--drivers/gpio/gpio-pcf857x.c6
-rw-r--r--drivers/gpio/gpiolib.c60
-rw-r--r--drivers/i2c/busses/i2c-bcm283x.c23
-rw-r--r--drivers/i2c/busses/i2c-imx-early.c21
-rw-r--r--drivers/led/led-pca955x.c5
-rw-r--r--drivers/mci/atmel-sdhci-pbl.c2
-rw-r--r--drivers/mci/atmel_mci_pbl.c5
-rw-r--r--drivers/mci/imx-esdhc-pbl.c2
-rw-r--r--drivers/mci/mci-core.c10
-rw-r--r--drivers/mfd/Kconfig9
-rw-r--r--drivers/mfd/Makefile3
-rw-r--r--drivers/mfd/core.c25
-rw-r--r--drivers/mfd/rk808.c395
-rw-r--r--drivers/net/Kconfig64
-rw-r--r--drivers/net/designware_eqos.c11
-rw-r--r--drivers/net/designware_eqos.h2
-rw-r--r--drivers/net/designware_stm32.c9
-rw-r--r--drivers/net/designware_tegra186.c2
-rw-r--r--drivers/net/e1000/e1000.h3
-rw-r--r--drivers/net/e1000/main.c44
-rw-r--r--drivers/net/fec_imx.c11
-rw-r--r--drivers/net/rtl8169.c51
-rw-r--r--drivers/of/base.c101
-rw-r--r--drivers/of/of_gpio.c5
-rw-r--r--drivers/phy/phy-core.c11
-rw-r--r--drivers/pinctrl/pinctrl-stm32.c42
-rw-r--r--drivers/power/reset/reboot-mode.c35
-rw-r--r--drivers/pwm/pwm-atmel.c383
-rw-r--r--drivers/pwm/pwm-imx.c8
-rw-r--r--drivers/regulator/Kconfig11
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/core.c81
-rw-r--r--drivers/regulator/fixed.c13
-rw-r--r--drivers/regulator/rk808-regulator.c963
-rw-r--r--drivers/reset/core.c15
-rw-r--r--drivers/rtc/rtc-abracon.c5
-rw-r--r--drivers/rtc/rtc-pcf85363.c5
-rw-r--r--drivers/serial/serial_ns16550.c10
-rw-r--r--drivers/soc/imx/gpcv2.c2
-rw-r--r--drivers/spi/stm32_spi.c20
-rw-r--r--drivers/usb/gadget/Kconfig7
-rw-r--r--drivers/usb/gadget/multi.c15
-rw-r--r--drivers/usb/imx/chipidea-imx.c10
-rw-r--r--drivers/video/stm32_ltdc.c2
-rw-r--r--drivers/watchdog/imxwd.c18
60 files changed, 2474 insertions, 439 deletions
diff --git a/drivers/aiodev/Kconfig b/drivers/aiodev/Kconfig
index 88a3b9a343..6bd697702e 100644
--- a/drivers/aiodev/Kconfig
+++ b/drivers/aiodev/Kconfig
@@ -30,6 +30,12 @@ config LM75
help
Support for LM75 and similar devices
+config ST_GYRO
+ tristate "ST L3GD20 SPI gyro driver"
+ depends on SPI
+ help
+ Support for L3GD20 three-axis angular rate sensor.
+
config MC13XXX_ADC
tristate "MC13XXX ADC driver"
depends on MFD_MC13XXX
diff --git a/drivers/aiodev/Makefile b/drivers/aiodev/Makefile
index 4c92a403a2..06a63b0d2d 100644
--- a/drivers/aiodev/Makefile
+++ b/drivers/aiodev/Makefile
@@ -3,6 +3,7 @@
obj-$(CONFIG_AIODEV) += core.o
obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
obj-$(CONFIG_LM75) += lm75.o
+obj-$(CONFIG_ST_GYRO) += st_gyro.o
obj-$(CONFIG_MC13XXX_ADC) += mc13xxx_adc.o
obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o
obj-$(CONFIG_AM335X_ADC) += am335x_adc.o
diff --git a/drivers/aiodev/st_gyro.c b/drivers/aiodev/st_gyro.c
new file mode 100644
index 0000000000..3938d8239e
--- /dev/null
+++ b/drivers/aiodev/st_gyro.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2022 Ahmad Fatoum
+
+#include <common.h>
+#include <driver.h>
+#include <xfuncs.h>
+#include <spi/spi.h>
+#include <aiodev.h>
+
+#define ST_GYRO_WHO_AM_I 0x0F
+#define ST_GYRO_CTRL_REG1 0x20
+
+#define ST_GYRO_DEFAULT_OUT_TEMP_ADDR 0x26
+#define ST_GYRO_DEFAULT_OUT_X_L_ADDR 0x28
+#define ST_GYRO_DEFAULT_OUT_Y_L_ADDR 0x2a
+#define ST_GYRO_DEFAULT_OUT_Z_L_ADDR 0x2c
+
+#define ST_GYRO_OUT_L_ADDR(idx) \
+ (ST_GYRO_DEFAULT_OUT_X_L_ADDR + 2 * (idx))
+
+#define ST_GYRO_OUT_H_ADDR(idx) \
+ (ST_GYRO_OUT_L_ADDR(idx) + 1)
+
+#define ST_GYRO_READ 0x80
+#define ST_GYRO_WRITE 0x00
+#define ST_GYRO_MULTI 0x40
+
+struct st_gyro {
+ struct aiodevice aiodev;
+ struct aiochannel aiochan[4];
+ struct spi_device *spi;
+};
+#define to_st_gyro(chan) container_of(chan->aiodev, struct st_gyro, aiodev)
+
+static int st_gyro_read(struct aiochannel *chan, int *val)
+{
+ struct st_gyro *gyro = to_st_gyro(chan);
+ int ret;
+ u8 tx;
+ u8 rx_h, rx_l;
+
+ if (chan->index == 3) {
+ tx = ST_GYRO_DEFAULT_OUT_TEMP_ADDR | ST_GYRO_READ;
+ ret = spi_write_then_read(gyro->spi, &tx, 1, &rx_l, 1);
+ if (ret)
+ return ret;
+
+ *val = (s8)rx_l;
+ return 0;
+ }
+
+ tx = ST_GYRO_OUT_H_ADDR(chan->index) | ST_GYRO_READ;
+ ret = spi_write_then_read(gyro->spi, &tx, 1, &rx_h, 1);
+ if (ret)
+ return ret;
+
+ tx = ST_GYRO_OUT_L_ADDR(chan->index) | ST_GYRO_READ;
+ ret = spi_write_then_read(gyro->spi, &tx, 1, &rx_l, 1);
+ if (ret)
+ return ret;
+
+ *val = (s16)((rx_h << 8) | rx_l);
+ *val *= 250;
+ *val >>= 16;
+
+ return 0;
+}
+
+static int st_gyro_probe(struct device_d *dev)
+{
+ u8 tx[2], rx[2];
+ struct st_gyro *gyro;
+ int ret, i;
+
+ gyro = xzalloc(sizeof(*gyro));
+ gyro->spi = to_spi_device(dev);
+
+ tx[0] = ST_GYRO_WHO_AM_I | ST_GYRO_READ;
+ ret = spi_write_then_read(gyro->spi, tx, 1, rx, 1);
+ if (ret)
+ return -EIO;
+ if (rx[0] != 0xD4)
+ return dev_err_probe(dev, -ENODEV, "unexpected device WAI: %02x\n", rx[0]);
+
+ /* initialize device */
+ tx[0] = ST_GYRO_CTRL_REG1 | ST_GYRO_WRITE;
+ tx[1] = 0xF; /* normal mode, 3 channels */
+ ret = spi_write(gyro->spi, tx, 2);
+ if (ret)
+ return -EIO;
+
+ gyro->aiodev.num_channels = 4;
+ gyro->aiodev.hwdev = dev;
+ gyro->aiodev.read = st_gyro_read;
+ gyro->aiodev.name = "gyroscope";
+ gyro->aiodev.channels =
+ xmalloc(gyro->aiodev.num_channels *
+ sizeof(gyro->aiodev.channels[0]));
+ for (i = 0; i < 3; i++) {
+ gyro->aiodev.channels[i] = &gyro->aiochan[i];
+ gyro->aiochan[i].unit = "dps";
+ gyro->aiochan[i].index = i;
+ }
+
+ gyro->aiodev.channels[3] = &gyro->aiochan[3];
+ gyro->aiochan[3].unit = "C";
+ gyro->aiochan[3].index = 3;
+
+ return aiodevice_register(&gyro->aiodev);
+}
+
+static const struct of_device_id st_gyro_match[] = {
+ { .compatible = "st,l3gd20-gyro" },
+ { /* sentinel */ }
+};
+
+static struct driver_d st_gyro_driver = {
+ .name = "st_gyro",
+ .probe = st_gyro_probe,
+ .of_compatible = st_gyro_match,
+};
+device_spi_driver(st_gyro_driver);
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 303ca061ce..e7288f6a61 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -265,6 +265,8 @@ int unregister_device(struct device_d *old_dev)
/* remove device from parents child list */
if (old_dev->parent)
list_del(&old_dev->sibling);
+ if (dev_of_node(old_dev))
+ old_dev->device_node->dev = NULL;
return 0;
}
@@ -283,6 +285,7 @@ void free_device_res(struct device_d *dev)
dev->name = NULL;
free(dev->unique_name);
dev->unique_name = NULL;
+ free(dev->deferred_probe_reason);
}
EXPORT_SYMBOL(free_device_res);
@@ -333,9 +336,13 @@ static int device_probe_deferred(void)
}
} while (success);
- list_for_each_entry(dev, &deferred, active)
- dev_err(dev, "probe permanently deferred\n");
-
+ list_for_each_entry(dev, &deferred, active) {
+ if (dev->deferred_probe_reason)
+ dev_err(dev, "probe permanently deferred (%s)\n",
+ dev->deferred_probe_reason);
+ else
+ dev_err(dev, "probe permanently deferred\n");
+ }
return 0;
}
late_initcall(device_probe_deferred);
@@ -573,6 +580,24 @@ const void *device_get_match_data(struct device_d *dev)
return NULL;
}
+static void device_set_deferred_probe_reason(struct device_d *dev, const struct va_format *vaf)
+{
+ char *reason;
+ char *last_char;
+
+ free(dev->deferred_probe_reason);
+
+ reason = xasprintf("%pV", vaf);
+
+ /* drop newline char at end of reason string */
+ last_char = reason + strlen(reason) - 1;
+
+ if (*last_char == '\n')
+ *last_char = '\0';
+
+ dev->deferred_probe_reason = reason;
+}
+
/**
* dev_err_probe - probe error check and log helper
* @loglevel: log level configured in source file
@@ -584,8 +609,12 @@ const void *device_get_match_data(struct device_d *dev)
* This helper implements common pattern present in probe functions for error
* checking: print debug or error message depending if the error value is
* -EPROBE_DEFER and propagate error upwards.
- * In case of -EPROBE_DEFER it sets also defer probe reason, which can be
- * checked later by reading devices_deferred debugfs attribute.
+ *
+ * In case of -EPROBE_DEFER it sets the device's deferred_probe_reason attribute,
+ * but does not report an error. The error is recorded and displayed later, if
+ * (and only if) the probe is permanently deferred. For all other error codes,
+ * it just outputs the error along with the formatted message.
+ *
* It replaces code sequence::
*
* if (err != -EPROBE_DEFER)
@@ -601,8 +630,8 @@ const void *device_get_match_data(struct device_d *dev)
* Returns @err.
*
*/
-int dev_err_probe(const struct device_d *dev, int err, const char *fmt, ...);
-int dev_err_probe(const struct device_d *dev, int err, const char *fmt, ...)
+int dev_err_probe(struct device_d *dev, int err, const char *fmt, ...);
+int dev_err_probe(struct device_d *dev, int err, const char *fmt, ...)
{
struct va_format vaf;
va_list args;
@@ -611,6 +640,9 @@ int dev_err_probe(const struct device_d *dev, int err, const char *fmt, ...)
vaf.fmt = fmt;
vaf.va = &args;
+ if (err == -EPROBE_DEFER)
+ device_set_deferred_probe_reason(dev, &vaf);
+
dev_printf(err == -EPROBE_DEFER ? MSG_DEBUG : MSG_ERR,
dev, "error %pe: %pV", ERR_PTR(err), &vaf);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 2fb73917b4..c0ea2746b3 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -17,7 +17,7 @@ static int platform_probe(struct device_d *dev)
ret = genpd_dev_pm_attach(dev);
if (ret < 0)
- return ret;
+ return dev_err_probe(dev, ret, "power domain attach failed\n");
return dev->driver->probe(dev);
}
diff --git a/drivers/base/power.c b/drivers/base/power.c
index 96cac1a091..4a206051b1 100644
--- a/drivers/base/power.c
+++ b/drivers/base/power.c
@@ -139,14 +139,32 @@ static struct generic_pm_domain *genpd_get_from_provider(
struct of_phandle_args *genpdspec)
{
struct generic_pm_domain *genpd = ERR_PTR(-ENOENT);
+ struct device_node *node = genpdspec->np;
struct of_genpd_provider *provider;
+ int ret;
if (!genpdspec)
return ERR_PTR(-EINVAL);
+ ret = of_device_ensure_probed(node);
+ if (ret) {
+ struct device_node *parent;
+
+ /*
+ * If "barebox,allow-dummy" property is set for power domain
+ * provider, assume it's turned on.
+ */
+ parent = of_get_parent(node);
+ if (of_get_property(node, "barebox,allow-dummy", NULL) ||
+ of_get_property(parent, "barebox,allow-dummy", NULL))
+ return NULL;
+
+ return ERR_PTR(ret);
+ }
+
/* Check if we have such a provider in our array */
list_for_each_entry(provider, &of_genpd_providers, link) {
- if (provider->node == genpdspec->np)
+ if (provider->node == node)
genpd = provider->xlate(genpdspec, provider->data);
if (!IS_ERR(genpd))
break;
@@ -175,7 +193,7 @@ static int genpd_power_on(struct generic_pm_domain *genpd, unsigned int depth)
{
int ret;
- if (genpd_status_on(genpd))
+ if (!genpd || genpd_status_on(genpd))
return 0;
ret = _genpd_power_on(genpd, true);
@@ -211,7 +229,7 @@ static int __genpd_dev_pm_attach(struct device_d *dev, struct device_node *np,
return (ret == -ENOENT) ? -EPROBE_DEFER : ret;
}
- dev_dbg(dev, "adding to PM domain %s\n", pd->name);
+ dev_dbg(dev, "adding to PM domain %s\n", pd ? pd->name : "dummy");
if (power_on)
ret = genpd_power_on(pd, 0);
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
index 5e3705162c..756bc224cc 100644
--- a/drivers/base/regmap/regmap-i2c.c
+++ b/drivers/base/regmap/regmap-i2c.c
@@ -42,3 +42,40 @@ struct regmap *regmap_init_i2c(struct i2c_client *client,
{
return regmap_init(&client->dev, &regmap_regmap_i2c_bus, client, config);
}
+
+static int regmap_smbus_byte_reg_read(void *client, unsigned int reg, unsigned int *val)
+{
+ int ret;
+
+ if (reg > 0xff)
+ return -EINVAL;
+
+ ret = i2c_smbus_read_byte_data(client, reg);
+ if (ret < 0)
+ return ret;
+
+ *val = ret;
+
+ return 0;
+}
+
+static int regmap_smbus_byte_reg_write(void *client, unsigned int reg, unsigned int val)
+{
+ if (val > 0xff || reg > 0xff)
+ return -EINVAL;
+
+ return i2c_smbus_write_byte_data(client, reg, val);
+}
+
+static const struct regmap_bus regmap_smbus_byte = {
+ .reg_write = regmap_smbus_byte_reg_write,
+ .reg_read = regmap_smbus_byte_reg_read,
+};
+
+struct regmap *regmap_init_i2c_smbus(struct i2c_client *client,
+ const struct regmap_config *config)
+{
+ if (config->val_bits != 8 || config->reg_bits != 8)
+ return ERR_PTR(-ENOSYS);
+ return regmap_init(&client->dev, &regmap_smbus_byte, client, config);
+}
diff --git a/drivers/base/resource.c b/drivers/base/resource.c
index d0d3962077..0134456ffa 100644
--- a/drivers/base/resource.c
+++ b/drivers/base/resource.c
@@ -20,7 +20,7 @@ struct device_d *device_alloc(const char *devname, int id)
return dev;
}
-int device_add_data(struct device_d *dev, void *data, size_t size)
+int device_add_data(struct device_d *dev, const void *data, size_t size)
{
free(dev->platform_data);
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 68a11438dc..625e81a4ec 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -5,3 +5,24 @@ config VIRTIO_BLK
help
This is the virtual block driver for virtio. It can be used with
QEMU based VMMs (like KVM or Xen).
+
+config EFI_BLK
+ bool "EFI block I/O driver"
+ default y
+ depends on EFI_BOOTUP
+
+config EFI_BLK_SEPARATE_USBDISK
+ bool "rename USB devices to /dev/usbdiskX"
+ default y
+ depends on EFI_BLK
+ help
+ EFI block devices will be normally called /dev/diskX. Setting this
+ option will cause block devices instantiated from handles with a
+ EFI_USB_IO protocol to be called /dev/usbdiskX instead. Note that
+ some buggy UEFI implementations have been observed to not do this
+ consistently for all USB mass storage. If you need to absolutely
+ be sure your boot device is a USB mass storage device and you can't
+ fix your UEFI, consider disabling this options and setting a GUID
+ for your disk and checking against it with
+
+ devlookup -v $bootguid /dev/disk$bootsource_instance guid
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index c50bdc1d02..a4e14a559c 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_EFI_BOOTUP) += efi-block-io.o
+obj-$(CONFIG_EFI_BLK) += efi-block-io.o
obj-$(CONFIG_VIRTIO_BLK) += virtio_blk.o
diff --git a/drivers/block/efi-block-io.c b/drivers/block/efi-block-io.c
index 086afb378a..b78117d445 100644
--- a/drivers/block/efi-block-io.c
+++ b/drivers/block/efi-block-io.c
@@ -140,7 +140,8 @@ static void efi_bio_print_info(struct device_d *dev)
static bool is_bio_usbdev(struct efi_device *efidev)
{
- return efi_device_has_guid(efidev, EFI_USB_IO_PROTOCOL_GUID);
+ return IS_ENABLED(CONFIG_EFI_BLK_SEPARATE_USBDISK) &&
+ efi_device_has_guid(efidev, EFI_USB_IO_PROTOCOL_GUID);
}
static int efi_bio_probe(struct efi_device *efidev)
@@ -187,7 +188,7 @@ static int efi_bio_probe(struct efi_device *efidev)
return ret;
if (efi_get_bootsource() == efidev)
- bootsource_set_instance(instance);
+ bootsource_set_raw_instance(instance);
parse_partition_table(&priv->blk);
diff --git a/drivers/ddr/imx8m/ddr_init.c b/drivers/ddr/imx8m/ddr_init.c
index 9a4b4e2ca8..18969ddb53 100644
--- a/drivers/ddr/imx8m/ddr_init.c
+++ b/drivers/ddr/imx8m/ddr_init.c
@@ -49,17 +49,18 @@ static void ddr_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num)
*/
#define IMX8M_SAVED_DRAM_TIMING_BASE 0x180000
-static int imx8m_ddr_init(struct dram_timing_info *dram_timing,
- enum ddrc_type type)
+int imx8m_ddr_init(struct dram_timing_info *dram_timing,
+ unsigned type)
{
unsigned long src_ddrc_rcr = MX8M_SRC_DDRC_RCR_ADDR;
unsigned int tmp, initial_drate, target_freq;
+ enum ddrc_type ddrc_type = get_ddrc_type(type);
int ret;
pr_debug("start DRAM init\n");
/* Step1: Follow the power up procedure */
- switch (type) {
+ switch (ddrc_type) {
case DDRC_TYPE_MQ:
reg32_write(src_ddrc_rcr + 0x04, 0x8f00000f);
reg32_write(src_ddrc_rcr, 0x8f00000f);
@@ -81,7 +82,7 @@ static int imx8m_ddr_init(struct dram_timing_info *dram_timing,
initial_drate = dram_timing->fsp_msg[0].drate;
/* default to the frequency point 0 clock */
- ddrphy_init_set_dfi_clk(initial_drate, type);
+ ddrphy_init_set_dfi_clk(initial_drate, ddrc_type);
/* D-aasert the presetn */
reg32_write(src_ddrc_rcr, 0x8F000006);
@@ -107,7 +108,7 @@ static int imx8m_ddr_init(struct dram_timing_info *dram_timing,
/* if ddr type is LPDDR4, do it */
tmp = reg32_read(DDRC_MSTR(0));
- if (tmp & (0x1 << 5) && type != DDRC_TYPE_MN)
+ if (tmp & (0x1 << 5) && ddrc_type != DDRC_TYPE_MN)
reg32_write(DDRC_DDR_SS_GPR0, 0x01); /* LPDDR4 mode */
/* determine the initial boot frequency */
@@ -154,7 +155,7 @@ static int imx8m_ddr_init(struct dram_timing_info *dram_timing,
reg32_write(DDRC_SWCTL(0), 0x00000000);
/* Apply rank-to-rank workaround */
- update_umctl2_rank_space_setting(dram_timing->fsp_msg_num - 1, type);
+ update_umctl2_rank_space_setting(dram_timing->fsp_msg_num - 1, ddrc_type);
/* Step16: Set DFIMISC.dfi_init_start to 1 */
setbits_le32(DDRC_DFIMISC(0), (0x1 << 5));
@@ -210,23 +211,3 @@ static int imx8m_ddr_init(struct dram_timing_info *dram_timing,
return 0;
}
-
-int imx8mm_ddr_init(struct dram_timing_info *dram_timing)
-{
- return imx8m_ddr_init(dram_timing, DDRC_TYPE_MM);
-}
-
-int imx8mn_ddr_init(struct dram_timing_info *dram_timing)
-{
- return imx8m_ddr_init(dram_timing, DDRC_TYPE_MN);
-}
-
-int imx8mq_ddr_init(struct dram_timing_info *dram_timing)
-{
- return imx8m_ddr_init(dram_timing, DDRC_TYPE_MQ);
-}
-
-int imx8mp_ddr_init(struct dram_timing_info *dram_timing)
-{
- return imx8m_ddr_init(dram_timing, DDRC_TYPE_MP);
-}
diff --git a/drivers/ddr/imx8m/ddrphy_train.c b/drivers/ddr/imx8m/ddrphy_train.c
index 9dc20a4762..e9d35afdfb 100644
--- a/drivers/ddr/imx8m/ddrphy_train.c
+++ b/drivers/ddr/imx8m/ddrphy_train.c
@@ -11,6 +11,48 @@
#include <firmware.h>
#include <mach/imx8m-regs.h>
+static const u16 *lpddr4_imem_1d;
+static size_t lpddr4_imem_1d_size;
+static const u16 *lpddr4_dmem_1d;
+static size_t lpddr4_dmem_1d_size;
+static const u16 *lpddr4_imem_2d;
+static size_t lpddr4_imem_2d_size;
+static const u16 *lpddr4_dmem_2d;
+static size_t lpddr4_dmem_2d_size;
+
+void ddr_get_firmware_lpddr4(void)
+{
+ get_builtin_firmware(lpddr4_pmu_train_1d_imem_bin, &lpddr4_imem_1d,
+ &lpddr4_imem_1d_size);
+ get_builtin_firmware(lpddr4_pmu_train_1d_dmem_bin, &lpddr4_dmem_1d,
+ &lpddr4_dmem_1d_size);
+ get_builtin_firmware(lpddr4_pmu_train_2d_imem_bin, &lpddr4_imem_2d,
+ &lpddr4_imem_2d_size);
+ get_builtin_firmware(lpddr4_pmu_train_2d_dmem_bin, &lpddr4_dmem_2d,
+ &lpddr4_dmem_2d_size);
+}
+
+static const u16 *ddr4_imem_1d;
+static size_t ddr4_imem_1d_size;
+static const u16 *ddr4_dmem_1d;
+static size_t ddr4_dmem_1d_size;
+static const u16 *ddr4_imem_2d;
+static size_t ddr4_imem_2d_size;
+static const u16 *ddr4_dmem_2d;
+static size_t ddr4_dmem_2d_size;
+
+void ddr_get_firmware_ddr(void)
+{
+ get_builtin_firmware(ddr4_imem_1d_bin, &ddr4_imem_1d,
+ &ddr4_imem_1d_size);
+ get_builtin_firmware(ddr4_dmem_1d_bin, &ddr4_dmem_1d,
+ &ddr4_dmem_1d_size);
+ get_builtin_firmware(ddr4_imem_2d_bin, &ddr4_imem_2d,
+ &ddr4_imem_2d_size);
+ get_builtin_firmware(ddr4_dmem_2d_bin, &ddr4_dmem_2d,
+ &ddr4_dmem_2d_size);
+}
+
void ddr_load_train_code(enum dram_type dram_type, enum fw_type fw_type)
{
const u16 *imem, *dmem;
@@ -18,19 +60,27 @@ void ddr_load_train_code(enum dram_type dram_type, enum fw_type fw_type)
if (dram_is_lpddr4(dram_type)) {
if (fw_type == FW_1D_IMAGE) {
- get_builtin_firmware(lpddr4_pmu_train_1d_imem_bin, &imem, &isize);
- get_builtin_firmware(lpddr4_pmu_train_1d_dmem_bin, &dmem, &dsize);
+ imem = lpddr4_imem_1d;
+ isize = lpddr4_imem_1d_size;
+ dmem = lpddr4_dmem_1d;
+ dsize = lpddr4_dmem_1d_size;
} else {
- get_builtin_firmware(lpddr4_pmu_train_2d_imem_bin, &imem, &isize);
- get_builtin_firmware(lpddr4_pmu_train_2d_dmem_bin, &dmem, &dsize);
+ imem = lpddr4_imem_2d;
+ isize = lpddr4_imem_2d_size;
+ dmem = lpddr4_dmem_2d;
+ dsize = lpddr4_dmem_2d_size;
}
} else if (dram_is_ddr4(dram_type)) {
if (fw_type == FW_1D_IMAGE) {
- get_builtin_firmware(ddr4_imem_1d_bin, &imem, &isize);
- get_builtin_firmware(ddr4_dmem_1d_bin, &dmem, &dsize);
+ imem = ddr4_imem_1d;
+ isize = ddr4_imem_1d_size;
+ dmem = ddr4_dmem_1d;
+ dsize = ddr4_dmem_1d_size;
} else {
- get_builtin_firmware(ddr4_imem_2d_bin, &imem, &isize);
- get_builtin_firmware(ddr4_dmem_2d_bin, &dmem, &dsize);
+ imem = ddr4_imem_2d;
+ isize = ddr4_imem_2d_size;
+ dmem = ddr4_dmem_2d;
+ dsize = ddr4_dmem_2d_size;
}
} else {
panic("No matching DDR PHY firmware found");
@@ -43,8 +93,10 @@ void ddr_load_train_code(enum dram_type dram_type, enum fw_type fw_type)
DDRC_PHY_DMEM, dmem, dsize);
}
-int ddr_cfg_phy(struct dram_timing_info *dram_timing, enum ddrc_type type)
+int ddr_cfg_phy(struct dram_timing_info *dram_timing, unsigned type)
{
+ enum ddrc_type ddrc_type = get_ddrc_type(type);
+ enum dram_type dram_type = get_dram_type(type);
struct dram_cfg_param *dram_cfg;
struct dram_fsp_msg *fsp_msg;
unsigned int num;
@@ -66,11 +118,11 @@ int ddr_cfg_phy(struct dram_timing_info *dram_timing, enum ddrc_type type)
for (i = 0; i < dram_timing->fsp_msg_num; i++) {
pr_debug("DRAM PHY training for %dMTS\n", fsp_msg->drate);
/* set dram PHY input clocks to desired frequency */
- ddrphy_init_set_dfi_clk(fsp_msg->drate, type);
+ ddrphy_init_set_dfi_clk(fsp_msg->drate, ddrc_type);
/* load the dram training firmware image */
dwc_ddrphy_apb_wr(0xd0000, 0x0);
- ddr_load_train_code(dram_timing->dram_type, fsp_msg->fw_type);
+ ddr_load_train_code(dram_type, fsp_msg->fw_type);
/* load the frequency set point message block parameter */
dram_cfg = fsp_msg->fsp_cfg;
diff --git a/drivers/efi/efi-device.c b/drivers/efi/efi-device.c
index f91d09e8ea..af5406afa6 100644
--- a/drivers/efi/efi-device.c
+++ b/drivers/efi/efi-device.c
@@ -426,8 +426,7 @@ static void efi_set_bootsource(void)
out:
- bootsource_set(src);
- bootsource_set_instance(instance);
+ bootsource_set_raw(src, instance);
}
static int efi_init_devices(void)
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index ef3d76b3f4..fc02a53a2b 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -1247,11 +1247,12 @@ static const struct of_device_id scmi_of_match[] = {
{ /* Sentinel */ },
};
-static struct driver_d scmi_driver = {
+static struct driver_d arm_scmi_driver = {
.name = "arm-scmi",
.of_compatible = scmi_of_match,
.probe = scmi_probe,
};
+core_platform_driver(arm_scmi_driver);
static int __init scmi_bus_driver_init(void)
{
@@ -1267,12 +1268,6 @@ static int __init scmi_bus_driver_init(void)
}
pure_initcall(scmi_bus_driver_init);
-static int __init scmi_platform_driver_init(void)
-{
- return platform_driver_register(&scmi_driver);
-}
-core_initcall(scmi_platform_driver_init);
-
MODULE_ALIAS("platform: arm-scmi");
MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
MODULE_DESCRIPTION("ARM SCMI protocol driver");
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index fefd20de6f..612ef3a82e 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -219,11 +219,7 @@ static int pcf857x_probe(struct device_d *dev)
*/
gpio->out = ~n_latch;
- ret = gpiochip_add(&gpio->chip);
- if (ret)
- return ret;
-
- return ret;
+ return gpiochip_add(&gpio->chip);
}
static const struct of_device_id pcf857x_dt_ids[] = {
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index f845a57394..97a99b84e3 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -444,44 +444,27 @@ static int of_hog_gpio(struct device_node *np, struct gpio_chip *chip,
unsigned int idx)
{
struct device_node *chip_np = chip->dev->device_node;
+ struct of_phandle_args gpiospec;
unsigned long flags = 0;
- u32 gpio_cells, gpio_num, gpio_flags;
+ u32 gpio_flags;
int ret, gpio;
const char *name = NULL;
- ret = of_property_read_u32(chip_np, "#gpio-cells", &gpio_cells);
+ ret = of_parse_phandle_with_args(chip_np, "gpios", "#gpio-cells", idx,
+ &gpiospec);
if (ret)
return ret;
- /*
- * Support for GPIOs that don't have #gpio-cells set to 2 is
- * not implemented
- */
- if (WARN_ON(gpio_cells != 2))
- return -ENOTSUPP;
-
- ret = of_property_read_u32_index(np, "gpios", idx * gpio_cells,
- &gpio_num);
- if (ret)
- return ret;
-
- ret = of_property_read_u32_index(np, "gpios", idx * gpio_cells + 1,
- &gpio_flags);
- if (ret)
- return ret;
-
- if (gpio_flags & OF_GPIO_ACTIVE_LOW)
- flags |= GPIOF_ACTIVE_LOW;
-
- gpio = gpio_get_num(chip->dev, gpio_num);
+ gpio = gpio_of_xlate(chip->dev, &gpiospec, &gpio_flags);
if (gpio == -EPROBE_DEFER)
return gpio;
-
if (gpio < 0) {
- dev_err(chip->dev, "unable to get gpio %u\n", gpio_num);
+ dev_err(chip->dev, "unable to get gpio: %d\n", gpio);
return gpio;
}
+ if (gpio_flags & OF_GPIO_ACTIVE_LOW)
+ flags |= GPIOF_ACTIVE_LOW;
/*
* Note that, in order to be compatible with Linux, the code
@@ -636,7 +619,24 @@ void gpiochip_remove(struct gpio_chip *chip)
list_del(&chip->list);
}
-int gpio_get_num(struct device_d *dev, int gpio)
+static int of_gpio_simple_xlate(struct gpio_chip *chip,
+ const struct of_phandle_args *gpiospec,
+ u32 *flags)
+{
+ /*
+ * Support for GPIOs that don't have #gpio-cells set to 2 is
+ * not implemented
+ */
+ if (WARN_ON(gpiospec->args_count != 2))
+ return -ENOTSUPP;
+
+ if (flags)
+ *flags = gpiospec->args[1];
+
+ return chip->base + gpiospec->args[0];
+}
+
+int gpio_of_xlate(struct device_d *dev, struct of_phandle_args *gpiospec, int *flags)
{
struct gpio_chip *chip;
@@ -644,8 +644,12 @@ int gpio_get_num(struct device_d *dev, int gpio)
return -ENODEV;
list_for_each_entry(chip, &chip_list, list) {
- if (chip->dev == dev)
- return chip->base + gpio;
+ if (chip->dev != dev)
+ continue;
+ if (chip->ops->of_xlate)
+ return chip->ops->of_xlate(chip, gpiospec, flags);
+ else
+ return of_gpio_simple_xlate(chip, gpiospec, flags);
}
return -EPROBE_DEFER;
diff --git a/drivers/i2c/busses/i2c-bcm283x.c b/drivers/i2c/busses/i2c-bcm283x.c
index 097f73d983..fdba3b91bd 100644
--- a/drivers/i2c/busses/i2c-bcm283x.c
+++ b/drivers/i2c/busses/i2c-bcm283x.c
@@ -147,7 +147,7 @@ static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c,
if (ret) {
dev_err(dev, "timeout: 10bit read initilization\n");
- return ret;
+ goto out;
}
if (reg_s & BSC_S_ERR)
goto nack;
@@ -178,7 +178,7 @@ static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c,
if (ret) {
dev_err(dev, "timeout: waiting for data in FIFO\n");
- return ret;
+ goto out;
}
if (reg_s & BSC_S_ERR)
goto nack;
@@ -197,7 +197,7 @@ static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c,
if (ret) {
dev_err(dev, "timeout: waiting for space in FIFO\n");
- return ret;
+ goto out;
}
if (reg_s & BSC_S_ERR)
goto nack;
@@ -216,16 +216,23 @@ static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c,
if (ret) {
dev_err(dev, "timeout: waiting for transfer to end\n");
- return ret;
+ goto out;
}
if (reg_s & BSC_S_ERR)
goto nack;
- writel(BSC_S_DONE | BSC_S_ERR | BSC_S_CLKT, &bcm_i2c->regs->s);
- writel(BSC_C_CLEAR1 | BSC_C_I2CEN, &bcm_i2c->regs->c);
- return 0;
+ goto out;
nack:
dev_dbg(dev, "device with addr %x didn't ACK\n", msg->addr);
- return -EREMOTEIO;
+ writel(BSC_S_ERR, &bcm_i2c->regs->s);
+ timeout = calc_byte_timeout_us(bcm_i2c->bitrate);
+ // Wait for end of transfer so BSC has time to send STOP condition
+ readl_poll_timeout(&bcm_i2c->regs->s, reg_s, ~reg_s & BSC_S_TA, timeout);
+ ret = -EREMOTEIO;
+out:
+ // Return to default state for next xfer
+ writel(BSC_S_DONE | BSC_S_ERR | BSC_S_CLKT, &bcm_i2c->regs->s);
+ writel(BSC_C_CLEAR1 | BSC_C_I2CEN, &bcm_i2c->regs->c);
+ return ret;
}
static int bcm283x_i2c_xfer(struct i2c_adapter *adapter,
diff --git a/drivers/i2c/busses/i2c-imx-early.c b/drivers/i2c/busses/i2c-imx-early.c
index a79d7bd88c..4e0f7e517d 100644
--- a/drivers/i2c/busses/i2c-imx-early.c
+++ b/drivers/i2c/busses/i2c-imx-early.c
@@ -9,11 +9,12 @@
*/
#include <common.h>
#include <i2c/i2c.h>
-#include <i2c/i2c-early.h>
+#include <pbl/i2c.h>
#include "i2c-imx.h"
struct fsl_i2c {
+ struct pbl_i2c i2c;
void __iomem *regs;
unsigned int i2cr_ien_opcode;
unsigned int i2sr_clr_opcode;
@@ -170,7 +171,7 @@ static int i2c_fsl_write(struct fsl_i2c *fsl_i2c, struct i2c_msg *msg)
/* write data */
for (i = 0; i < msg->len; i++) {
ret = i2c_fsl_send(fsl_i2c, msg->buf[i]);
- if (ret)
+ if (ret)
return ret;
}
@@ -229,9 +230,9 @@ static int i2c_fsl_read(struct fsl_i2c *fsl_i2c, struct i2c_msg *msg)
* If successful returns the number of messages transferred, otherwise a negative
* error code is returned.
*/
-int i2c_fsl_xfer(void *ctx, struct i2c_msg *msgs, int num)
+static int i2c_fsl_xfer(struct pbl_i2c *i2c, struct i2c_msg *msgs, int num)
{
- struct fsl_i2c *fsl_i2c = ctx;
+ struct fsl_i2c *fsl_i2c = container_of(i2c, struct fsl_i2c, i2c);
unsigned int i, temp;
int ret;
@@ -288,7 +289,7 @@ static struct fsl_i2c fsl_i2c;
* This function returns a context pointer suitable to transfer I2C messages
* using i2c_fsl_xfer.
*/
-void *ls1046_i2c_init(void __iomem *regs)
+struct pbl_i2c *ls1046_i2c_init(void __iomem *regs)
{
fsl_i2c.regs = regs;
fsl_i2c.regshift = 0;
@@ -297,10 +298,12 @@ void *ls1046_i2c_init(void __iomem *regs)
/* Divider for ~100kHz when coming from the ROM */
fsl_i2c.ifdr = 0x3e;
- return &fsl_i2c;
+ fsl_i2c.i2c.xfer = i2c_fsl_xfer;
+
+ return &fsl_i2c.i2c;
}
-void *imx8m_i2c_early_init(void __iomem *regs)
+struct pbl_i2c *imx8m_i2c_early_init(void __iomem *regs)
{
fsl_i2c.regs = regs;
fsl_i2c.regshift = 2;
@@ -309,5 +312,7 @@ void *imx8m_i2c_early_init(void __iomem *regs)
/* Divider for ~100kHz when coming from the ROM */
fsl_i2c.ifdr = 0x0f;
- return &fsl_i2c;
+ fsl_i2c.i2c.xfer = i2c_fsl_xfer;
+
+ return &fsl_i2c.i2c;
}
diff --git a/drivers/led/led-pca955x.c b/drivers/led/led-pca955x.c
index 848feb9773..aa518fe738 100644
--- a/drivers/led/led-pca955x.c
+++ b/drivers/led/led-pca955x.c
@@ -387,11 +387,10 @@ static int led_pca955x_probe(struct device_d *dev)
err = pca955x_write_psc(client, 0, 0);
if (err)
return err;
+
err = pca955x_write_psc(client, 1, 0);
- if (err)
- return err;
- return 0;
+ return err;
}
static struct driver_d led_pca955x_driver = {
diff --git a/drivers/mci/atmel-sdhci-pbl.c b/drivers/mci/atmel-sdhci-pbl.c
index 626e4008fe..2c5f107abd 100644
--- a/drivers/mci/atmel-sdhci-pbl.c
+++ b/drivers/mci/atmel-sdhci-pbl.c
@@ -8,7 +8,7 @@
*/
#include <common.h>
-#include <pbl.h>
+#include <pbl/bio.h>
#include <mci.h>
#include <debug_ll.h>
#include <mach/xload.h>
diff --git a/drivers/mci/atmel_mci_pbl.c b/drivers/mci/atmel_mci_pbl.c
index 767d6f3ce2..65d8b3632a 100644
--- a/drivers/mci/atmel_mci_pbl.c
+++ b/drivers/mci/atmel_mci_pbl.c
@@ -114,3 +114,8 @@ int at91_mci_bio_init(struct pbl_bio *bio, void __iomem *base,
return 0;
}
+
+void at91_mci_bio_set_highcapacity(bool highcapacity_card)
+{
+ atmci_sdcard.highcapacity_card = highcapacity_card;
+}
diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
index 5a76e7a663..c81eba5b9d 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -44,7 +44,7 @@ static int esdhc_send_ext_csd(struct fsl_esdhc_host *host)
return esdhc_send_cmd(host, &cmd, &data);
}
-static bool esdhc_bootpart_active(struct fsl_esdhc_host *host)
+static bool __maybe_unused esdhc_bootpart_active(struct fsl_esdhc_host *host)
{
unsigned bootpart;
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index b8f71e1598..8c08a4f61f 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -1941,6 +1941,16 @@ int mci_register(struct mci_host *host)
host->supply = regulator_get(hw_dev, "vmmc");
if (IS_ERR(host->supply)) {
+ /*
+ * If you know your regulator to be always online on boot, but
+ * can't easily add a barebox driver for it, you may use
+ * barebox,allow-dummy-supply in your board's regulator device
+ * tree node to side step this warning.
+ *
+ * If you run into this warning, because your regulator driver
+ * hasn't probed the device yet, consider enabling deep probe
+ * for your board, to probe dependencies on demand.
+ */
dev_warn(hw_dev, "Failed to get 'vmmc' regulator (ignored).\n");
host->supply = NULL;
}
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 9d4a82a9bb..6c6b65dacf 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -108,4 +108,13 @@ config MFD_ATMEL_FLEXCOM
by the probe function of this MFD driver according to a device tree
property.
+config MFD_RK808
+ tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power Management Chip"
+ depends on I2C && OFDEVICE
+ help
+ If you say yes here you get support for the RK805, RK808, RK809,
+ RK817 and RK818 Power Management chips.
+ This driver provides common support for accessing the device
+ through I2C interface.
+
endmenu
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 50f54cfcf2..7b5d0398d1 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -1,4 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
+obj-y += core.o
+
obj-$(CONFIG_MFD_ACT8846) += act8846.o
obj-$(CONFIG_MFD_DA9053) += da9053.o
obj-$(CONFIG_MFD_DA9063) += da9063.o
@@ -19,3 +21,4 @@ obj-$(CONFIG_FINTEK_SUPERIO) += fintek-superio.o
obj-$(CONFIG_SMSC_SUPERIO) += smsc-superio.o
obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o
obj-$(CONFIG_MFD_ATMEL_FLEXCOM) += atmel-flexcom.o
+obj-$(CONFIG_MFD_RK808) += rk808.o
diff --git a/drivers/mfd/core.c b/drivers/mfd/core.c
new file mode 100644
index 0000000000..495427ae9c
--- /dev/null
+++ b/drivers/mfd/core.c
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <linux/mfd/core.h>
+#include <driver.h>
+
+int mfd_add_devices(struct device_d *parent, const struct mfd_cell *cells, int n_devs)
+{
+ struct device_d *dev;
+ int ret, i;
+
+ for (i = 0; i < n_devs; i++) {
+ dev = device_alloc(cells[i].name, DEVICE_ID_DYNAMIC);
+ dev->parent = parent;
+
+ ret = device_add_data(dev, &cells[i], sizeof(cells[i]));
+ if (ret)
+ return ret;
+
+ ret = platform_device_register(dev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c
new file mode 100644
index 0000000000..1b5b9d3a17
--- /dev/null
+++ b/drivers/mfd/rk808.c
@@ -0,0 +1,395 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * MFD core driver for Rockchip RK808/RK818
+ *
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * Author: Chris Zhong <zyw@rock-chips.com>
+ * Author: Zhang Qing <zhangqing@rock-chips.com>
+ *
+ * Copyright (C) 2016 PHYTEC Messtechnik GmbH
+ *
+ * Author: Wadim Egorov <w.egorov@phytec.de>
+ */
+
+#define pr_fmt(fmt) "rk808: " fmt
+
+#include <common.h>
+#include <i2c/i2c.h>
+#include <linux/mfd/rk808.h>
+#include <linux/mfd/core.h>
+#include <driver.h>
+#include <poweroff.h>
+#include <of.h>
+#include <regmap.h>
+
+struct rk808_reg_data {
+ int addr;
+ int mask;
+ int value;
+};
+
+static const struct regmap_config rk818_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = RK818_USB_CTRL_REG,
+};
+
+static const struct regmap_config rk805_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = RK805_OFF_SOURCE_REG,
+};
+
+static const struct regmap_config rk808_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = RK808_IO_POL_REG,
+};
+
+static const struct regmap_config rk817_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = RK817_GPIO_INT_CFG,
+};
+
+static const struct mfd_cell rk805s[] = {
+ { .name = "rk808-clkout", },
+ { .name = "rk808-regulator", },
+ { .name = "rk805-pinctrl", },
+ { .name = "rk808-rtc", },
+ { .name = "rk805-pwrkey", },
+};
+
+static const struct mfd_cell rk808s[] = {
+ { .name = "rk808-clkout", },
+ { .name = "rk808-regulator", },
+ { .name = "rk808-rtc", },
+};
+
+static const struct mfd_cell rk817s[] = {
+ { .name = "rk808-clkout", },
+ { .name = "rk808-regulator", },
+ { .name = "rk805-pwrkey", },
+ { .name = "rk808-rtc", },
+ { .name = "rk817-codec", },
+};
+
+static const struct mfd_cell rk818s[] = {
+ { .name = "rk808-clkout", },
+ { .name = "rk808-regulator", },
+ { .name = "rk808-rtc", },
+};
+
+static const struct rk808_reg_data rk805_pre_init_reg[] = {
+ {RK805_BUCK1_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK,
+ RK805_BUCK1_2_ILMAX_4000MA},
+ {RK805_BUCK2_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK,
+ RK805_BUCK1_2_ILMAX_4000MA},
+ {RK805_BUCK3_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK,
+ RK805_BUCK3_ILMAX_3000MA},
+ {RK805_BUCK4_CONFIG_REG, RK805_BUCK3_4_ILMAX_MASK,
+ RK805_BUCK4_ILMAX_3500MA},
+ {RK805_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_400MA},
+ {RK805_THERMAL_REG, TEMP_HOTDIE_MSK, TEMP115C},
+};
+
+static const struct rk808_reg_data rk808_pre_init_reg[] = {
+ { RK808_BUCK3_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_150MA },
+ { RK808_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_200MA },
+ { RK808_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA },
+ { RK808_BUCK1_CONFIG_REG, BUCK1_RATE_MASK, BUCK_ILMIN_200MA },
+ { RK808_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_200MA },
+ { RK808_DCDC_UV_ACT_REG, BUCK_UV_ACT_MASK, BUCK_UV_ACT_DISABLE},
+ { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT |
+ VB_LO_SEL_3500MV },
+};
+
+static const struct rk808_reg_data rk817_pre_init_reg[] = {
+ {RK817_RTC_CTRL_REG, RTC_STOP, RTC_STOP},
+ /* Codec specific registers */
+ { RK817_CODEC_DTOP_VUCTL, MASK_ALL, 0x03 },
+ { RK817_CODEC_DTOP_VUCTIME, MASK_ALL, 0x00 },
+ { RK817_CODEC_DTOP_LPT_SRST, MASK_ALL, 0x00 },
+ { RK817_CODEC_DTOP_DIGEN_CLKE, MASK_ALL, 0x00 },
+ /* from vendor driver, CODEC_AREF_RTCFG0 not defined in data sheet */
+ { RK817_CODEC_AREF_RTCFG0, MASK_ALL, 0x00 },
+ { RK817_CODEC_AREF_RTCFG1, MASK_ALL, 0x06 },
+ { RK817_CODEC_AADC_CFG0, MASK_ALL, 0xc8 },
+ /* from vendor driver, CODEC_AADC_CFG1 not defined in data sheet */
+ { RK817_CODEC_AADC_CFG1, MASK_ALL, 0x00 },
+ { RK817_CODEC_DADC_VOLL, MASK_ALL, 0x00 },
+ { RK817_CODEC_DADC_VOLR, MASK_ALL, 0x00 },
+ { RK817_CODEC_DADC_SR_ACL0, MASK_ALL, 0x00 },
+ { RK817_CODEC_DADC_ALC1, MASK_ALL, 0x00 },
+ { RK817_CODEC_DADC_ALC2, MASK_ALL, 0x00 },
+ { RK817_CODEC_DADC_NG, MASK_ALL, 0x00 },
+ { RK817_CODEC_DADC_HPF, MASK_ALL, 0x00 },
+ { RK817_CODEC_DADC_RVOLL, MASK_ALL, 0xff },
+ { RK817_CODEC_DADC_RVOLR, MASK_ALL, 0xff },
+ { RK817_CODEC_AMIC_CFG0, MASK_ALL, 0x70 },
+ { RK817_CODEC_AMIC_CFG1, MASK_ALL, 0x00 },
+ { RK817_CODEC_DMIC_PGA_GAIN, MASK_ALL, 0x66 },
+ { RK817_CODEC_DMIC_LMT1, MASK_ALL, 0x00 },
+ { RK817_CODEC_DMIC_LMT2, MASK_ALL, 0x00 },
+ { RK817_CODEC_DMIC_NG1, MASK_ALL, 0x00 },
+ { RK817_CODEC_DMIC_NG2, MASK_ALL, 0x00 },
+ /* from vendor driver, CODEC_ADAC_CFG0 not defined in data sheet */
+ { RK817_CODEC_ADAC_CFG0, MASK_ALL, 0x00 },
+ { RK817_CODEC_ADAC_CFG1, MASK_ALL, 0x07 },
+ { RK817_CODEC_DDAC_POPD_DACST, MASK_ALL, 0x82 },
+ { RK817_CODEC_DDAC_VOLL, MASK_ALL, 0x00 },
+ { RK817_CODEC_DDAC_VOLR, MASK_ALL, 0x00 },
+ { RK817_CODEC_DDAC_SR_LMT0, MASK_ALL, 0x00 },
+ { RK817_CODEC_DDAC_LMT1, MASK_ALL, 0x00 },
+ { RK817_CODEC_DDAC_LMT2, MASK_ALL, 0x00 },
+ { RK817_CODEC_DDAC_MUTE_MIXCTL, MASK_ALL, 0xa0 },
+ { RK817_CODEC_DDAC_RVOLL, MASK_ALL, 0xff },
+ { RK817_CODEC_DADC_RVOLR, MASK_ALL, 0xff },
+ { RK817_CODEC_AMIC_CFG0, MASK_ALL, 0x70 },
+ { RK817_CODEC_AMIC_CFG1, MASK_ALL, 0x00 },
+ { RK817_CODEC_DMIC_PGA_GAIN, MASK_ALL, 0x66 },
+ { RK817_CODEC_DMIC_LMT1, MASK_ALL, 0x00 },
+ { RK817_CODEC_DMIC_LMT2, MASK_ALL, 0x00 },
+ { RK817_CODEC_DMIC_NG1, MASK_ALL, 0x00 },
+ { RK817_CODEC_DMIC_NG2, MASK_ALL, 0x00 },
+ /* from vendor driver, CODEC_ADAC_CFG0 not defined in data sheet */
+ { RK817_CODEC_ADAC_CFG0, MASK_ALL, 0x00 },
+ { RK817_CODEC_ADAC_CFG1, MASK_ALL, 0x07 },
+ { RK817_CODEC_DDAC_POPD_DACST, MASK_ALL, 0x82 },
+ { RK817_CODEC_DDAC_VOLL, MASK_ALL, 0x00 },
+ { RK817_CODEC_DDAC_VOLR, MASK_ALL, 0x00 },
+ { RK817_CODEC_DDAC_SR_LMT0, MASK_ALL, 0x00 },
+ { RK817_CODEC_DDAC_LMT1, MASK_ALL, 0x00 },
+ { RK817_CODEC_DDAC_LMT2, MASK_ALL, 0x00 },
+ { RK817_CODEC_DDAC_MUTE_MIXCTL, MASK_ALL, 0xa0 },
+ { RK817_CODEC_DDAC_RVOLL, MASK_ALL, 0xff },
+ { RK817_CODEC_DDAC_RVOLR, MASK_ALL, 0xff },
+ { RK817_CODEC_AHP_ANTI0, MASK_ALL, 0x00 },
+ { RK817_CODEC_AHP_ANTI1, MASK_ALL, 0x00 },
+ { RK817_CODEC_AHP_CFG0, MASK_ALL, 0xe0 },
+ { RK817_CODEC_AHP_CFG1, MASK_ALL, 0x1f },
+ { RK817_CODEC_AHP_CP, MASK_ALL, 0x09 },
+ { RK817_CODEC_ACLASSD_CFG1, MASK_ALL, 0x69 },
+ { RK817_CODEC_ACLASSD_CFG2, MASK_ALL, 0x44 },
+ { RK817_CODEC_APLL_CFG0, MASK_ALL, 0x04 },
+ { RK817_CODEC_APLL_CFG1, MASK_ALL, 0x00 },
+ { RK817_CODEC_APLL_CFG2, MASK_ALL, 0x30 },
+ { RK817_CODEC_APLL_CFG3, MASK_ALL, 0x19 },
+ { RK817_CODEC_APLL_CFG4, MASK_ALL, 0x65 },
+ { RK817_CODEC_APLL_CFG5, MASK_ALL, 0x01 },
+ { RK817_CODEC_DI2S_CKM, MASK_ALL, 0x01 },
+ { RK817_CODEC_DI2S_RSD, MASK_ALL, 0x00 },
+ { RK817_CODEC_DI2S_RXCR1, MASK_ALL, 0x00 },
+ { RK817_CODEC_DI2S_RXCR2, MASK_ALL, 0x17 },
+ { RK817_CODEC_DI2S_RXCMD_TSD, MASK_ALL, 0x00 },
+ { RK817_CODEC_DI2S_TXCR1, MASK_ALL, 0x00 },
+ { RK817_CODEC_DI2S_TXCR2, MASK_ALL, 0x17 },
+ { RK817_CODEC_DI2S_TXCR3_TXCMD, MASK_ALL, 0x00 },
+ {RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_L},
+ {RK817_SYS_CFG(1), RK817_HOTDIE_TEMP_MSK | RK817_TSD_TEMP_MSK,
+ RK817_HOTDIE_105 | RK817_TSD_140},
+};
+
+static const struct rk808_reg_data rk818_pre_init_reg[] = {
+ /* improve efficiency */
+ { RK818_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_250MA },
+ { RK818_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_250MA },
+ { RK818_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA },
+ { RK818_USB_CTRL_REG, RK818_USB_ILIM_SEL_MASK,
+ RK818_USB_ILMIN_2000MA },
+ /* close charger when usb lower then 3.4V */
+ { RK818_USB_CTRL_REG, RK818_USB_CHG_SD_VSEL_MASK,
+ (0x7 << 4) },
+ /* no action when vref */
+ { RK818_H5V_EN_REG, BIT(1), RK818_REF_RDY_CTRL },
+ /* enable HDMI 5V */
+ { RK818_H5V_EN_REG, BIT(0), RK818_H5V_EN },
+ { RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT |
+ VB_LO_SEL_3500MV },
+};
+
+static void rk808_poweroff(struct poweroff_handler *handler)
+{
+ struct rk808 *rk808 = container_of(handler, struct rk808, poweroff);
+ int ret;
+ unsigned int reg, bit;
+
+ switch (rk808->variant) {
+ case RK805_ID:
+ reg = RK805_DEV_CTRL_REG;
+ bit = DEV_OFF;
+ break;
+ case RK808_ID:
+ reg = RK808_DEVCTRL_REG,
+ bit = DEV_OFF_RST;
+ break;
+ case RK817_ID:
+ reg = RK817_SYS_CFG(3);
+ bit = DEV_OFF;
+ break;
+ case RK818_ID:
+ reg = RK818_DEVCTRL_REG;
+ bit = DEV_OFF;
+ break;
+ default:
+ return;
+ }
+
+ shutdown_barebox();
+
+ ret = regmap_update_bits(rk808->regmap, reg, bit, bit);
+ if (ret)
+ pr_err("Failed to shutdown device!\n");
+
+ mdelay(1000);
+ hang();
+}
+
+static int rk808_probe(struct device_d *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct device_node *np = dev->device_node;
+ struct rk808 *rk808;
+ const struct rk808_reg_data *pre_init_reg;
+ const struct mfd_cell *cells;
+ int nr_pre_init_regs;
+ int nr_cells;
+ int msb, lsb;
+ unsigned char pmic_id_msb, pmic_id_lsb;
+ int ret;
+ int i;
+
+ rk808 = kzalloc(sizeof(*rk808), GFP_KERNEL);
+ if (!rk808)
+ return -ENOMEM;
+
+ dev->priv = rk808;
+
+ if (of_device_is_compatible(np, "rockchip,rk817") ||
+ of_device_is_compatible(np, "rockchip,rk809")) {
+ pmic_id_msb = RK817_ID_MSB;
+ pmic_id_lsb = RK817_ID_LSB;
+ } else {
+ pmic_id_msb = RK808_ID_MSB;
+ pmic_id_lsb = RK808_ID_LSB;
+ }
+
+ /* Read chip variant */
+ msb = i2c_smbus_read_byte_data(client, pmic_id_msb);
+ if (msb < 0) {
+ dev_err(dev, "failed to read the chip id at 0x%x\n",
+ RK808_ID_MSB);
+ return msb;
+ }
+
+ lsb = i2c_smbus_read_byte_data(client, pmic_id_lsb);
+ if (lsb < 0) {
+ dev_err(dev, "failed to read the chip id at 0x%x\n",
+ RK808_ID_LSB);
+ return lsb;
+ }
+
+ rk808->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
+ dev_info(dev, "chip id: 0x%x\n", (unsigned int)rk808->variant);
+
+ switch (rk808->variant) {
+ case RK805_ID:
+ rk808->regmap_cfg = &rk805_regmap_config;
+ pre_init_reg = rk805_pre_init_reg;
+ nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg);
+ cells = rk805s;
+ nr_cells = ARRAY_SIZE(rk805s);
+ break;
+ case RK808_ID:
+ rk808->regmap_cfg = &rk808_regmap_config;
+ pre_init_reg = rk808_pre_init_reg;
+ nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg);
+ cells = rk808s;
+ nr_cells = ARRAY_SIZE(rk808s);
+ break;
+ case RK818_ID:
+ rk808->regmap_cfg = &rk818_regmap_config;
+ pre_init_reg = rk818_pre_init_reg;
+ nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg);
+ cells = rk818s;
+ nr_cells = ARRAY_SIZE(rk818s);
+ break;
+ case RK809_ID:
+ case RK817_ID:
+ rk808->regmap_cfg = &rk817_regmap_config;
+ pre_init_reg = rk817_pre_init_reg;
+ nr_pre_init_regs = ARRAY_SIZE(rk817_pre_init_reg);
+ cells = rk817s;
+ nr_cells = ARRAY_SIZE(rk817s);
+ break;
+ default:
+ dev_err(dev, "Unsupported RK8XX ID %lu\n",
+ rk808->variant);
+ return -EINVAL;
+ }
+
+ rk808->i2c = client;
+ i2c_set_clientdata(client, rk808);
+
+ rk808->regmap = regmap_init_i2c_smbus(client, rk808->regmap_cfg);
+ if (IS_ERR(rk808->regmap)) {
+ dev_err(dev, "regmap initialization failed\n");
+ return PTR_ERR(rk808->regmap);
+ }
+
+ ret = regmap_register_cdev(rk808->regmap, NULL);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < nr_pre_init_regs; i++) {
+ ret = regmap_update_bits(rk808->regmap,
+ pre_init_reg[i].addr,
+ pre_init_reg[i].mask,
+ pre_init_reg[i].value);
+ if (ret) {
+ dev_err(dev,
+ "0x%x write err\n",
+ pre_init_reg[i].addr);
+ return ret;
+ }
+ }
+
+ ret = mfd_add_devices(dev, cells, nr_cells);
+ if (ret) {
+ dev_err(dev, "failed to add MFD devices %d\n", ret);
+ return ret;
+ }
+
+ rk808->poweroff.name = "stpmic1-poweroff";
+ rk808->poweroff.poweroff = rk808_poweroff;
+ rk808->poweroff.priority = 200;
+
+ if (of_property_read_bool(np, "rockchip,system-power-controller"))
+ rk808->poweroff.priority += 100;
+
+ poweroff_handler_register(&rk808->poweroff);
+ return 0;
+}
+
+static const struct of_device_id rk808_of_match[] = {
+ { .compatible = "rockchip,rk805" },
+ { .compatible = "rockchip,rk808" },
+ { .compatible = "rockchip,rk809" },
+ { .compatible = "rockchip,rk817" },
+ { .compatible = "rockchip,rk818" },
+ { },
+};
+
+static struct driver_d rk808_i2c_driver = {
+ .name = "rk808",
+ .of_compatible = rk808_of_match,
+ .probe = rk808_probe,
+};
+coredevice_i2c_driver(rk808_i2c_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
+MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
+MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
+MODULE_DESCRIPTION("RK808/RK818 PMIC driver");
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 803444cc44..341d02a1da 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -55,71 +55,75 @@ config DRIVER_NET_DAVINCI_EMAC
select PHYLIB
config DRIVER_NET_DESIGNWARE
- bool "Designware Universal MAC1000 ethernet platform support"
+ bool "Designware DWMAC1000 Ethernet driver support" if COMPILE_TEST
depends on HAS_DMA
select PHYLIB
help
- This option enables support for the Synopsys
- Designware Core Univesal MAC 10M/100M/1G ethernet IP.
-
-if DRIVER_NET_DESIGNWARE
+ This option is selected by platform glue drivers that contain
+ a DWMAC1000-compatible Ethernet IP.
config DRIVER_NET_DESIGNWARE_GENERIC
- bool "Designware Universal MAC ethernet generic driver"
+ bool "Generic Synopsis Designware Ethernet driver"
+ select DRIVER_NET_DESIGNWARE
+ depends on HAS_DMA
help
- This option enables support for the Synopsys
- Designware Core Univesal MAC 10M/100M/1G ethernet IP on SoCFPGA.
+ This option enables support for the generic Synopsys
+ Designware Core Universal MAC 10M/100M/1G binding. Supported
+ are 3.70a and 3.72. Most integrations additionally require
+ access to platform-specific registers, e.g. for clocking.
+ If you are on such a platform, use the platform specific
+ driver instead.
config DRIVER_NET_DESIGNWARE_SOCFPGA
- bool "Designware Universal MAC ethernet driver for SoCFPGA platforms"
- depends on ARCH_SOCFPGA || COMPILE_TEST
+ bool "SOCFPGA Designware Ethernet driver"
+ depends on HAS_DMA && (ARCH_SOCFPGA || COMPILE_TEST)
+ select DRIVER_NET_DESIGNWARE
select MFD_SYSCON
select RESET_CONTROLLER
help
This option enables support for the Synopsys
- Designware Core Univesal MAC 10M/100M/1G ethernet IP on SoCFPGA.
+ Designware Core Universal MAC 10M/100M/1G Ethernet IP on SoCFPGA.
config DRIVER_NET_DESIGNWARE_STARFIVE
- bool "Designware Universal MAC ethernet driver for StarFive platforms"
- depends on SOC_STARFIVE || COMPILE_TEST
+ bool "StarFive Designware Ethernet driver"
+ depends on HAS_DMA && (SOC_STARFIVE || COMPILE_TEST)
+ select DRIVER_NET_DESIGNWARE
select MFD_SYSCON
help
This option enables support for the Synopsys
- Designware Core Univesal MAC 10M/100M/1G ethernet IP on StarFive.
-
-endif
+ Designware Core Universal MAC 10M/100M/1G Ethernet IP on StarFive.
config DRIVER_NET_DESIGNWARE_EQOS
- bool "Designware Designware Ethernet QoS support"
- depends on HAS_DMA
- depends on COMMON_CLK
- depends on OFTREE
+ bool "Designware EQOS (GMAC4) Ethernet driver support" if COMPILE_TEST
+ depends on HAS_DMA && OFTREE
select PHYLIB
help
This option enables support for the Synopsys
Designware Ethernet Quality-of-Service (GMAC4).
-if DRIVER_NET_DESIGNWARE_EQOS
-
config DRIVER_NET_DESIGNWARE_STM32
- bool "Designware EQOS STM32 driver"
+ bool "STM32 Designware Ethernet driver"
+ depends on HAS_DMA && COMMON_CLK && OFTREE && (ARCH_STM32MP || COMPILE_TEST)
+ select DRIVER_NET_DESIGNWARE_EQOS
select MFD_SYSCON
help
- This option enables support for the ethernet MAC on the STM32MP platforms.
+ This option enables support for the Ethernet MAC on the STM32MP platforms.
config DRIVER_NET_DESIGNWARE_TEGRA186
- bool "Designware Universal MAC ethernet driver for Tegra 186 platforms"
+ bool "Tegra 186/194 Designware Ethernet driver"
+ depends on HAS_DMA && COMMON_CLK && OFTREE && (ARCH_TEGRA || COMPILE_TEST)
+ select DRIVER_NET_DESIGNWARE_EQOS
select RESET_CONTROLLER
help
- This option enables support for the ethernet MAC on the Tegra186 & 194.
+ This option enables support for the Ethernet MAC on the Tegra186 & 194.
config DRIVER_NET_DESIGNWARE_ROCKCHIP
- bool "Designware Universal MAC ethernet driver for Rockchip platforms"
+ bool "Rockchip Designware Ethernet driver"
+ select DRIVER_NET_DESIGNWARE_EQOS
+ depends on HAS_DMA && COMMON_CLK && OFTREE && (ARCH_ROCKCHIP || COMPILE_TEST)
select MFD_SYSCON
help
- This option enables support for the ethernet MAC on different Rockchip SoCs
-
-endif
+ This option enables support for the Ethernet MAC on different Rockchip SoCs
config DRIVER_NET_DM9K
bool "Davicom dm9k[E|A|B] ethernet driver"
diff --git a/drivers/net/designware_eqos.c b/drivers/net/designware_eqos.c
index 6b372e4274..79b9979697 100644
--- a/drivers/net/designware_eqos.c
+++ b/drivers/net/designware_eqos.c
@@ -623,10 +623,6 @@ static int eqos_start(struct eth_device *edev)
last_rx_desc = (ulong)&eqos->rx_descs[(EQOS_DESCRIPTORS_RX - 1)];
writel(last_rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer);
- barrier();
-
- eqos->started = true;
-
return 0;
}
@@ -635,13 +631,6 @@ static void eqos_stop(struct eth_device *edev)
struct eqos *eqos = edev->priv;
int i;
- if (!eqos->started)
- return;
-
- eqos->started = false;
-
- barrier();
-
/* Disable TX DMA */
clrbits_le32(&eqos->dma_regs->ch0_tx_control,
EQOS_DMA_CH0_TX_CONTROL_ST);
diff --git a/drivers/net/designware_eqos.h b/drivers/net/designware_eqos.h
index be7bead09e..1b6b0400e1 100644
--- a/drivers/net/designware_eqos.h
+++ b/drivers/net/designware_eqos.h
@@ -60,13 +60,11 @@ struct eqos {
const struct eqos_ops *ops;
void *priv;
- bool started;
};
struct device_d;
int eqos_probe(struct device_d *dev, const struct eqos_ops *ops, void *priv);
void eqos_remove(struct device_d *dev);
-int eqos_reset(struct eqos *priv);
int eqos_get_ethaddr(struct eth_device *edev, unsigned char *mac);
int eqos_set_ethaddr(struct eth_device *edev, const unsigned char *mac);
diff --git a/drivers/net/designware_stm32.c b/drivers/net/designware_stm32.c
index 0a5ced98f5..43f2d0987c 100644
--- a/drivers/net/designware_stm32.c
+++ b/drivers/net/designware_stm32.c
@@ -163,14 +163,7 @@ static int eqos_init_stm32(struct device_d *dev, struct eqos *eqos)
dev_dbg(dev, "No phy clock provided. Continuing without.\n");
}
- ret = clk_bulk_enable(priv->num_clks, priv->clks);
- if (ret < 0) {
- eqos_err(eqos, "clk_bulk_enable() failed: %s\n",
- strerror(-ret));
- return ret;
- }
-
- return 0;
+ return clk_bulk_enable(priv->num_clks, priv->clks);
}
static struct eqos_ops stm32_ops = {
diff --git a/drivers/net/designware_tegra186.c b/drivers/net/designware_tegra186.c
index 0241b9ad16..0cbbdb46a4 100644
--- a/drivers/net/designware_tegra186.c
+++ b/drivers/net/designware_tegra186.c
@@ -195,7 +195,7 @@ static int eqos_set_ethaddr_tegra186(struct eth_device *edev, const unsigned cha
* ported to some system where the expectation above is true.
*/
- if (!eqos->started) {
+ if (!edev->active) {
memcpy(eqos->macaddr, mac, 6);
return 0;
}
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 52ad3d4cdb..3a5ee9988e 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -1388,6 +1388,9 @@ struct e1000_eeprom_info {
#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */
+#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
+#define MAX_PHY_MULTI_PAGE_REG 0xF /* Registers equal on all pages */
+
/* M88E1000 Specific Registers */
#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */
#define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Register */
diff --git a/drivers/net/e1000/main.c b/drivers/net/e1000/main.c
index f67c5d867b..363730de0a 100644
--- a/drivers/net/e1000/main.c
+++ b/drivers/net/e1000/main.c
@@ -54,13 +54,17 @@ static int e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t *speed,
uint16_t *duplex);
static int e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr,
uint16_t *phy_data);
+static int e1000_phy_write(struct mii_bus *bus, int phy_addr, int reg_addr,
+ u16 phy_data);
static int e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr,
uint16_t phy_data);
static int32_t e1000_phy_hw_reset(struct e1000_hw *hw);
static int e1000_phy_reset(struct e1000_hw *hw);
static int e1000_detect_gig_phy(struct e1000_hw *hw);
static void e1000_set_media_type(struct e1000_hw *hw);
-
+static void e1000_configure_tx(struct e1000_hw *hw);
+static void e1000_configure_rx(struct e1000_hw *hw);
+static void e1000_setup_rctl(struct e1000_hw *hw);
static int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
@@ -243,6 +247,10 @@ int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
int32_t timeout = 200;
DEBUGFUNC();
+
+ if (hw->mac_type <= e1000_82547_rev_2)
+ return E1000_SUCCESS;
+
while (timeout) {
if (e1000_get_hw_eeprom_semaphore(hw))
return -E1000_ERR_SWFW_SYNC;
@@ -274,6 +282,9 @@ int32_t e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask)
{
uint32_t swfw_sync;
+ if (hw->mac_type <= e1000_82547_rev_2)
+ return E1000_SUCCESS;
+
if (e1000_get_hw_eeprom_semaphore(hw))
return -E1000_ERR_SWFW_SYNC;
@@ -802,6 +813,10 @@ static int e1000_open(struct eth_device *edev)
e1000_write_reg(hw, E1000_CTRL_EXT, ctrl_ext);
}
+ e1000_configure_tx(hw);
+ e1000_configure_rx(hw);
+ e1000_setup_rctl(hw);
+
return 0;
}
@@ -2627,6 +2642,15 @@ static int e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr,
{
int ret;
+ if ((hw->phy_type == e1000_phy_igp) && (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
+ ret = e1000_phy_write(&hw->miibus, 1, IGP01E1000_PHY_PAGE_SELECT,
+ (u16)reg_addr);
+ if (ret)
+ return ret;
+
+ reg_addr &= MAX_PHY_REG_ADDRESS;
+ }
+
ret = e1000_phy_read(&hw->miibus, 1, reg_addr);
if (ret < 0)
return ret;
@@ -2702,6 +2726,17 @@ static int e1000_phy_write(struct mii_bus *bus, int phy_addr,
******************************************************************************/
static int e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t phy_data)
{
+ int ret;
+
+ if ((hw->phy_type == e1000_phy_igp) && (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
+ ret = e1000_phy_write(&hw->miibus, 1, IGP01E1000_PHY_PAGE_SELECT,
+ (u16)reg_addr);
+ if (ret)
+ return ret;
+
+ reg_addr &= MAX_PHY_REG_ADDRESS;
+ }
+
return e1000_phy_write(&hw->miibus, 1, reg_addr, phy_data);
}
@@ -3546,10 +3581,6 @@ static int e1000_init(struct eth_device *edev)
if (hw->mac_type == e1000_igb)
mdelay(15);
- e1000_configure_tx(hw);
- e1000_configure_rx(hw);
- e1000_setup_rctl(hw);
-
return 0;
}
@@ -3575,9 +3606,6 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *id)
edev->priv = hw;
hw->packet = dma_alloc(PAGE_SIZE);
- if (!hw->packet)
- return -ENOMEM;
-
hw->packet_dma = dma_map_single(hw->dev, hw->packet, PAGE_SIZE,
DMA_FROM_DEVICE);
if (dma_mapping_error(hw->dev, hw->packet_dma))
diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c
index 0c2d600d12..673555a48a 100644
--- a/drivers/net/fec_imx.c
+++ b/drivers/net/fec_imx.c
@@ -320,6 +320,10 @@ static int fec_init(struct eth_device *dev)
/* size of each buffer */
writel(FEC_MAX_PKT_SIZE, fec->regs + FEC_EMRBR);
+ /* set rx and tx buffer descriptor base address */
+ writel(virt_to_phys(fec->tbd_base), fec->regs + FEC_ETDSR);
+ writel(virt_to_phys(fec->rbd_base), fec->regs + FEC_ERDSR);
+
return 0;
}
@@ -359,6 +363,8 @@ static int fec_open(struct eth_device *edev)
if (fec->phy_init)
fec->phy_init(edev->phydev);
+ fec_init(edev);
+
/*
* Initialize RxBD/TxBD rings
*/
@@ -839,9 +845,6 @@ static int fec_probe(struct device_d *dev)
base += FEC_RBD_NUM * sizeof(struct buffer_descriptor);
fec->tbd_base = base;
- writel(virt_to_phys(fec->tbd_base), fec->regs + FEC_ETDSR);
- writel(virt_to_phys(fec->rbd_base), fec->regs + FEC_ERDSR);
-
ret = fec_alloc_receive_packets(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE);
if (ret < 0)
goto free_xbd;
@@ -861,8 +864,6 @@ static int fec_probe(struct device_d *dev)
if (ret)
goto free_receive_packets;
- fec_init(edev);
-
fec->miibus.read = fec_miibus_read;
fec->miibus.write = fec_miibus_write;
diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index 341f5f240e..e923e179bf 100644
--- a/drivers/net/rtl8169.c
+++ b/drivers/net/rtl8169.c
@@ -42,11 +42,13 @@ struct rtl8169_priv {
volatile struct bufdesc *tx_desc;
dma_addr_t tx_desc_phys;
void *tx_buf;
+ dma_addr_t tx_buf_phys;
unsigned int cur_tx;
volatile struct bufdesc *rx_desc;
dma_addr_t rx_desc_phys;
void *rx_buf;
+ dma_addr_t rx_buf_phys;
unsigned int cur_rx;
struct mii_bus miibus;
@@ -218,14 +220,17 @@ static void rtl8169_init_ring(struct rtl8169_priv *priv)
priv->cur_rx = priv->cur_tx = 0;
- priv->tx_desc = dma_alloc_coherent(NUM_TX_DESC *
- sizeof(struct bufdesc), &priv->tx_desc_phys);
+ priv->tx_desc = dma_alloc_coherent(NUM_TX_DESC * sizeof(struct bufdesc),
+ &priv->tx_desc_phys);
priv->tx_buf = malloc(NUM_TX_DESC * PKT_BUF_SIZE);
- priv->rx_desc = dma_alloc_coherent(NUM_RX_DESC *
- sizeof(struct bufdesc), &priv->rx_desc_phys);
+ priv->tx_buf_phys = dma_map_single(&priv->edev.dev, priv->tx_buf,
+ NUM_TX_DESC * PKT_BUF_SIZE, DMA_TO_DEVICE);
+
+ priv->rx_desc = dma_alloc_coherent(NUM_RX_DESC * sizeof(struct bufdesc),
+ &priv->rx_desc_phys);
priv->rx_buf = malloc(NUM_RX_DESC * PKT_BUF_SIZE);
- dma_sync_single_for_device((unsigned long)priv->rx_buf,
- NUM_RX_DESC * PKT_BUF_SIZE, DMA_FROM_DEVICE);
+ priv->rx_buf_phys = dma_map_single(&priv->edev.dev, priv->rx_buf,
+ NUM_RX_DESC * PKT_BUF_SIZE, DMA_FROM_DEVICE);
for (i = 0; i < NUM_RX_DESC; i++) {
if (i == (NUM_RX_DESC - 1))
@@ -236,7 +241,7 @@ static void rtl8169_init_ring(struct rtl8169_priv *priv)
cpu_to_le32(BD_STAT_OWN | PKT_BUF_SIZE);
priv->rx_desc[i].buf_addr =
- cpu_to_le32(virt_to_phys(priv->rx_buf + i * PKT_BUF_SIZE));
+ cpu_to_le32(priv->rx_buf_phys + i * PKT_BUF_SIZE);
}
}
@@ -288,6 +293,8 @@ static int rtl8169_eth_open(struct eth_device *edev)
struct rtl8169_priv *priv = edev->priv;
int ret;
+ pci_set_master(priv->pci_dev);
+
rtl8169_init_ring(priv);
rtl8169_hw_start(priv);
@@ -353,12 +360,12 @@ static int rtl8169_eth_send(struct eth_device *edev, void *packet,
if (packet_length < ETH_ZLEN)
memset(priv->tx_buf + entry * PKT_BUF_SIZE, 0, ETH_ZLEN);
memcpy(priv->tx_buf + entry * PKT_BUF_SIZE, packet, packet_length);
- dma_sync_single_for_device((unsigned long)priv->tx_buf + entry *
+ dma_sync_single_for_device(priv->tx_buf_phys + entry *
PKT_BUF_SIZE, PKT_BUF_SIZE, DMA_TO_DEVICE);
priv->tx_desc[entry].buf_Haddr = 0;
priv->tx_desc[entry].buf_addr =
- cpu_to_le32(virt_to_phys(priv->tx_buf + entry * PKT_BUF_SIZE));
+ cpu_to_le32(priv->tx_buf_phys + entry * PKT_BUF_SIZE);
if (entry != (NUM_TX_DESC - 1)) {
priv->tx_desc[entry].status =
@@ -375,8 +382,8 @@ static int rtl8169_eth_send(struct eth_device *edev, void *packet,
while (le32_to_cpu(priv->tx_desc[entry].status) & BD_STAT_OWN)
;
- dma_sync_single_for_cpu((unsigned long)priv->tx_buf + entry *
- PKT_BUF_SIZE, PKT_BUF_SIZE, DMA_TO_DEVICE);
+ dma_sync_single_for_cpu(priv->tx_buf_phys + entry * PKT_BUF_SIZE,
+ PKT_BUF_SIZE, DMA_TO_DEVICE);
priv->cur_tx++;
@@ -395,15 +402,13 @@ static int rtl8169_eth_rx(struct eth_device *edev)
if (!(le32_to_cpu(priv->rx_desc[entry].status) & BD_STAT_RX_RES)) {
pkt_size = (le32_to_cpu(priv->rx_desc[entry].status) & 0x1fff) - 4;
- dma_sync_single_for_cpu((unsigned long)priv->rx_buf
- + entry * PKT_BUF_SIZE,
+ dma_sync_single_for_cpu(priv->rx_buf_phys + entry * PKT_BUF_SIZE,
pkt_size, DMA_FROM_DEVICE);
net_receive(edev, priv->rx_buf + entry * PKT_BUF_SIZE,
pkt_size);
- dma_sync_single_for_device((unsigned long)priv->rx_buf
- + entry * PKT_BUF_SIZE,
+ dma_sync_single_for_device(priv->rx_buf_phys + entry * PKT_BUF_SIZE,
pkt_size, DMA_FROM_DEVICE);
if (entry == NUM_RX_DESC - 1)
@@ -413,8 +418,8 @@ static int rtl8169_eth_rx(struct eth_device *edev)
priv->rx_desc[entry].status =
cpu_to_le32(BD_STAT_OWN | PKT_BUF_SIZE);
priv->rx_desc[entry].buf_addr =
- cpu_to_le32(virt_to_phys(priv->rx_buf +
- entry * PKT_BUF_SIZE));
+ cpu_to_le32(priv->rx_buf_phys +
+ entry * PKT_BUF_SIZE);
} else {
dev_err(&edev->dev, "rx error\n");
}
@@ -473,6 +478,18 @@ static void rtl8169_eth_halt(struct eth_device *edev)
RTL_W32(priv, RxMissed, 0);
pci_clear_master(priv->pci_dev);
+
+ dma_unmap_single(&edev->dev, priv->tx_buf_phys, NUM_TX_DESC * PKT_BUF_SIZE,
+ DMA_TO_DEVICE);
+ free(priv->tx_buf);
+ dma_free_coherent((void *)priv->tx_desc, priv->tx_desc_phys,
+ NUM_TX_DESC * sizeof(struct bufdesc));
+
+ dma_unmap_single(&edev->dev, priv->rx_buf_phys, NUM_RX_DESC * PKT_BUF_SIZE,
+ DMA_FROM_DEVICE);
+ free(priv->rx_buf);
+ dma_free_coherent((void *)priv->rx_desc, priv->rx_desc_phys,
+ NUM_RX_DESC * sizeof(struct bufdesc));
}
static int rtl8169_probe(struct pci_dev *pdev, const struct pci_device_id *id)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 83291c4785..b91ee92e1b 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -17,8 +17,8 @@
#include <linux/sizes.h>
#include <of_graph.h>
#include <string.h>
+#include <linux/clk.h>
#include <linux/ctype.h>
-#include <linux/amba/bus.h>
#include <linux/err.h>
static struct device_node *root_node;
@@ -2006,7 +2006,26 @@ int of_property_read_string_helper(const struct device_node *np,
return i <= 0 ? -ENODATA : i;
}
-static int __of_print_nodes(struct device_node *node, int indent, const char *prefix)
+static void __of_print_property_prefixed(const struct property *p, int indent,
+ unsigned maxpropsize, const char *prefix)
+{
+ unsigned length;
+
+ printf("%s%*s%s", prefix, indent * 8, "", p->name);
+
+ length = min_t(unsigned, p->length, maxpropsize);
+ if (length) {
+ printf(" = ");
+ of_print_property(of_property_get_value(p), length);
+ }
+ if (length != p->length)
+ printf(" /* %u more bytes omitted */", p->length - length);
+
+ printf(";\n");
+}
+
+static int __of_print_nodes(struct device_node *node, int indent,
+ unsigned maxpropsize, const char *prefix)
{
struct device_node *n;
struct property *p;
@@ -2020,20 +2039,14 @@ static int __of_print_nodes(struct device_node *node, int indent, const char *pr
printf("%s%*s%s%s\n", prefix, indent * 8, "", node->name, node->name ? " {" : "{");
- list_for_each_entry(p, &node->properties, list) {
- printf("%s%*s%s", prefix, (indent + 1) * 8, "", p->name);
- if (p->length) {
- printf(" = ");
- of_print_property(of_property_get_value(p), p->length);
- }
- printf(";\n");
- }
+ list_for_each_entry(p, &node->properties, list)
+ __of_print_property_prefixed(p, indent + 1, maxpropsize, prefix);
if (ctrlc())
return -EINTR;
list_for_each_entry(n, &node->children, parent_list) {
- ret = __of_print_nodes(n, indent + 1, prefix);
+ ret = __of_print_nodes(n, indent + 1, maxpropsize, prefix);
if (ret)
return ret;
}
@@ -2042,27 +2055,22 @@ static int __of_print_nodes(struct device_node *node, int indent, const char *pr
return 0;
}
-void of_print_nodes(struct device_node *node, int indent)
+void of_print_nodes(struct device_node *node, int indent, unsigned maxpropsize)
{
- __of_print_nodes(node, indent, NULL);
+ __of_print_nodes(node, indent, maxpropsize, NULL);
}
-static void __of_print_property(struct property *p, int indent)
+static void __of_print_property(struct property *p, int indent, unsigned maxpropsize)
{
- printf("%*s%s", indent * 8, "", p->name);
- if (p->length) {
- printf(" = ");
- of_print_property(of_property_get_value(p), p->length);
- }
- printf(";\n");
+ __of_print_property_prefixed(p, indent, maxpropsize, "");
}
-void of_print_properties(struct device_node *node)
+void of_print_properties(struct device_node *node, unsigned maxpropsize)
{
struct property *prop;
list_for_each_entry(prop, &node->properties, list)
- __of_print_property(prop, 0);
+ __of_print_property(prop, 0, maxpropsize);
}
static int __of_print_parents(struct device_node *node)
@@ -2130,7 +2138,7 @@ int of_diff(struct device_node *a, struct device_node *b, int indent)
continue;
of_print_parents(a, &printed);
printf("- ");
- __of_print_property(ap, indent);
+ __of_print_property(ap, indent, ~0);
continue;
}
@@ -2140,9 +2148,9 @@ int of_diff(struct device_node *a, struct device_node *b, int indent)
continue;
of_print_parents(a, &printed);
printf("- ");
- __of_print_property(ap, indent);
+ __of_print_property(ap, indent, ~0);
printf("+ ");
- __of_print_property(bp, indent);
+ __of_print_property(bp, indent, ~0);
}
}
@@ -2154,7 +2162,7 @@ int of_diff(struct device_node *a, struct device_node *b, int indent)
continue;
of_print_parents(a, &printed);
printf("+ ");
- __of_print_property(bp, indent);
+ __of_print_property(bp, indent, ~0);
}
}
@@ -2167,7 +2175,7 @@ int of_diff(struct device_node *a, struct device_node *b, int indent)
if (silent)
continue;
of_print_parents(a, &printed);
- __of_print_nodes(ca, indent, "- ");
+ __of_print_nodes(ca, indent, ~0, "- ");
}
}
@@ -2177,7 +2185,7 @@ int of_diff(struct device_node *a, struct device_node *b, int indent)
if (silent)
continue;
of_print_parents(a, &printed);
- __of_print_nodes(cb, indent, "+ ");
+ __of_print_nodes(cb, indent, ~0, "+ ");
}
}
@@ -2213,8 +2221,8 @@ struct device_node *of_new_node(struct device_node *parent, const char *name)
return node;
}
-static struct property *__of_new_property(struct device_node *node, const char *name,
- void *data, int len)
+struct property *__of_new_property(struct device_node *node, const char *name,
+ void *data, int len)
{
struct property *prop;
@@ -2321,6 +2329,39 @@ int of_set_property(struct device_node *np, const char *name, const void *val, i
return 0;
}
+int of_append_property(struct device_node *np, const char *name, const void *val, int len)
+{
+ struct property *pp;
+ int orig_len;
+ void *buf;
+
+ if (!np)
+ return -ENOENT;
+
+ pp = of_find_property(np, name, NULL);
+ if (!pp) {
+ of_new_property(np, name, val, len);
+ return 0;
+ }
+
+ orig_len = pp->length;
+ buf = realloc(pp->value, orig_len + len);
+ if (!buf)
+ return -ENOMEM;
+
+ memcpy(buf + orig_len, val, len);
+
+ pp->value = buf;
+ pp->length += len;
+
+ if (pp->value_const) {
+ memcpy(buf, pp->value_const, orig_len);
+ pp->value_const = NULL;
+ }
+
+ return 0;
+}
+
int of_property_sprintf(struct device_node *np,
const char *propname, const char *fmt, ...)
{
diff --git a/drivers/of/of_gpio.c b/drivers/of/of_gpio.c
index 42e0347529..c23923b425 100644
--- a/drivers/of/of_gpio.c
+++ b/drivers/of/of_gpio.c
@@ -62,6 +62,7 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname,
{
struct of_phandle_args out_args;
struct device_d *dev;
+ int of_flags;
int ret;
ret = of_parse_phandle_with_args(np, propname, "#gpio-cells",
@@ -79,7 +80,7 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname,
return -EPROBE_DEFER;
}
- ret = gpio_get_num(dev, out_args.args[0]);
+ ret = gpio_of_xlate(dev, &out_args, &of_flags);
if (ret == -EPROBE_DEFER)
return ret;
if (ret < 0) {
@@ -89,7 +90,7 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname,
}
if (flags) {
- *flags = out_args.args[1];
+ *flags = of_flags;
of_gpio_flags_quirks(np, propname, flags, index);
}
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index b298da0000..8a57bd1aa9 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -220,6 +220,11 @@ static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
{
struct phy_provider *phy_provider;
struct device_node *child;
+ int ret;
+
+ ret = of_device_ensure_probed(node);
+ if (ret)
+ return ERR_PTR(ret);
list_for_each_entry(phy_provider, &phy_provider_list, list) {
if (phy_provider->dev->device_node == node)
@@ -255,10 +260,6 @@ static struct phy *_of_phy_get(struct device_node *np, int index)
if (ret)
return ERR_PTR(-ENODEV);
- ret = of_device_ensure_probed(args.np);
- if (ret)
- return ERR_PTR(ret);
-
phy_provider = of_phy_provider_lookup(args.np);
if (IS_ERR(phy_provider)) {
return ERR_CAST(phy_provider);
@@ -316,7 +317,7 @@ struct phy *of_phy_get_by_phandle(struct device_d *dev, const char *phandle,
phy_provider = of_phy_provider_lookup(np);
if (IS_ERR(phy_provider)) {
- return ERR_PTR(-ENODEV);
+ return ERR_CAST(phy_provider);
}
return phy_provider->of_xlate(phy_provider->dev, NULL);
diff --git a/drivers/pinctrl/pinctrl-stm32.c b/drivers/pinctrl/pinctrl-stm32.c
index cee10636ce..fc0cc78f43 100644
--- a/drivers/pinctrl/pinctrl-stm32.c
+++ b/drivers/pinctrl/pinctrl-stm32.c
@@ -24,7 +24,6 @@
struct stm32_gpio_bank {
void __iomem *base;
struct gpio_chip chip;
- struct clk *clk;
const char *name;
};
@@ -154,8 +153,6 @@ static int __stm32_pinctrl_set_state(struct device_d *dev, struct device_node *p
"fn %u, mode %u, alt %u\n",
bank->name, offset, func, mode, alt);
- clk_enable(bank->clk);
-
__stm32_pmx_set_mode(bank->base, offset, mode, alt);
if (adjust_slew_rate)
@@ -173,8 +170,6 @@ static int __stm32_pinctrl_set_state(struct device_d *dev, struct device_node *p
__stm32_pmx_gpio_output(bank->base, offset, 0);
else if (dir == PIN_OUTPUT_HIGH)
__stm32_pmx_gpio_output(bank->base, offset, 1);
-
- clk_disable(bank->clk);
}
return 0;
@@ -219,8 +214,6 @@ static int stm32_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio)
int ret;
u32 mode, alt;
- clk_enable(bank->clk);
-
__stm32_pmx_get_mode(bank->base, stm32_gpio_pin(gpio, NULL), &mode, &alt);
if ((alt == 0) && (mode == 0))
ret = 1;
@@ -229,8 +222,6 @@ static int stm32_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio)
else
ret = -EINVAL;
- clk_disable(bank->clk);
-
return ret;
}
@@ -238,37 +229,22 @@ static void stm32_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
{
struct stm32_gpio_bank *bank = to_stm32_gpio_bank(chip);
- clk_enable(bank->clk);
-
__stm32_pmx_gpio_set(bank->base, stm32_gpio_pin(gpio, NULL), value);
-
- clk_disable(bank->clk);
}
static int stm32_gpio_get(struct gpio_chip *chip, unsigned gpio)
{
struct stm32_gpio_bank *bank = to_stm32_gpio_bank(chip);
- int ret;
-
- clk_enable(bank->clk);
-
- ret = __stm32_pmx_gpio_get(bank->base, stm32_gpio_pin(gpio, NULL));
- clk_disable(bank->clk);
-
- return ret;
+ return __stm32_pmx_gpio_get(bank->base, stm32_gpio_pin(gpio, NULL));
}
static int stm32_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
struct stm32_gpio_bank *bank = to_stm32_gpio_bank(chip);
- clk_enable(bank->clk);
-
__stm32_pmx_gpio_input(bank->base, stm32_gpio_pin(gpio, NULL));
- clk_disable(bank->clk);
-
return 0;
}
@@ -277,12 +253,8 @@ static int stm32_gpio_direction_output(struct gpio_chip *chip,
{
struct stm32_gpio_bank *bank = to_stm32_gpio_bank(chip);
- clk_enable(bank->clk);
-
__stm32_pmx_gpio_output(bank->base, stm32_gpio_pin(gpio, NULL), value);
- clk_disable(bank->clk);
-
return 0;
}
@@ -302,6 +274,7 @@ static int stm32_gpiochip_add(struct stm32_gpio_bank *bank,
struct resource *iores;
enum { PINCTRL_PHANDLE, GPIOCTRL_OFFSET, PINCTRL_OFFSET, PINCOUNT, GPIO_RANGE_NCELLS };
const __be32 *gpio_ranges;
+ struct clk *clk;
u32 ngpios;
int ret, size;
@@ -350,12 +323,15 @@ static int stm32_gpiochip_add(struct stm32_gpio_bank *bank,
bank->chip.base = be32_to_cpu(gpio_ranges[PINCTRL_OFFSET]);
bank->chip.ops = &stm32_gpio_ops;
bank->chip.dev = dev;
- bank->clk = clk_get(dev, NULL);
- if (IS_ERR(bank->clk)) {
- dev_err(dev, "failed to get clk (%ld)\n", PTR_ERR(bank->clk));
- return PTR_ERR(bank->clk);
+
+ clk = clk_get(dev, NULL);
+ if (IS_ERR(clk)) {
+ dev_err(dev, "failed to get clk (%ld)\n", PTR_ERR(clk));
+ return PTR_ERR(clk);
}
+ clk_enable(clk);
+
return gpiochip_add(&bank->chip);
}
diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c
index 01709e0019..1316af4213 100644
--- a/drivers/power/reset/reboot-mode.c
+++ b/drivers/power/reset/reboot-mode.c
@@ -12,8 +12,6 @@
#include <globalvar.h>
#include <magicvar.h>
-#define PREFIX "mode-"
-
static int __priority;
static struct reboot_mode_driver *__boot_mode;
@@ -111,6 +109,19 @@ static void reboot_mode_print(struct reboot_mode_driver *reboot,
__pr_printk(7, "\n");
}
+static const char *get_mode_name(const struct property *prop)
+{
+ unsigned prefix_len;
+
+ prefix_len = str_has_prefix(prop->name, "mode-");
+ if (!prefix_len)
+ prefix_len = str_has_prefix(prop->name, "barebox,mode-");
+ if (!prefix_len)
+ return NULL;
+
+ return prop->name + prefix_len;
+}
+
/**
* reboot_mode_register - register a reboot mode driver
* @reboot: reboot mode driver
@@ -123,7 +134,6 @@ int reboot_mode_register(struct reboot_mode_driver *reboot,
{
struct property *prop;
struct device_node *np = reboot->dev->device_node;
- size_t len = strlen(PREFIX);
const char *alias;
size_t nmodes = 0;
int i = 0;
@@ -132,7 +142,7 @@ int reboot_mode_register(struct reboot_mode_driver *reboot,
for_each_property_of_node(np, prop) {
u32 magic;
- if (strncmp(prop->name, PREFIX, len))
+ if (!get_mode_name(prop))
continue;
if (of_property_read_u32(np, prop->name, &magic))
continue;
@@ -154,16 +164,9 @@ int reboot_mode_register(struct reboot_mode_driver *reboot,
magic = &reboot->magics[i * nelems];
mode = &reboot->modes[i];
- if (strncmp(prop->name, PREFIX, len))
- continue;
-
- if (of_property_read_u32_array(np, prop->name, magic, nelems)) {
- dev_err(reboot->dev, "reboot mode %s without magic number\n",
- *mode);
+ *mode = get_mode_name(prop);
+ if (!*mode)
continue;
- }
-
- *mode = prop->name + len;
if (*mode[0] == '\0') {
ret = -EINVAL;
dev_err(reboot->dev, "invalid mode name(%s): too short!\n",
@@ -174,6 +177,12 @@ int reboot_mode_register(struct reboot_mode_driver *reboot,
if (!strcmp(*mode, "normal"))
normal = i;
+ if (of_property_read_u32_array(np, prop->name, magic, nelems)) {
+ dev_err(reboot->dev, "reboot mode %s without magic number\n",
+ *mode);
+ continue;
+ }
+
reboot_mode_print(reboot, *mode, magic);
i++;
diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c
index 648f75fb72..9ec81e18b1 100644
--- a/drivers/pwm/pwm-atmel.c
+++ b/drivers/pwm/pwm-atmel.c
@@ -55,15 +55,7 @@
#define PWMV2_CPRD 0x0C
#define PWMV2_CPRDUPD 0x10
-/*
- * Max value for duty and period
- *
- * Although the duty and period register is 32 bit,
- * however only the LSB 16 bits are significant.
- */
-#define PWM_MAX_DTY 0xFFFF
-#define PWM_MAX_PRD 0xFFFF
-#define PRD_MAX_PRES 10
+#define PWM_MAX_PRES 10
struct atmel_pwm_registers {
u8 period;
@@ -72,30 +64,53 @@ struct atmel_pwm_registers {
u8 duty_upd;
};
-struct atmel_pwm;
+struct atmel_pwm_config {
+ u32 period_bits;
+};
-struct atmel_pwm_chip {
- struct pwm_chip chip;
- struct atmel_pwm *atmel;
+struct atmel_pwm_data {
+ struct atmel_pwm_registers regs;
+ struct atmel_pwm_config cfg;
};
-struct atmel_pwm {
- struct atmel_pwm_chip atmel_pwm_chip[PWM_CHANNELS];
- const struct atmel_pwm_registers *regs;
+struct atmel_pwm_chip {
+ struct pwm_chip chips[PWM_CHANNELS];
struct clk *clk;
void __iomem *base;
struct device_d *dev;
+ const struct atmel_pwm_data *data;
+
+ /*
+ * The hardware supports a mechanism to update a channel's duty cycle at
+ * the end of the currently running period. When such an update is
+ * pending we delay disabling the PWM until the new configuration is
+ * active because otherwise pmw_config(duty_cycle=0); pwm_disable();
+ * might not result in an inactive output.
+ * This bitmask tracks for which channels an update is pending in
+ * hardware.
+ */
+ u32 update_pending;
+
+ /* Protects .update_pending */
+ spinlock_t lock;
};
static inline struct atmel_pwm_chip *to_atmel_pwm_chip(struct pwm_chip *chip)
{
- return container_of(chip, struct atmel_pwm_chip, chip);
+ struct pwm_chip (*chips)[4] = (void *)&chip[-chip->id];
+ return container_of(chips, struct atmel_pwm_chip, chips);
+}
+
+static inline u32 atmel_pwm_readl(struct atmel_pwm_chip *chip,
+ unsigned long offset)
+{
+ return readl_relaxed(chip->base + offset);
}
static inline void atmel_pwm_writel(struct atmel_pwm_chip *chip,
unsigned long offset, unsigned long val)
{
- writel(val, chip->atmel->base + offset);
+ writel_relaxed(val, chip->base + offset);
}
static inline u32 atmel_pwm_ch_readl(struct atmel_pwm_chip *chip,
@@ -103,7 +118,7 @@ static inline u32 atmel_pwm_ch_readl(struct atmel_pwm_chip *chip,
{
unsigned long base = PWM_CH_REG_OFFSET + ch * PWM_CH_REG_SIZE;
- return readl(chip->atmel->base + base + offset);
+ return atmel_pwm_readl(chip, base + offset);
}
static inline void atmel_pwm_ch_writel(struct atmel_pwm_chip *chip,
@@ -112,24 +127,95 @@ static inline void atmel_pwm_ch_writel(struct atmel_pwm_chip *chip,
{
unsigned long base = PWM_CH_REG_OFFSET + ch * PWM_CH_REG_SIZE;
- writel(val, chip->atmel->base + base + offset);
+ atmel_pwm_writel(chip, base + offset, val);
+}
+
+static void atmel_pwm_update_pending(struct atmel_pwm_chip *chip)
+{
+ /*
+ * Each channel that has its bit in ISR set started a new period since
+ * ISR was cleared and so there is no more update pending. Note that
+ * reading ISR clears it, so this needs to handle all channels to not
+ * loose information.
+ */
+ u32 isr = atmel_pwm_readl(chip, PWM_ISR);
+
+ chip->update_pending &= ~isr;
+}
+
+static void atmel_pwm_set_pending(struct atmel_pwm_chip *chip, unsigned int ch)
+{
+ spin_lock(&chip->lock);
+
+ /*
+ * Clear pending flags in hardware because otherwise there might still
+ * be a stale flag in ISR.
+ */
+ atmel_pwm_update_pending(chip);
+
+ chip->update_pending |= (1 << ch);
+
+ spin_unlock(&chip->lock);
+}
+
+static int atmel_pwm_test_pending(struct atmel_pwm_chip *chip, unsigned int ch)
+{
+ int ret = 0;
+
+ spin_lock(&chip->lock);
+
+ if (chip->update_pending & (1 << ch)) {
+ atmel_pwm_update_pending(chip);
+
+ if (chip->update_pending & (1 << ch))
+ ret = 1;
+ }
+
+ spin_unlock(&chip->lock);
+
+ return ret;
+}
+
+static int atmel_pwm_wait_nonpending(struct atmel_pwm_chip *chip, unsigned int ch)
+{
+ unsigned long timeout = get_time_ns() + 2 * HZ;
+ int ret;
+
+ while ((ret = atmel_pwm_test_pending(chip, ch)) &&
+ !is_timeout(get_time_ns(), timeout))
+ udelay(100);
+
+ return ret ? -ETIMEDOUT : 0;
}
-static int atmel_pwm_calculate_cprd_and_pres(struct atmel_pwm_chip *atmel_pwm,
- int period,
+static int atmel_pwm_calculate_cprd_and_pres(struct pwm_chip *chip,
+ unsigned long clkrate,
+ const struct pwm_state *state,
unsigned long *cprd, u32 *pres)
{
- unsigned long long cycles = period;
+ struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
+ unsigned long long cycles = state->period_ns;
+ int shift;
+
/* Calculate the period cycles and prescale value */
- cycles *= clk_get_rate(atmel_pwm->atmel->clk);
+ cycles *= clkrate;
do_div(cycles, NSEC_PER_SEC);
- for (*pres = 0; cycles > PWM_MAX_PRD; cycles >>= 1)
- (*pres)++;
+ /*
+ * The register for the period length is cfg.period_bits bits wide.
+ * So for each bit the number of clock cycles is wider divide the input
+ * clock frequency by two using pres and shift cprd accordingly.
+ */
+ shift = fls(cycles) - atmel_pwm->data->cfg.period_bits;
- if (*pres > PRD_MAX_PRES) {
- dev_err(atmel_pwm->atmel->dev, "pres exceeds the maximum value\n");
+ if (shift > PWM_MAX_PRES) {
+ dev_err(atmel_pwm->dev, "pres exceeds the maximum value\n");
return -EINVAL;
+ } else if (shift > 0) {
+ *pres = shift;
+ cycles >>= *pres;
+ } else {
+ *pres = 0;
}
*cprd = cycles;
@@ -137,137 +223,238 @@ static int atmel_pwm_calculate_cprd_and_pres(struct atmel_pwm_chip *atmel_pwm,
return 0;
}
-static void atmel_pwm_calculate_cdty(int duty, int period,
- unsigned long cprd, unsigned long *cdty)
+static void atmel_pwm_calculate_cdty(const struct pwm_state *state,
+ unsigned long clkrate, unsigned long cprd,
+ u32 pres, unsigned long *cdty)
{
- unsigned long long cycles = duty;
+ unsigned long long cycles = state->duty_ns;
- cycles *= cprd;
- do_div(cycles, period);
+ cycles *= clkrate;
+ do_div(cycles, NSEC_PER_SEC);
+ cycles >>= pres;
*cdty = cprd - cycles;
}
-static void atmel_pwm_set_cprd_cdty(struct atmel_pwm_chip *atmel_pwm, int ch,
+static void atmel_pwm_update_cdty(struct pwm_chip *chip, unsigned long cdty)
+{
+ struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
+ u32 val;
+
+ if (atmel_pwm->data->regs.duty_upd ==
+ atmel_pwm->data->regs.period_upd) {
+ val = atmel_pwm_ch_readl(atmel_pwm, chip->id, PWM_CMR);
+ val &= ~PWM_CMR_UPD_CDTY;
+ atmel_pwm_ch_writel(atmel_pwm, chip->id, PWM_CMR, val);
+ }
+
+ atmel_pwm_ch_writel(atmel_pwm, chip->id,
+ atmel_pwm->data->regs.duty_upd, cdty);
+ atmel_pwm_set_pending(atmel_pwm, chip->id);
+}
+
+static void atmel_pwm_set_cprd_cdty(struct pwm_chip *chip,
unsigned long cprd, unsigned long cdty)
{
- const struct atmel_pwm_registers *regs = atmel_pwm->atmel->regs;
+ struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
- atmel_pwm_ch_writel(atmel_pwm, ch, regs->duty, cdty);
- atmel_pwm_ch_writel(atmel_pwm, ch, regs->period, cprd);
+ atmel_pwm_ch_writel(atmel_pwm, chip->id,
+ atmel_pwm->data->regs.duty, cdty);
+ atmel_pwm_ch_writel(atmel_pwm, chip->id,
+ atmel_pwm->data->regs.period, cprd);
}
-static int atmel_pwm_config(struct pwm_chip *chip, int duty_ns, int period_ns)
+static void atmel_pwm_disable(struct pwm_chip *chip, bool disable_clk)
{
struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
- unsigned long cprd, cdty;
- u32 pres, val;
- int ret;
- int ch;
+ unsigned long timeout;
- ch = atmel_pwm->chip.id;
- ret = atmel_pwm_calculate_cprd_and_pres(atmel_pwm, period_ns, &cprd, &pres);
- if (ret)
- return ret;
+ atmel_pwm_wait_nonpending(atmel_pwm, chip->id);
- atmel_pwm_calculate_cdty(duty_ns, period_ns, cprd, &cdty);
+ atmel_pwm_writel(atmel_pwm, PWM_DIS, 1 << chip->id);
- /* It is necessary to preserve CPOL, inside CMR */
- val = atmel_pwm_ch_readl(atmel_pwm, ch, PWM_CMR);
- val = (val & ~PWM_CMR_CPRE_MSK) | (pres & PWM_CMR_CPRE_MSK);
- /* Assuming normal polarity */
- val &= ~PWM_CMR_CPOL;
+ /*
+ * Wait for the PWM channel disable operation to be effective before
+ * stopping the clock.
+ */
+ timeout = get_time_ns() + 2 * HZ;
- atmel_pwm_ch_writel(atmel_pwm, ch, PWM_CMR, val);
- atmel_pwm_set_cprd_cdty(atmel_pwm, ch, cprd, cdty);
+ while ((atmel_pwm_readl(atmel_pwm, PWM_SR) & (1 << chip->id)) &&
+ !is_timeout(get_time_ns(), timeout))
+ udelay(100);
- return 0;
+ if (disable_clk)
+ clk_disable(atmel_pwm->clk);
}
-static int atmel_pwm_enable(struct pwm_chip *chip)
+static int atmel_pwm_apply(struct pwm_chip *chip, const struct pwm_state *state)
{
struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
+ struct pwm_state cstate;
+ unsigned long cprd, cdty;
+ u32 pres, val;
+ int ret;
- atmel_pwm_writel(atmel_pwm, PWM_ENA, 1 << atmel_pwm->chip.id);
- return 0;
-}
+ cstate = chip->state;
-static void atmel_pwm_disable(struct pwm_chip *chip)
-{
- struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
+ if (state->p_enable) {
+ unsigned long clkrate = clk_get_rate(atmel_pwm->clk);
+
+ if (cstate.p_enable &&
+ cstate.polarity == state->polarity &&
+ cstate.period_ns == state->period_ns) {
+ u32 cmr = atmel_pwm_ch_readl(atmel_pwm, chip->id, PWM_CMR);
+
+ cprd = atmel_pwm_ch_readl(atmel_pwm, chip->id,
+ atmel_pwm->data->regs.period);
+ pres = cmr & PWM_CMR_CPRE_MSK;
+
+ atmel_pwm_calculate_cdty(state, clkrate, cprd, pres, &cdty);
+ atmel_pwm_update_cdty(chip, cdty);
+ return 0;
+ }
+
+ ret = atmel_pwm_calculate_cprd_and_pres(chip, clkrate, state, &cprd,
+ &pres);
+ if (ret) {
+ dev_err(atmel_pwm->dev,
+ "failed to calculate cprd and prescaler\n");
+ return ret;
+ }
+
+ atmel_pwm_calculate_cdty(state, clkrate, cprd, pres, &cdty);
- atmel_pwm_writel(atmel_pwm, PWM_DIS, 1 << atmel_pwm->chip.id);
+ if (cstate.p_enable) {
+ atmel_pwm_disable(chip, false);
+ } else {
+ ret = clk_enable(atmel_pwm->clk);
+ if (ret) {
+ dev_err(atmel_pwm->dev, "failed to enable clock\n");
+ return ret;
+ }
+ }
+
+ /* It is necessary to preserve CPOL, inside CMR */
+ val = atmel_pwm_ch_readl(atmel_pwm, chip->id, PWM_CMR);
+ val = (val & ~PWM_CMR_CPRE_MSK) | (pres & PWM_CMR_CPRE_MSK);
+ if (state->polarity == PWM_POLARITY_NORMAL)
+ val &= ~PWM_CMR_CPOL;
+ else
+ val |= PWM_CMR_CPOL;
+ atmel_pwm_ch_writel(atmel_pwm, chip->id, PWM_CMR, val);
+ atmel_pwm_set_cprd_cdty(chip, cprd, cdty);
+ atmel_pwm_writel(atmel_pwm, PWM_ENA, 1 << chip->id);
+ } else if (cstate.p_enable) {
+ atmel_pwm_disable(chip, true);
+ }
+
+ return 0;
}
-static struct pwm_ops atmel_pwm_ops = {
- .config = atmel_pwm_config,
- .enable = atmel_pwm_enable,
- .disable = atmel_pwm_disable,
+static const struct pwm_ops atmel_pwm_ops = {
+ .apply = atmel_pwm_apply,
};
-static const struct atmel_pwm_registers atmel_pwm_regs_v1 = {
- .period = PWMV1_CPRD,
- .period_upd = PWMV1_CUPD,
- .duty = PWMV1_CDTY,
- .duty_upd = PWMV1_CUPD,
+static const struct atmel_pwm_data atmel_sam9rl_pwm_data = {
+ .regs = {
+ .period = PWMV1_CPRD,
+ .period_upd = PWMV1_CUPD,
+ .duty = PWMV1_CDTY,
+ .duty_upd = PWMV1_CUPD,
+ },
+ .cfg = {
+ /* 16 bits to keep period and duty. */
+ .period_bits = 16,
+ },
+};
+
+static const struct atmel_pwm_data atmel_sama5_pwm_data = {
+ .regs = {
+ .period = PWMV2_CPRD,
+ .period_upd = PWMV2_CPRDUPD,
+ .duty = PWMV2_CDTY,
+ .duty_upd = PWMV2_CDTYUPD,
+ },
+ .cfg = {
+ /* 16 bits to keep period and duty. */
+ .period_bits = 16,
+ },
};
-static const struct atmel_pwm_registers atmel_pwm_regs_v2 = {
- .period = PWMV2_CPRD,
- .period_upd = PWMV2_CPRDUPD,
- .duty = PWMV2_CDTY,
- .duty_upd = PWMV2_CDTYUPD,
+static const struct atmel_pwm_data mchp_sam9x60_pwm_data = {
+ .regs = {
+ .period = PWMV1_CPRD,
+ .period_upd = PWMV1_CUPD,
+ .duty = PWMV1_CDTY,
+ .duty_upd = PWMV1_CUPD,
+ },
+ .cfg = {
+ /* 32 bits to keep period and duty. */
+ .period_bits = 32,
+ },
};
static const struct of_device_id atmel_pwm_dt_ids[] = {
{
.compatible = "atmel,at91sam9rl-pwm",
- .data = &atmel_pwm_regs_v1,
+ .data = &atmel_sam9rl_pwm_data,
}, {
.compatible = "atmel,sama5d3-pwm",
- .data = &atmel_pwm_regs_v2,
+ .data = &atmel_sama5_pwm_data,
}, {
.compatible = "atmel,sama5d2-pwm",
- .data = &atmel_pwm_regs_v2,
+ .data = &atmel_sama5_pwm_data,
+ }, {
+ .compatible = "microchip,sam9x60-pwm",
+ .data = &mchp_sam9x60_pwm_data,
}, {
/* sentinel */
},
};
+static int id = -1;
+
static int atmel_pwm_probe(struct device_d *dev)
{
- const struct atmel_pwm_registers *regs;
- struct atmel_pwm *atmel_pwm;
- struct resource *res;
+ const struct atmel_pwm_data *data;
+ struct atmel_pwm_chip *atmel_pwm;
+ struct resource *iores;
+ const char *alias;
int ret;
int i;
- ret = dev_get_drvdata(dev, (const void **)&regs);
+ ret = dev_get_drvdata(dev, (const void **)&data);
if (ret)
return ret;
atmel_pwm = xzalloc(sizeof(*atmel_pwm));
- atmel_pwm->regs = regs;
+ atmel_pwm->data = data;
atmel_pwm->dev = dev;
atmel_pwm->clk = clk_get(dev, "pwm_clk");
if (IS_ERR(atmel_pwm->clk))
return PTR_ERR(atmel_pwm->clk);
- res = dev_request_mem_resource(dev, 0);
- if (IS_ERR(res))
- return PTR_ERR(res);
+ iores = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
- atmel_pwm->base = IOMEM(res->start);
+ atmel_pwm->base = IOMEM(iores->start);
+ alias = of_alias_get(dev->device_node);
+ if (!alias)
+ id++;
for (i = 0; i < PWM_CHANNELS; i++) {
- struct atmel_pwm_chip *chip = &atmel_pwm->atmel_pwm_chip[i];
- chip->chip.ops = &atmel_pwm_ops;
- chip->chip.devname = basprintf("pwm%d", i);
- chip->chip.id = i;
- chip->atmel = atmel_pwm;
-
- ret = pwmchip_add(&chip->chip, dev);
- if (ret < 0) {
- dev_err(dev, "failed to add pwm chip[%d] %d\n", i, ret);
+ struct pwm_chip *chip = &atmel_pwm->chips[i];
+
+ if (alias)
+ chip->devname = basprintf("%sch%u", alias, i + 1);
+ else
+ chip->devname = basprintf("pwm%uch%u", id, i + 1);
+
+ chip->ops = &atmel_pwm_ops;
+ chip->id = i;
+ ret = pwmchip_add(chip, dev);
+ if (ret) {
+ dev_err(dev, "failed to add pwm chip %d\n", ret);
return ret;
}
}
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 609765d895..c542b72796 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -206,7 +206,7 @@ static int imx_pwm_probe(struct device_d *dev)
struct resource *iores;
const struct imx_pwm_data *data;
struct imx_chip *imx;
- int ret = 0;
+ int ret;
ret = dev_get_drvdata(dev, (const void **)&data);
if (ret)
@@ -236,11 +236,7 @@ static int imx_pwm_probe(struct device_d *dev)
imx->config = data->config;
imx->set_enable = data->set_enable;
- ret = pwmchip_add(&imx->chip, dev);
- if (ret < 0)
- return ret;
-
- return 0;
+ return pwmchip_add(&imx->chip, dev);;
}
static struct driver_d imx_pwm_driver = {
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 38a47b7bc2..56abe3896e 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -55,6 +55,7 @@ config REGULATOR_ANATOP
regulators. It is recommended that this option be
enabled on i.MX6 platform.
+
config REGULATOR_ARM_SCMI
tristate "SCMI based regulator driver"
depends on ARM_SCMI_PROTOCOL && OFDEVICE
@@ -64,4 +65,14 @@ config REGULATOR_ARM_SCMI
This driver uses SCMI Message Protocol driver to interact with the
firmware providing the device Voltage functionality.
+config REGULATOR_RK808
+ tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power regulators"
+ depends on MFD_RK808
+ help
+ Select this option to enable the power regulator of ROCKCHIP
+ PMIC RK805,RK809&RK817,RK808 and RK818.
+ This driver supports the control of different power rails of device
+ through regulator interface. The device supports multiple DCDC/LDO
+ outputs which can be controlled by i2c communication.
+
endif
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 5eaa657ad1..95e42719d1 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
obj-$(CONFIG_REGULATOR_STM32_PWR) += stm32-pwr.o
obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
obj-$(CONFIG_REGULATOR_ARM_SCMI) += scmi-regulator.o
+obj-$(CONFIG_REGULATOR_RK808) += rk808-regulator.o
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index af8a0cb4fc..4876f0f44b 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -9,6 +9,7 @@
#include <of.h>
#include <malloc.h>
#include <linux/err.h>
+#include <deep-probe.h>
static LIST_HEAD(regulator_list);
@@ -42,6 +43,7 @@ static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV,
static int regulator_enable_internal(struct regulator_internal *ri)
{
+ struct regulator_dev *rdev = ri->rdev;
int ret;
if (ri->enable_count) {
@@ -49,13 +51,20 @@ static int regulator_enable_internal(struct regulator_internal *ri)
return 0;
}
- if (!ri->rdev->desc->ops->enable)
+ if (!rdev->desc->ops->enable)
return -ENOSYS;
- ret = ri->rdev->desc->ops->enable(ri->rdev);
+ /* turn on parent regulator */
+ ret = regulator_enable(rdev->supply);
if (ret)
return ret;
+ ret = rdev->desc->ops->enable(ri->rdev);
+ if (ret) {
+ regulator_disable(rdev->supply);
+ return ret;
+ }
+
if (ri->enable_time_us)
udelay(ri->enable_time_us);
@@ -66,6 +75,7 @@ static int regulator_enable_internal(struct regulator_internal *ri)
static int regulator_disable_internal(struct regulator_internal *ri)
{
+ struct regulator_dev *rdev = ri->rdev;
int ret;
if (!ri->enable_count)
@@ -76,16 +86,20 @@ static int regulator_disable_internal(struct regulator_internal *ri)
return 0;
}
- if (!ri->rdev->desc->ops->disable)
+ /* Crisis averted, be loud about the unbalanced regulator use */
+ if (WARN_ON(rdev->always_on))
+ return -EPERM;
+
+ if (!rdev->desc->ops->disable)
return -ENOSYS;
- ret = ri->rdev->desc->ops->disable(ri->rdev);
+ ret = rdev->desc->ops->disable(rdev);
if (ret)
return ret;
ri->enable_count--;
- return 0;
+ return regulator_disable(ri->rdev->supply);
}
static int regulator_set_voltage_internal(struct regulator_internal *ri,
@@ -115,6 +129,41 @@ static int regulator_set_voltage_internal(struct regulator_internal *ri,
return -ENOSYS;
}
+static int regulator_resolve_supply(struct regulator_dev *rdev)
+{
+ struct regulator *supply;
+ const char *supply_name;
+
+ if (!rdev || rdev->supply)
+ return 0;
+
+ supply_name = rdev->desc->supply_name;
+ if (!supply_name)
+ return 0;
+
+ supply = regulator_get(rdev->dev, supply_name);
+ if (IS_ERR(supply)) {
+ if (deep_probe_is_supported())
+ return PTR_ERR(supply);
+
+ /* For historic reasons, some regulator consumers don't handle
+ * -EPROBE_DEFER (e.g. vmmc-supply). If we now start propagating
+ * parent EPROBE_DEFER, previously requested vmmc-supply with
+ * always-on parent that worked before will end up not being
+ * requested breaking MMC use. So for non-deep probe systems,
+ * just make best effort to resolve, but don't fail the get if
+ * we couldn't. If you want to get rid of this warning, consider
+ * migrating your platform to have deep probe support.
+ */
+ dev_warn(rdev->dev, "Failed to get '%s' regulator (ignored).\n",
+ supply_name);
+ return 0;
+ }
+
+ rdev->supply = supply;
+ return 0;
+}
+
static struct regulator_internal * __regulator_register(struct regulator_dev *rd, const char *name)
{
struct regulator_internal *ri;
@@ -131,6 +180,10 @@ static struct regulator_internal * __regulator_register(struct regulator_dev *rd
ri->name = xstrdup(name);
if (rd->boot_on || rd->always_on) {
+ ret = regulator_resolve_supply(ri->rdev);
+ if (ret < 0)
+ goto err;
+
ret = regulator_enable_internal(ri);
if (ret && ret != -ENOSYS)
goto err;
@@ -333,6 +386,7 @@ struct regulator *regulator_get(struct device_d *dev, const char *supply)
{
struct regulator_internal *ri = NULL;
struct regulator *r;
+ int ret;
if (dev->device_node) {
ri = of_regulator_get(dev, supply);
@@ -349,6 +403,10 @@ struct regulator *regulator_get(struct device_d *dev, const char *supply)
if (!ri)
return NULL;
+ ret = regulator_resolve_supply(ri->rdev);
+ if (ret < 0)
+ return ERR_PTR(ret);
+
r = xzalloc(sizeof(*r));
r->ri = ri;
r->dev = dev;
@@ -569,9 +627,16 @@ EXPORT_SYMBOL_GPL(regulator_bulk_free);
int regulator_get_voltage(struct regulator *regulator)
{
- struct regulator_dev *rdev = regulator->ri->rdev;
+ struct regulator_internal *ri;
+ struct regulator_dev *rdev;
int sel, ret;
+ if (!regulator)
+ return -EINVAL;
+
+ ri = regulator->ri;
+ rdev = ri->rdev;
+
if (rdev->desc->ops->get_voltage_sel) {
sel = rdev->desc->ops->get_voltage_sel(rdev);
if (sel < 0)
@@ -583,6 +648,10 @@ int regulator_get_voltage(struct regulator *regulator)
ret = rdev->desc->ops->list_voltage(rdev, 0);
} else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) {
ret = rdev->desc->fixed_uV;
+ } else if (ri->min_uv && ri->min_uv == ri->max_uv) {
+ ret = ri->min_uv;
+ } else if (rdev->supply) {
+ ret = regulator_get_voltage(rdev->supply);
} else {
return -EINVAL;
}
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index ae16df8a0c..bdb01c0a95 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -15,7 +15,6 @@
struct regulator_fixed {
int gpio;
- int always_on;
struct regulator_dev rdev;
struct regulator_desc rdesc;
};
@@ -34,9 +33,6 @@ static int regulator_fixed_disable(struct regulator_dev *rdev)
{
struct regulator_fixed *fix = container_of(rdev, struct regulator_fixed, rdev);
- if (fix->always_on)
- return 0;
-
if (!gpio_is_valid(fix->gpio))
return 0;
@@ -76,15 +72,12 @@ static int regulator_fixed_probe(struct device_d *dev)
if (!of_property_read_u32(np, "off-on-delay-us", &delay))
fix->rdesc.off_on_delay = delay;
- if (of_find_property(np, "regulator-always-on", NULL) ||
- of_find_property(np, "regulator-boot-on", NULL)) {
- fix->always_on = 1;
- regulator_fixed_enable(&fix->rdev);
- }
+ if (of_find_property(np, "vin-supply", NULL))
+ fix->rdesc.supply_name = "vin";
ret = of_regulator_register(&fix->rdev, np);
if (ret)
- return ret;
+ goto err;
return 0;
err:
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
new file mode 100644
index 0000000000..39eadbd3eb
--- /dev/null
+++ b/drivers/regulator/rk808-regulator.c
@@ -0,0 +1,963 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Regulator driver for Rockchip RK808
+ *
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * Author: Chris Zhong <zyw@rock-chips.com>
+ * Author: Zhang Qing <zhangqing@rock-chips.com>
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <gpio.h>
+#include <init.h>
+#include <i2c/i2c.h>
+#include <of_device.h>
+#include <regmap.h>
+#include <linux/regulator/of_regulator.h>
+#include <regulator.h>
+#include <linux/mfd/rk808.h>
+
+/* Field Definitions */
+#define RK808_BUCK_VSEL_MASK 0x3f
+#define RK808_BUCK4_VSEL_MASK 0xf
+#define RK808_LDO_VSEL_MASK 0x1f
+
+#define RK809_BUCK5_VSEL_MASK 0x7
+
+#define RK817_LDO_VSEL_MASK 0x7f
+#define RK817_BOOST_VSEL_MASK 0x7
+#define RK817_BUCK_VSEL_MASK 0x7f
+
+#define RK818_BUCK_VSEL_MASK 0x3f
+#define RK818_BUCK4_VSEL_MASK 0x1f
+#define RK818_LDO_VSEL_MASK 0x1f
+#define RK818_LDO3_ON_VSEL_MASK 0xf
+#define RK818_BOOST_ON_VSEL_MASK 0xe0
+
+#define ENABLE_MASK(id) (BIT(id) | BIT(4 + (id)))
+#define DISABLE_VAL(id) (BIT(4 + (id)))
+
+#define RK817_BOOST_DESC(_supply_name, _min, _max, _step, _vreg,\
+ _vmask, _ereg, _emask, _enval, _disval, _etime) \
+ {{ \
+ .supply_name = (_supply_name), \
+ .n_voltages = (((_max) - (_min)) / (_step) + 1), \
+ .min_uV = (_min) * 1000, \
+ .uV_step = (_step) * 1000, \
+ .vsel_reg = (_vreg), \
+ .vsel_mask = (_vmask), \
+ .enable_reg = (_ereg), \
+ .enable_mask = (_emask), \
+ .enable_val = (_enval), \
+ .disable_val = (_disval), \
+ .off_on_delay = (_etime), \
+ .ops = &rk817_boost_ops, \
+ }}
+
+#define RK8XX_DESC_COM(_supply_name, _min, _max, _step, _vreg, \
+ _vmask, _ereg, _emask, _enval, _disval, _etime, _ops) \
+ {{ \
+ .supply_name = (_supply_name), \
+ .n_voltages = (((_max) - (_min)) / (_step) + 1), \
+ .min_uV = (_min) * 1000, \
+ .uV_step = (_step) * 1000, \
+ .vsel_reg = (_vreg), \
+ .vsel_mask = (_vmask), \
+ .enable_reg = (_ereg), \
+ .enable_mask = (_emask), \
+ .enable_val = (_enval), \
+ .disable_val = (_disval), \
+ .off_on_delay = (_etime), \
+ .ops = _ops, \
+ }}
+
+#define RK805_DESC(_supply_name, _min, _max, _step, _vreg, \
+ _vmask, _ereg, _emask, _etime) \
+ RK8XX_DESC_COM(_supply_name, _min, _max, _step, _vreg, \
+ _vmask, _ereg, _emask, 0, 0, _etime, &rk808_reg_ops)
+
+#define RK8XX_DESC(_supply_name, _min, _max, _step, _vreg, \
+ _vmask, _ereg, _emask, _etime) \
+ RK8XX_DESC_COM(_supply_name, _min, _max, _step, _vreg, \
+ _vmask, _ereg, _emask, 0, 0, _etime, &rk808_reg_ops)
+
+#define RK817_DESC(_supply_name, _min, _max, _step, _vreg, \
+ _vmask, _ereg, _emask, _disval, _etime) \
+ RK8XX_DESC_COM(_supply_name, _min, _max, _step, _vreg, \
+ _vmask, _ereg, _emask, _emask, _disval, _etime, &rk817_reg_ops)
+
+#define RKXX_DESC_SWITCH_COM(_supply_name,_ereg, _emask, \
+ _enval, _disval, _ops) \
+ {{ \
+ .supply_name = (_supply_name), \
+ .enable_reg = (_ereg), \
+ .enable_mask = (_emask), \
+ .enable_val = (_enval), \
+ .disable_val = (_disval), \
+ .ops = _ops \
+ }}
+
+#define RK817_DESC_SWITCH(_supply_name, _ereg, _emask, \
+ _disval) \
+ RKXX_DESC_SWITCH_COM(_supply_name, _ereg, _emask, \
+ _emask, _disval, &rk817_switch_ops)
+
+#define RK8XX_DESC_SWITCH(_supply_name, _ereg, _emask) \
+ RKXX_DESC_SWITCH_COM(_supply_name, _ereg, _emask, \
+ 0, 0, &rk808_switch_ops)
+
+static const struct regulator_linear_range rk808_ldo3_voltage_ranges[] = {
+ REGULATOR_LINEAR_RANGE(800000, 0, 13, 100000),
+ REGULATOR_LINEAR_RANGE(2500000, 15, 15, 0),
+};
+
+#define RK809_BUCK5_SEL_CNT (8)
+
+static const struct regulator_linear_range rk809_buck5_voltage_ranges[] = {
+ REGULATOR_LINEAR_RANGE(1500000, 0, 0, 0),
+ REGULATOR_LINEAR_RANGE(1800000, 1, 3, 200000),
+ REGULATOR_LINEAR_RANGE(2800000, 4, 5, 200000),
+ REGULATOR_LINEAR_RANGE(3300000, 6, 7, 300000),
+};
+
+#define RK817_BUCK1_MIN0 500000
+#define RK817_BUCK1_MAX0 1500000
+
+#define RK817_BUCK1_MIN1 1600000
+#define RK817_BUCK1_MAX1 2400000
+
+#define RK817_BUCK3_MAX1 3400000
+
+#define RK817_BUCK1_STP0 12500
+#define RK817_BUCK1_STP1 100000
+
+#define RK817_BUCK1_SEL0 ((RK817_BUCK1_MAX0 - RK817_BUCK1_MIN0) /\
+ RK817_BUCK1_STP0)
+#define RK817_BUCK1_SEL1 ((RK817_BUCK1_MAX1 - RK817_BUCK1_MIN1) /\
+ RK817_BUCK1_STP1)
+
+#define RK817_BUCK3_SEL1 ((RK817_BUCK3_MAX1 - RK817_BUCK1_MIN1) /\
+ RK817_BUCK1_STP1)
+
+#define RK817_BUCK1_SEL_CNT (RK817_BUCK1_SEL0 + RK817_BUCK1_SEL1 + 1)
+#define RK817_BUCK3_SEL_CNT (RK817_BUCK1_SEL0 + RK817_BUCK3_SEL1 + 1)
+
+static const struct regulator_linear_range rk817_buck1_voltage_ranges[] = {
+ REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN0, 0,
+ RK817_BUCK1_SEL0, RK817_BUCK1_STP0),
+ REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN1, RK817_BUCK1_SEL0 + 1,
+ RK817_BUCK1_SEL_CNT, RK817_BUCK1_STP1),
+};
+
+static const struct regulator_linear_range rk817_buck3_voltage_ranges[] = {
+ REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN0, 0,
+ RK817_BUCK1_SEL0, RK817_BUCK1_STP0),
+ REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN1, RK817_BUCK1_SEL0 + 1,
+ RK817_BUCK3_SEL_CNT, RK817_BUCK1_STP1),
+};
+
+struct rk_regulator_cfg {
+ struct regulator_desc desc;
+ struct regulator_dev rdev;
+};
+
+static int rk8xx_is_enabled_wmsk_regmap(struct regulator_dev *rdev)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
+ if (ret != 0)
+ return ret;
+
+ /* add write mask bit */
+ val |= (rdev->desc->enable_mask & 0xf0);
+ val &= rdev->desc->enable_mask;
+
+ if (rdev->desc->enable_is_inverted) {
+ if (rdev->desc->enable_val)
+ return val != rdev->desc->enable_val;
+ return (val == 0);
+ }
+ if (rdev->desc->enable_val)
+ return val == rdev->desc->enable_val;
+ return val != 0;
+}
+
+static struct regulator_ops rk808_buck1_2_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
+static struct regulator_ops rk808_reg_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
+static struct regulator_ops rk808_reg_ops_ranges = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
+static struct regulator_ops rk808_switch_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
+static const struct regulator_linear_range rk805_buck_1_2_voltage_ranges[] = {
+ REGULATOR_LINEAR_RANGE(712500, 0, 59, 12500),
+ REGULATOR_LINEAR_RANGE(1800000, 60, 62, 200000),
+ REGULATOR_LINEAR_RANGE(2300000, 63, 63, 0),
+};
+
+static const struct regulator_ops rk809_buck5_ops_range = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = rk8xx_is_enabled_wmsk_regmap,
+};
+
+static const struct regulator_ops rk817_reg_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = rk8xx_is_enabled_wmsk_regmap,
+};
+
+static const struct regulator_ops rk817_boost_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = rk8xx_is_enabled_wmsk_regmap,
+};
+
+static const struct regulator_ops rk817_buck_ops_range = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = rk8xx_is_enabled_wmsk_regmap,
+};
+
+static const struct regulator_ops rk817_switch_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = rk8xx_is_enabled_wmsk_regmap,
+};
+
+static struct rk_regulator_cfg rk805_reg[] = {
+ {{
+ /* .name = "DCDC_REG1", */
+ .supply_name = "vcc1",
+ .ops = &rk808_reg_ops_ranges,
+ .n_voltages = 64,
+ .linear_ranges = rk805_buck_1_2_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk805_buck_1_2_voltage_ranges),
+ .vsel_reg = RK805_BUCK1_ON_VSEL_REG,
+ .vsel_mask = RK818_BUCK_VSEL_MASK,
+ .enable_reg = RK805_DCDC_EN_REG,
+ .enable_mask = BIT(0),
+ }}, {{
+ /* .name = "DCDC_REG2", */
+ .supply_name = "vcc2",
+ .ops = &rk808_reg_ops_ranges,
+ .n_voltages = 64,
+ .linear_ranges = rk805_buck_1_2_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk805_buck_1_2_voltage_ranges),
+ .vsel_reg = RK805_BUCK2_ON_VSEL_REG,
+ .vsel_mask = RK818_BUCK_VSEL_MASK,
+ .enable_reg = RK805_DCDC_EN_REG,
+ .enable_mask = BIT(1),
+ }}, {{
+ /* .name = "DCDC_REG3", */
+ .supply_name = "vcc3",
+ .ops = &rk808_switch_ops,
+ .n_voltages = 1,
+ .enable_reg = RK805_DCDC_EN_REG,
+ .enable_mask = BIT(2),
+ }},
+
+ RK805_DESC(/* "DCDC_REG4", */ "vcc4", 800, 3400, 100,
+ RK805_BUCK4_ON_VSEL_REG, RK818_BUCK4_VSEL_MASK,
+ RK805_DCDC_EN_REG, BIT(3), 0),
+
+ RK805_DESC(/* "LDO_REG1", */ "vcc5", 800, 3400, 100,
+ RK805_LDO1_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK805_LDO_EN_REG,
+ BIT(0), 400),
+ RK805_DESC(/* "LDO_REG2", */ "vcc5", 800, 3400, 100,
+ RK805_LDO2_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK805_LDO_EN_REG,
+ BIT(1), 400),
+ RK805_DESC(/* "LDO_REG3", */ "vcc6", 800, 3400, 100,
+ RK805_LDO3_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK805_LDO_EN_REG,
+ BIT(2), 400),
+};
+static_assert(ARRAY_SIZE(rk805_reg) == RK805_NUM_REGULATORS);
+
+static struct rk_regulator_cfg rk808_reg[] = {
+ {{
+ /* .name = "DCDC_REG1", */
+ .supply_name = "vcc1",
+ .ops = &rk808_buck1_2_ops,
+ .min_uV = 712500,
+ .uV_step = 12500,
+ .n_voltages = 64,
+ .vsel_reg = RK808_BUCK1_ON_VSEL_REG,
+ .vsel_mask = RK808_BUCK_VSEL_MASK,
+ .enable_reg = RK808_DCDC_EN_REG,
+ .enable_mask = BIT(0),
+ }}, {{
+ /* .name = "DCDC_REG2", */
+ .supply_name = "vcc2",
+ .ops = &rk808_buck1_2_ops,
+ .min_uV = 712500,
+ .uV_step = 12500,
+ .n_voltages = 64,
+ .vsel_reg = RK808_BUCK2_ON_VSEL_REG,
+ .vsel_mask = RK808_BUCK_VSEL_MASK,
+ .enable_reg = RK808_DCDC_EN_REG,
+ .enable_mask = BIT(1),
+ }}, {{
+ /* .name = "DCDC_REG3", */
+ .supply_name = "vcc3",
+ .ops = &rk808_switch_ops,
+ .n_voltages = 1,
+ .enable_reg = RK808_DCDC_EN_REG,
+ .enable_mask = BIT(2),
+ }}, {{
+ /* .name = "DCDC_REG4", */
+ .supply_name = "vcc4",
+ .ops = &rk808_reg_ops,
+ .min_uV = 1800000,
+ .uV_step = 100000,
+ .n_voltages = 16,
+ .vsel_reg = RK808_BUCK4_ON_VSEL_REG,
+ .vsel_mask = RK808_BUCK4_VSEL_MASK,
+ .enable_reg = RK808_DCDC_EN_REG,
+ .enable_mask = BIT(3),
+ }}, {{
+ /* .name = "LDO_REG1", */
+ .supply_name = "vcc6",
+ .ops = &rk808_reg_ops,
+ .min_uV = 1800000,
+ .uV_step = 100000,
+ .n_voltages = 17,
+ .vsel_reg = RK808_LDO1_ON_VSEL_REG,
+ .vsel_mask = RK808_LDO_VSEL_MASK,
+ .enable_reg = RK808_LDO_EN_REG,
+ .enable_mask = BIT(0),
+ .off_on_delay = 400,
+ }}, {{
+ /* .name = "LDO_REG2", */
+ .supply_name = "vcc6",
+ .ops = &rk808_reg_ops,
+ .min_uV = 1800000,
+ .uV_step = 100000,
+ .n_voltages = 17,
+ .vsel_reg = RK808_LDO2_ON_VSEL_REG,
+ .vsel_mask = RK808_LDO_VSEL_MASK,
+ .enable_reg = RK808_LDO_EN_REG,
+ .enable_mask = BIT(1),
+ .off_on_delay = 400,
+ }}, {{
+ /* .name = "LDO_REG3", */
+ .supply_name = "vcc7",
+ .ops = &rk808_reg_ops_ranges,
+ .n_voltages = 16,
+ .linear_ranges = rk808_ldo3_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk808_ldo3_voltage_ranges),
+ .vsel_reg = RK808_LDO3_ON_VSEL_REG,
+ .vsel_mask = RK808_BUCK4_VSEL_MASK,
+ .enable_reg = RK808_LDO_EN_REG,
+ .enable_mask = BIT(2),
+ .off_on_delay = 400,
+ }}, {{
+ /* .name = "LDO_REG4", */
+ .supply_name = "vcc9",
+ .ops = &rk808_reg_ops,
+ .min_uV = 1800000,
+ .uV_step = 100000,
+ .n_voltages = 17,
+ .vsel_reg = RK808_LDO4_ON_VSEL_REG,
+ .vsel_mask = RK808_LDO_VSEL_MASK,
+ .enable_reg = RK808_LDO_EN_REG,
+ .enable_mask = BIT(3),
+ .off_on_delay = 400,
+ }}, {{
+ /* .name = "LDO_REG5", */
+ .supply_name = "vcc9",
+ .ops = &rk808_reg_ops,
+ .min_uV = 1800000,
+ .uV_step = 100000,
+ .n_voltages = 17,
+ .vsel_reg = RK808_LDO5_ON_VSEL_REG,
+ .vsel_mask = RK808_LDO_VSEL_MASK,
+ .enable_reg = RK808_LDO_EN_REG,
+ .enable_mask = BIT(4),
+ .off_on_delay = 400,
+ }}, {{
+ /* .name = "LDO_REG6", */
+ .supply_name = "vcc10",
+ .ops = &rk808_reg_ops,
+ .min_uV = 800000,
+ .uV_step = 100000,
+ .n_voltages = 18,
+ .vsel_reg = RK808_LDO6_ON_VSEL_REG,
+ .vsel_mask = RK808_LDO_VSEL_MASK,
+ .enable_reg = RK808_LDO_EN_REG,
+ .enable_mask = BIT(5),
+ .off_on_delay = 400,
+ }}, {{
+ /* .name = "LDO_REG7", */
+ .supply_name = "vcc7",
+ .ops = &rk808_reg_ops,
+ .min_uV = 800000,
+ .uV_step = 100000,
+ .n_voltages = 18,
+ .vsel_reg = RK808_LDO7_ON_VSEL_REG,
+ .vsel_mask = RK808_LDO_VSEL_MASK,
+ .enable_reg = RK808_LDO_EN_REG,
+ .enable_mask = BIT(6),
+ .off_on_delay = 400,
+ }}, {{
+ /* .name = "LDO_REG8", */
+ .supply_name = "vcc11",
+ .ops = &rk808_reg_ops,
+ .min_uV = 1800000,
+ .uV_step = 100000,
+ .n_voltages = 17,
+ .vsel_reg = RK808_LDO8_ON_VSEL_REG,
+ .vsel_mask = RK808_LDO_VSEL_MASK,
+ .enable_reg = RK808_LDO_EN_REG,
+ .enable_mask = BIT(7),
+ .off_on_delay = 400,
+ }}, {{
+ /* .name = "SWITCH_REG1", */
+ .supply_name = "vcc8",
+ .ops = &rk808_switch_ops,
+ .enable_reg = RK808_DCDC_EN_REG,
+ .enable_mask = BIT(5),
+ }}, {{
+ /* .name = "SWITCH_REG2", */
+ .supply_name = "vcc12",
+ .ops = &rk808_switch_ops,
+ .enable_reg = RK808_DCDC_EN_REG,
+ .enable_mask = BIT(6),
+ }},
+};
+static_assert(ARRAY_SIZE(rk808_reg) == RK808_NUM_REGULATORS);
+
+static struct rk_regulator_cfg rk809_reg[] = {
+ {{
+ /* .name = "DCDC_REG1", */
+ .supply_name = "vcc1",
+ .ops = &rk817_buck_ops_range,
+ .n_voltages = RK817_BUCK1_SEL_CNT + 1,
+ .linear_ranges = rk817_buck1_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges),
+ .vsel_reg = RK817_BUCK1_ON_VSEL_REG,
+ .vsel_mask = RK817_BUCK_VSEL_MASK,
+ .enable_reg = RK817_POWER_EN_REG(0),
+ .enable_mask = ENABLE_MASK(RK817_ID_DCDC1),
+ .enable_val = ENABLE_MASK(RK817_ID_DCDC1),
+ .disable_val = DISABLE_VAL(RK817_ID_DCDC1),
+ }}, {{
+ /* .name = "DCDC_REG2", */
+ .supply_name = "vcc2",
+ .ops = &rk817_buck_ops_range,
+ .n_voltages = RK817_BUCK1_SEL_CNT + 1,
+ .linear_ranges = rk817_buck1_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges),
+ .vsel_reg = RK817_BUCK2_ON_VSEL_REG,
+ .vsel_mask = RK817_BUCK_VSEL_MASK,
+ .enable_reg = RK817_POWER_EN_REG(0),
+ .enable_mask = ENABLE_MASK(RK817_ID_DCDC2),
+ .enable_val = ENABLE_MASK(RK817_ID_DCDC2),
+ .disable_val = DISABLE_VAL(RK817_ID_DCDC2),
+ }}, {{
+ /* .name = "DCDC_REG3", */
+ .supply_name = "vcc3",
+ .ops = &rk817_buck_ops_range,
+ .n_voltages = RK817_BUCK1_SEL_CNT + 1,
+ .linear_ranges = rk817_buck1_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges),
+ .vsel_reg = RK817_BUCK3_ON_VSEL_REG,
+ .vsel_mask = RK817_BUCK_VSEL_MASK,
+ .enable_reg = RK817_POWER_EN_REG(0),
+ .enable_mask = ENABLE_MASK(RK817_ID_DCDC3),
+ .enable_val = ENABLE_MASK(RK817_ID_DCDC3),
+ .disable_val = DISABLE_VAL(RK817_ID_DCDC3),
+ }}, {{
+ /* .name = "DCDC_REG4", */
+ .supply_name = "vcc4",
+ .ops = &rk817_buck_ops_range,
+ .n_voltages = RK817_BUCK3_SEL_CNT + 1,
+ .linear_ranges = rk817_buck3_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk817_buck3_voltage_ranges),
+ .vsel_reg = RK817_BUCK4_ON_VSEL_REG,
+ .vsel_mask = RK817_BUCK_VSEL_MASK,
+ .enable_reg = RK817_POWER_EN_REG(0),
+ .enable_mask = ENABLE_MASK(RK817_ID_DCDC4),
+ .enable_val = ENABLE_MASK(RK817_ID_DCDC4),
+ .disable_val = DISABLE_VAL(RK817_ID_DCDC4),
+ }}, {{
+ /* .name = "DCDC_REG5", */
+ .supply_name = "vcc9",
+ .ops = &rk809_buck5_ops_range,
+ .n_voltages = RK809_BUCK5_SEL_CNT,
+ .linear_ranges = rk809_buck5_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk809_buck5_voltage_ranges),
+ .vsel_reg = RK809_BUCK5_CONFIG(0),
+ .vsel_mask = RK809_BUCK5_VSEL_MASK,
+ .enable_reg = RK817_POWER_EN_REG(3),
+ .enable_mask = ENABLE_MASK(1),
+ .enable_val = ENABLE_MASK(1),
+ .disable_val = DISABLE_VAL(1),
+ }},
+ RK817_DESC(/* "LDO_REG1", */ "vcc5", 600, 3400, 25,
+ RK817_LDO_ON_VSEL_REG(0), RK817_LDO_VSEL_MASK,
+ RK817_POWER_EN_REG(1), ENABLE_MASK(0),
+ DISABLE_VAL(0), 400),
+ RK817_DESC(/* "LDO_REG2", */ "vcc5", 600, 3400, 25,
+ RK817_LDO_ON_VSEL_REG(1), RK817_LDO_VSEL_MASK,
+ RK817_POWER_EN_REG(1), ENABLE_MASK(1),
+ DISABLE_VAL(1), 400),
+ RK817_DESC(/* "LDO_REG3", */ "vcc5", 600, 3400, 25,
+ RK817_LDO_ON_VSEL_REG(2), RK817_LDO_VSEL_MASK,
+ RK817_POWER_EN_REG(1), ENABLE_MASK(2),
+ DISABLE_VAL(2), 400),
+ RK817_DESC(/* "LDO_REG4", */ "vcc6", 600, 3400, 25,
+ RK817_LDO_ON_VSEL_REG(3), RK817_LDO_VSEL_MASK,
+ RK817_POWER_EN_REG(1), ENABLE_MASK(3),
+ DISABLE_VAL(3), 400),
+ RK817_DESC(/* "LDO_REG5", */ "vcc6", 600, 3400, 25,
+ RK817_LDO_ON_VSEL_REG(4), RK817_LDO_VSEL_MASK,
+ RK817_POWER_EN_REG(2), ENABLE_MASK(0),
+ DISABLE_VAL(0), 400),
+ RK817_DESC(/* "LDO_REG6", */ "vcc6", 600, 3400, 25,
+ RK817_LDO_ON_VSEL_REG(5), RK817_LDO_VSEL_MASK,
+ RK817_POWER_EN_REG(2), ENABLE_MASK(1),
+ DISABLE_VAL(1), 400),
+ RK817_DESC(/* "LDO_REG7", */ "vcc7", 600, 3400, 25,
+ RK817_LDO_ON_VSEL_REG(6), RK817_LDO_VSEL_MASK,
+ RK817_POWER_EN_REG(2), ENABLE_MASK(2),
+ DISABLE_VAL(2), 400),
+ RK817_DESC(/* "LDO_REG8", */ "vcc7", 600, 3400, 25,
+ RK817_LDO_ON_VSEL_REG(7), RK817_LDO_VSEL_MASK,
+ RK817_POWER_EN_REG(2), ENABLE_MASK(3),
+ DISABLE_VAL(3), 400),
+ RK817_DESC(/* "LDO_REG9", */ "vcc7", 600, 3400, 25,
+ RK817_LDO_ON_VSEL_REG(8), RK817_LDO_VSEL_MASK,
+ RK817_POWER_EN_REG(3), ENABLE_MASK(0),
+ DISABLE_VAL(0), 400),
+ RK817_DESC_SWITCH(/* "SWITCH_REG1", */ "vcc9",
+ RK817_POWER_EN_REG(3), ENABLE_MASK(2), DISABLE_VAL(2)),
+ RK817_DESC_SWITCH(/* "SWITCH_REG2", */ "vcc8",
+ RK817_POWER_EN_REG(3), ENABLE_MASK(3), DISABLE_VAL(3)),
+};
+static_assert(ARRAY_SIZE(rk809_reg) == RK809_NUM_REGULATORS);
+
+static struct rk_regulator_cfg rk817_reg[] = {
+ {{
+ /* .name = "DCDC_REG1", */
+ .supply_name = "vcc1",
+ .ops = &rk817_buck_ops_range,
+ .n_voltages = RK817_BUCK1_SEL_CNT + 1,
+ .linear_ranges = rk817_buck1_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges),
+ .vsel_reg = RK817_BUCK1_ON_VSEL_REG,
+ .vsel_mask = RK817_BUCK_VSEL_MASK,
+ .enable_reg = RK817_POWER_EN_REG(0),
+ .enable_mask = ENABLE_MASK(RK817_ID_DCDC1),
+ .enable_val = ENABLE_MASK(RK817_ID_DCDC1),
+ .disable_val = DISABLE_VAL(RK817_ID_DCDC1),
+ }}, {{
+ /* .name = "DCDC_REG2", */
+ .supply_name = "vcc2",
+ .ops = &rk817_buck_ops_range,
+ .n_voltages = RK817_BUCK1_SEL_CNT + 1,
+ .linear_ranges = rk817_buck1_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges),
+ .vsel_reg = RK817_BUCK2_ON_VSEL_REG,
+ .vsel_mask = RK817_BUCK_VSEL_MASK,
+ .enable_reg = RK817_POWER_EN_REG(0),
+ .enable_mask = ENABLE_MASK(RK817_ID_DCDC2),
+ .enable_val = ENABLE_MASK(RK817_ID_DCDC2),
+ .disable_val = DISABLE_VAL(RK817_ID_DCDC2),
+ }}, {{
+ /* .name = "DCDC_REG3", */
+ .supply_name = "vcc3",
+ .ops = &rk817_buck_ops_range,
+ .n_voltages = RK817_BUCK1_SEL_CNT + 1,
+ .linear_ranges = rk817_buck1_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges),
+ .vsel_reg = RK817_BUCK3_ON_VSEL_REG,
+ .vsel_mask = RK817_BUCK_VSEL_MASK,
+ .enable_reg = RK817_POWER_EN_REG(0),
+ .enable_mask = ENABLE_MASK(RK817_ID_DCDC3),
+ .enable_val = ENABLE_MASK(RK817_ID_DCDC3),
+ .disable_val = DISABLE_VAL(RK817_ID_DCDC3),
+ }}, {{
+ /* .name = "DCDC_REG4", */
+ .supply_name = "vcc4",
+ .ops = &rk817_buck_ops_range,
+ .n_voltages = RK817_BUCK3_SEL_CNT + 1,
+ .linear_ranges = rk817_buck3_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk817_buck3_voltage_ranges),
+ .vsel_reg = RK817_BUCK4_ON_VSEL_REG,
+ .vsel_mask = RK817_BUCK_VSEL_MASK,
+ .enable_reg = RK817_POWER_EN_REG(0),
+ .enable_mask = ENABLE_MASK(RK817_ID_DCDC4),
+ .enable_val = ENABLE_MASK(RK817_ID_DCDC4),
+ .disable_val = DISABLE_VAL(RK817_ID_DCDC4),
+ }},
+ RK817_DESC(/* "LDO_REG1", */ "vcc5", 600, 3400, 25,
+ RK817_LDO_ON_VSEL_REG(0), RK817_LDO_VSEL_MASK,
+ RK817_POWER_EN_REG(1), ENABLE_MASK(0),
+ DISABLE_VAL(0), 400),
+ RK817_DESC(/* "LDO_REG2", */ "vcc5", 600, 3400, 25,
+ RK817_LDO_ON_VSEL_REG(1), RK817_LDO_VSEL_MASK,
+ RK817_POWER_EN_REG(1), ENABLE_MASK(1),
+ DISABLE_VAL(1), 400),
+ RK817_DESC(/* "LDO_REG3", */ "vcc5", 600, 3400, 25,
+ RK817_LDO_ON_VSEL_REG(2), RK817_LDO_VSEL_MASK,
+ RK817_POWER_EN_REG(1), ENABLE_MASK(2),
+ DISABLE_VAL(2), 400),
+ RK817_DESC(/* "LDO_REG4", */ "vcc6", 600, 3400, 25,
+ RK817_LDO_ON_VSEL_REG(3), RK817_LDO_VSEL_MASK,
+ RK817_POWER_EN_REG(1), ENABLE_MASK(3),
+ DISABLE_VAL(3), 400),
+ RK817_DESC(/* "LDO_REG5", */ "vcc6", 600, 3400, 25,
+ RK817_LDO_ON_VSEL_REG(4), RK817_LDO_VSEL_MASK,
+ RK817_POWER_EN_REG(2), ENABLE_MASK(0),
+ DISABLE_VAL(0), 400),
+ RK817_DESC(/* "LDO_REG6", */ "vcc6", 600, 3400, 25,
+ RK817_LDO_ON_VSEL_REG(5), RK817_LDO_VSEL_MASK,
+ RK817_POWER_EN_REG(2), ENABLE_MASK(1),
+ DISABLE_VAL(1), 400),
+ RK817_DESC(/* "LDO_REG7", */ "vcc7", 600, 3400, 25,
+ RK817_LDO_ON_VSEL_REG(6), RK817_LDO_VSEL_MASK,
+ RK817_POWER_EN_REG(2), ENABLE_MASK(2),
+ DISABLE_VAL(2), 400),
+ RK817_DESC(/* "LDO_REG8", */ "vcc7", 600, 3400, 25,
+ RK817_LDO_ON_VSEL_REG(7), RK817_LDO_VSEL_MASK,
+ RK817_POWER_EN_REG(2), ENABLE_MASK(3),
+ DISABLE_VAL(3), 400),
+ RK817_DESC(/* "LDO_REG9", */ "vcc7", 600, 3400, 25,
+ RK817_LDO_ON_VSEL_REG(8), RK817_LDO_VSEL_MASK,
+ RK817_POWER_EN_REG(3), ENABLE_MASK(0),
+ DISABLE_VAL(0), 400),
+ RK817_BOOST_DESC(/* "BOOST", */ "vcc8", 4700, 5400, 100,
+ RK817_BOOST_OTG_CFG, RK817_BOOST_VSEL_MASK,
+ RK817_POWER_EN_REG(3), ENABLE_MASK(1), ENABLE_MASK(1),
+ DISABLE_VAL(1), 400),
+ RK817_DESC_SWITCH(/* "OTG_SWITCH", */ "vcc9",
+ RK817_POWER_EN_REG(3), ENABLE_MASK(2), DISABLE_VAL(2)),
+};
+static_assert(ARRAY_SIZE(rk817_reg) == RK817_NUM_REGULATORS);
+
+static struct rk_regulator_cfg rk818_reg[] = {
+ {{
+ /* .name = "DCDC_REG1", */
+ .supply_name = "vcc1",
+ .ops = &rk808_reg_ops,
+ .min_uV = 712500,
+ .uV_step = 12500,
+ .n_voltages = 64,
+ .vsel_reg = RK818_BUCK1_ON_VSEL_REG,
+ .vsel_mask = RK818_BUCK_VSEL_MASK,
+ .enable_reg = RK818_DCDC_EN_REG,
+ .enable_mask = BIT(0),
+ }}, {{
+ /* .name = "DCDC_REG2", */
+ .supply_name = "vcc2",
+ .ops = &rk808_reg_ops,
+ .min_uV = 712500,
+ .uV_step = 12500,
+ .n_voltages = 64,
+ .vsel_reg = RK818_BUCK2_ON_VSEL_REG,
+ .vsel_mask = RK818_BUCK_VSEL_MASK,
+ .enable_reg = RK818_DCDC_EN_REG,
+ .enable_mask = BIT(1),
+ }}, {{
+ /* .name = "DCDC_REG3", */
+ .supply_name = "vcc3",
+ .ops = &rk808_switch_ops,
+ .n_voltages = 1,
+ .enable_reg = RK818_DCDC_EN_REG,
+ .enable_mask = BIT(2),
+ }},
+ RK8XX_DESC(/* "DCDC_REG4", */ "vcc4", 1800, 3600, 100,
+ RK818_BUCK4_ON_VSEL_REG, RK818_BUCK4_VSEL_MASK,
+ RK818_DCDC_EN_REG, BIT(3), 0),
+ RK8XX_DESC(/* "DCDC_BOOST", */ "boost", 4700, 5400, 100,
+ RK818_BOOST_LDO9_ON_VSEL_REG, RK818_BOOST_ON_VSEL_MASK,
+ RK818_DCDC_EN_REG, BIT(4), 0),
+ RK8XX_DESC(/* "LDO_REG1", */ "vcc6", 1800, 3400, 100,
+ RK818_LDO1_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
+ BIT(0), 400),
+ RK8XX_DESC(/* "LDO_REG2", */ "vcc6", 1800, 3400, 100,
+ RK818_LDO2_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
+ BIT(1), 400),
+ {{
+ /* .name = "LDO_REG3", */
+ .supply_name = "vcc7",
+ .ops = &rk808_reg_ops_ranges,
+ .n_voltages = 16,
+ .linear_ranges = rk808_ldo3_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk808_ldo3_voltage_ranges),
+ .vsel_reg = RK818_LDO3_ON_VSEL_REG,
+ .vsel_mask = RK818_LDO3_ON_VSEL_MASK,
+ .enable_reg = RK818_LDO_EN_REG,
+ .enable_mask = BIT(2),
+ .off_on_delay = 400,
+ }},
+ RK8XX_DESC(/* "LDO_REG4", */ "vcc8", 1800, 3400, 100,
+ RK818_LDO4_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
+ BIT(3), 400),
+ RK8XX_DESC(/* "LDO_REG5", */ "vcc7", 1800, 3400, 100,
+ RK818_LDO5_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
+ BIT(4), 400),
+ RK8XX_DESC(/* "LDO_REG6", */ "vcc8", 800, 2500, 100,
+ RK818_LDO6_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
+ BIT(5), 400),
+ RK8XX_DESC(/* "LDO_REG7", */ "vcc7", 800, 2500, 100,
+ RK818_LDO7_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
+ BIT(6), 400),
+ RK8XX_DESC(/* "LDO_REG8", */ "vcc8", 1800, 3400, 100,
+ RK818_LDO8_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
+ BIT(7), 400),
+ RK8XX_DESC(/* "LDO_REG9", */ "vcc9", 1800, 3400, 100,
+ RK818_BOOST_LDO9_ON_VSEL_REG, RK818_LDO_VSEL_MASK,
+ RK818_DCDC_EN_REG, BIT(5), 400),
+ RK8XX_DESC_SWITCH(/* "SWITCH_REG", */ "vcc9",
+ RK818_DCDC_EN_REG, BIT(6)),
+ RK8XX_DESC_SWITCH(/* "HDMI_SWITCH", */ "h_5v",
+ RK818_H5V_EN_REG, BIT(0)),
+ RK8XX_DESC_SWITCH(/* "OTG_SWITCH", */ "usb",
+ RK818_DCDC_EN_REG, BIT(7)),
+};
+static_assert(ARRAY_SIZE(rk818_reg) == RK818_NUM_REGULATORS);
+
+static int rk808_regulator_register(struct rk808 *rk808, int id,
+ struct of_regulator_match *match,
+ struct rk_regulator_cfg *cfg)
+{
+ struct device_d *dev = &rk808->i2c->dev;
+ int ret;
+
+ if (!match->of_node) {
+ dev_dbg(dev, "Skip missing DTB regulator %s", match->name);
+ return 0;
+ }
+
+ cfg->rdev.desc = &cfg->desc;
+ cfg->rdev.dev = dev;
+ cfg->rdev.regmap = rk808->regmap;
+
+ ret = of_regulator_register(&cfg->rdev, match->of_node);
+ if (ret) {
+ dev_err(dev, "failed to register %s regulator\n", match->name);
+ return ret;
+ }
+
+ dev_dbg(dev, "registered %s\n", match->name);
+
+ return 0;
+}
+
+#define MATCH(variant, _name, _id) [RK##variant##_ID_##_id] = \
+ { .name = #_name, .desc = &rk##variant##_reg[RK##variant##_ID_##_id].desc }
+
+static struct of_regulator_match rk805_reg_matches[] = {
+ MATCH(805, DCDC_REG1, DCDC1),
+ MATCH(805, DCDC_REG2, DCDC2),
+ MATCH(805, DCDC_REG3, DCDC3),
+ MATCH(805, DCDC_REG4, DCDC4),
+ MATCH(805, LDO_REG1, LDO1),
+ MATCH(805, LDO_REG2, LDO2),
+ MATCH(805, LDO_REG3, LDO3),
+};
+static_assert(ARRAY_SIZE(rk805_reg_matches) == RK805_NUM_REGULATORS);
+
+static struct of_regulator_match rk808_reg_matches[] = {
+ MATCH(808, DCDC_REG1, DCDC1),
+ MATCH(808, DCDC_REG2, DCDC2),
+ MATCH(808, DCDC_REG3, DCDC3),
+ MATCH(808, DCDC_REG4, DCDC4),
+ MATCH(808, LDO_REG1, LDO1),
+ MATCH(808, LDO_REG2, LDO2),
+ MATCH(808, LDO_REG3, LDO3),
+ MATCH(808, LDO_REG4, LDO4),
+ MATCH(808, LDO_REG5, LDO5),
+ MATCH(808, LDO_REG6, LDO6),
+ MATCH(808, LDO_REG7, LDO7),
+ MATCH(808, LDO_REG8, LDO8),
+ MATCH(808, SWITCH_REG1, SWITCH1),
+ MATCH(808, SWITCH_REG2, SWITCH2),
+};
+static_assert(ARRAY_SIZE(rk808_reg_matches) == RK808_NUM_REGULATORS);
+
+static struct of_regulator_match rk809_reg_matches[] = {
+ MATCH(809, DCDC_REG1, DCDC1),
+ MATCH(809, DCDC_REG2, DCDC2),
+ MATCH(809, DCDC_REG3, DCDC3),
+ MATCH(809, DCDC_REG4, DCDC4),
+ MATCH(809, LDO_REG1, LDO1),
+ MATCH(809, LDO_REG2, LDO2),
+ MATCH(809, LDO_REG3, LDO3),
+ MATCH(809, LDO_REG4, LDO4),
+ MATCH(809, LDO_REG5, LDO5),
+ MATCH(809, LDO_REG6, LDO6),
+ MATCH(809, LDO_REG7, LDO7),
+ MATCH(809, LDO_REG8, LDO8),
+ MATCH(809, LDO_REG9, LDO9),
+ MATCH(809, DCDC_REG5, DCDC5),
+ MATCH(809, SWITCH_REG1, SW1),
+ MATCH(809, SWITCH_REG2, SW2),
+};
+static_assert(ARRAY_SIZE(rk809_reg_matches) == RK809_NUM_REGULATORS);
+
+static struct of_regulator_match rk817_reg_matches[] = {
+ MATCH(817, DCDC_REG1, DCDC1),
+ MATCH(817, DCDC_REG2, DCDC2),
+ MATCH(817, DCDC_REG3, DCDC3),
+ MATCH(817, DCDC_REG4, DCDC4),
+ MATCH(817, LDO_REG1, LDO1),
+ MATCH(817, LDO_REG2, LDO2),
+ MATCH(817, LDO_REG3, LDO3),
+ MATCH(817, LDO_REG4, LDO4),
+ MATCH(817, LDO_REG5, LDO5),
+ MATCH(817, LDO_REG6, LDO6),
+ MATCH(817, LDO_REG7, LDO7),
+ MATCH(817, LDO_REG8, LDO8),
+ MATCH(817, LDO_REG9, LDO9),
+ MATCH(817, BOOST, BOOST),
+ MATCH(817, OTG_SWITCH, BOOST_OTG_SW),
+};
+static_assert(ARRAY_SIZE(rk817_reg_matches) == RK817_NUM_REGULATORS);
+
+static struct of_regulator_match rk818_reg_matches[] = {
+ MATCH(818, DCDC_REG1, DCDC1),
+ MATCH(818, DCDC_REG2, DCDC2),
+ MATCH(818, DCDC_REG3, DCDC3),
+ MATCH(818, DCDC_REG4, DCDC4),
+ MATCH(818, DCDC_BOOST, BOOST),
+ MATCH(818, LDO_REG1, LDO1),
+ MATCH(818, LDO_REG2, LDO2),
+ MATCH(818, LDO_REG3, LDO3),
+ MATCH(818, LDO_REG4, LDO4),
+ MATCH(818, LDO_REG5, LDO5),
+ MATCH(818, LDO_REG6, LDO6),
+ MATCH(818, LDO_REG7, LDO7),
+ MATCH(818, LDO_REG8, LDO8),
+ MATCH(818, LDO_REG9, LDO9),
+ MATCH(818, SWITCH_REG, SWITCH),
+ MATCH(818, HDMI_SWITCH, HDMI_SWITCH),
+ MATCH(818, OTG_SWITCH, OTG_SWITCH),
+};
+static_assert(ARRAY_SIZE(rk818_reg_matches) == RK818_NUM_REGULATORS);
+
+static int rk808_regulator_dt_parse(struct device_d *dev,
+ struct of_regulator_match *matches,
+ int nregulators)
+{
+ struct device_node *np = dev->device_node;
+
+ np = of_get_child_by_name(np, "regulators");
+ if (!np)
+ return -ENOENT;
+
+ return of_regulator_match(dev, np, matches, nregulators);
+}
+
+static int rk808_regulator_probe(struct device_d *dev)
+{
+ struct rk808 *rk808 = dev->parent->priv;
+ struct rk_regulator_cfg *regulators;
+ struct of_regulator_match *matches;
+ int ret, i, nregulators;
+
+ switch (rk808->variant) {
+ case RK805_ID:
+ regulators = rk805_reg;
+ matches = rk805_reg_matches;
+ nregulators = RK805_NUM_REGULATORS;
+ break;
+ case RK808_ID:
+ regulators = rk808_reg;
+ matches = rk808_reg_matches;
+ nregulators = RK809_NUM_REGULATORS;
+ break;
+ case RK809_ID:
+ regulators = rk809_reg;
+ matches = rk809_reg_matches;
+ nregulators = RK809_NUM_REGULATORS;
+ break;
+ case RK817_ID:
+ regulators = rk817_reg;
+ matches = rk817_reg_matches;
+ nregulators = RK817_NUM_REGULATORS;
+ break;
+ case RK818_ID:
+ regulators = rk818_reg;
+ matches = rk818_reg_matches;
+ nregulators = RK818_NUM_REGULATORS;
+ break;
+ default:
+ dev_err(dev, "unsupported RK8XX ID %lu\n", rk808->variant);
+ return -EINVAL;
+ }
+
+ ret = rk808_regulator_dt_parse(&rk808->i2c->dev, matches, nregulators);
+ if (ret < 0)
+ return ret;
+
+ /* Instantiate the regulators */
+ for (i = 0; i < nregulators; i++) {
+ ret = rk808_regulator_register(rk808, i, &matches[i],
+ &regulators[i]);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct driver_d rk808_regulator_driver = {
+ .name = "rk808-regulator",
+ .probe = rk808_regulator_probe,
+};
+device_platform_driver(rk808_regulator_driver);
+
+MODULE_DESCRIPTION("regulator driver for the rk808 series PMICs");
+MODULE_AUTHOR("Chris Zhong<zyw@rock-chips.com>");
+MODULE_AUTHOR("Zhang Qing<zhangqing@rock-chips.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:rk808-regulator");
diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index 4355c3415e..b252f94d6e 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -157,14 +157,14 @@ int reset_control_deassert(struct reset_control *rstc)
EXPORT_SYMBOL_GPL(reset_control_deassert);
/**
- * of_reset_control_count - Count reset lines
- * @node: device node
+ * reset_control_get_count - Count reset lines
+ * @dev: device
*
* Returns number of resets, 0 if none specified
*/
-static int of_reset_control_count(struct device_node *node)
+int reset_control_get_count(struct device_d *dev)
{
- return of_count_phandle_with_args(node, "resets", "#reset-cells");
+ return of_count_phandle_with_args(dev->device_node, "resets", "#reset-cells");
}
/**
@@ -236,8 +236,11 @@ struct reset_control *of_reset_control_get(struct device_node *node,
{
int index = 0;
- if (id)
+ if (id) {
index = of_property_match_string(node, "reset-names", id);
+ if (index < 0)
+ return ERR_PTR(-ENOENT);
+ }
return of_reset_control_get_by_index(node, index);
}
@@ -354,7 +357,7 @@ int device_reset_all(struct device_d *dev)
struct reset_control *rstc;
int ret, i;
- for (i = 0; i < of_reset_control_count(dev->device_node); i++) {
+ for (i = 0; i < reset_control_get_count(dev); i++) {
int ret;
rstc = of_reset_control_get_by_index(dev->device_node, i);
diff --git a/drivers/rtc/rtc-abracon.c b/drivers/rtc/rtc-abracon.c
index 6144fc0aa9..585b95c4a7 100644
--- a/drivers/rtc/rtc-abracon.c
+++ b/drivers/rtc/rtc-abracon.c
@@ -84,7 +84,6 @@ static int abracon_probe(struct device_d *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct abracon *abracon;
- int ret;
abracon = xzalloc(sizeof(*abracon));
@@ -93,9 +92,7 @@ static int abracon_probe(struct device_d *dev)
abracon->rtc.ops = &ds13xx_rtc_ops;
abracon->rtc.dev = dev;
- ret = rtc_register(&abracon->rtc);
-
- return ret;
+ return rtc_register(&abracon->rtc);
};
static struct platform_device_id abracon_id[] = {
diff --git a/drivers/rtc/rtc-pcf85363.c b/drivers/rtc/rtc-pcf85363.c
index 7b785d6a77..b9f0fc6012 100644
--- a/drivers/rtc/rtc-pcf85363.c
+++ b/drivers/rtc/rtc-pcf85363.c
@@ -131,7 +131,6 @@ static int pcf85363_probe(struct device_d *dev)
struct i2c_client *client = to_i2c_client(dev);
struct pcf85363 *pcf85363;
struct regmap *regmap;
- int ret;
regmap = regmap_init_i2c(client,
&pcf85363_regmap_i2c_config);
@@ -147,9 +146,7 @@ static int pcf85363_probe(struct device_d *dev)
pcf85363->rtc.ops = &rtc_ops;
pcf85363->rtc.dev = dev;
- ret = rtc_register(&pcf85363->rtc);
-
- return ret;
+ return rtc_register(&pcf85363->rtc);
}
static struct platform_device_id dev_ids[] = {
diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c
index 07f951e535..e5cbc3624e 100644
--- a/drivers/serial/serial_ns16550.c
+++ b/drivers/serial/serial_ns16550.c
@@ -309,11 +309,11 @@ static void ns16550_flush(struct console_device *cdev)
static void ns16550_probe_dt(struct device_d *dev, struct ns16550_priv *priv)
{
- struct device_node *np = dev->device_node;
+ struct device_node *np = dev_of_node(dev);
u32 offset;
u32 width = 1;
- if (!IS_ENABLED(CONFIG_OFDEVICE))
+ if (!np)
return;
of_property_read_u32(np, "clock-frequency", &priv->plat.clock);
@@ -368,7 +368,7 @@ static __maybe_unused struct ns16550_drvdata omap_drvdata = {
.linux_earlycon_name = "omap8250",
};
-static __maybe_unused struct ns16550_drvdata am43xx_drvdata = {
+static __maybe_unused struct ns16550_drvdata omap_clk48m_drvdata = {
.init_port = ns16550_omap_init_port,
.linux_console_name = "ttyO",
.clk_default = 48000000,
@@ -561,7 +561,7 @@ static struct of_device_id ns16550_serial_dt_ids[] = {
.data = &omap_drvdata,
}, {
.compatible = "ti,am4372-uart",
- .data = &am43xx_drvdata,
+ .data = &omap_clk48m_drvdata,
},
#endif
#if IS_ENABLED(CONFIG_MACH_MIPS_XBURST)
@@ -584,7 +584,7 @@ static struct of_device_id ns16550_serial_dt_ids[] = {
static __maybe_unused struct platform_device_id ns16550_serial_ids[] = {
{
.name = "omap-uart",
- .driver_data = (unsigned long)&omap_drvdata,
+ .driver_data = (unsigned long)&omap_clk48m_drvdata,
}, {
/* sentinel */
},
diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
index 62cfc21519..a0e78ce55e 100644
--- a/drivers/soc/imx/gpcv2.c
+++ b/drivers/soc/imx/gpcv2.c
@@ -483,10 +483,10 @@ again:
pd_dev = xzalloc(sizeof(*pd_dev));
pd_dev->device_node = np;
+ pd_dev->device_node->dev = pd_dev;
pd_dev->id = domain_index;
pd_dev->parent = dev;
pd_dev->priv = domain;
- pd_dev->device_node = np;
dev_set_name(pd_dev, imx_pgc_domain_id[0].name);
ret = platform_device_register(pd_dev);
diff --git a/drivers/spi/stm32_spi.c b/drivers/spi/stm32_spi.c
index 0cb04a968c..639c4f1740 100644
--- a/drivers/spi/stm32_spi.c
+++ b/drivers/spi/stm32_spi.c
@@ -11,6 +11,7 @@
#include <init.h>
#include <errno.h>
#include <linux/reset.h>
+#include <linux/spi/spi-mem.h>
#include <spi/spi.h>
#include <linux/bitops.h>
#include <clock.h>
@@ -474,6 +475,24 @@ out:
return ret;
}
+static int stm32_spi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
+{
+ if (op->data.nbytes > SPI_CR2_TSIZE)
+ op->data.nbytes = SPI_CR2_TSIZE;
+
+ return 0;
+}
+
+static int stm32_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
+{
+ return -ENOTSUPP;
+}
+
+static const struct spi_controller_mem_ops stm32_spi_mem_ops = {
+ .adjust_op_size = stm32_spi_adjust_op_size,
+ .exec_op = stm32_spi_exec_op,
+};
+
static int stm32_spi_get_fifo_size(struct stm32_spi_priv *priv)
{
u32 count = 0;
@@ -522,6 +541,7 @@ static int stm32_spi_probe(struct device_d *dev)
master->setup = stm32_spi_setup;
master->transfer = stm32_spi_transfer;
+ master->mem_ops = &stm32_spi_mem_ops;
master->bus_num = -1;
stm32_spi_dt_probe(priv);
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 10c713e833..96c51768f6 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -4,6 +4,9 @@ menuconfig USB_GADGET
select POLLER
bool "USB gadget support"
+config USB_GADGET_DRIVER_ARC_PBL
+ bool
+
if USB_GADGET
config USB_GADGET_DUALSPEED
@@ -16,9 +19,6 @@ config USB_GADGET_DRIVER_ARC
default y
select USB_GADGET_DUALSPEED
-config USB_GADGET_DRIVER_ARC_PBL
- bool
-
config USB_GADGET_DRIVER_AT91
bool
prompt "at91 gadget driver"
@@ -37,6 +37,7 @@ config USB_GADGET_AUTOSTART
bool
default y
prompt "Automatically start usbgadget on boot"
+ depends on GLOBALVAR
select SYSTEM_PARTITIONS if USB_GADGET_MASS_STORAGE
help
Enabling this option allows to automatically start a dfu or
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c
index 102d8714f8..6225e9a313 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/multi.c
@@ -137,6 +137,12 @@ static int multi_bind_fastboot(struct usb_composite_dev *cdev)
return usb_add_function(&config, f_fastboot);
}
+static bool fastboot_has_exports(struct f_multi_opts *opts)
+{
+ return !file_list_empty(opts->fastboot_opts.files) ||
+ opts->fastboot_opts.export_bbu;
+}
+
static int multi_bind_ums(struct usb_composite_dev *cdev)
{
int ret;
@@ -179,7 +185,7 @@ static int multi_unbind(struct usb_composite_dev *cdev)
usb_put_function_instance(fi_dfu);
}
- if (gadget_multi_opts->fastboot_opts.files) {
+ if (fastboot_has_exports(gadget_multi_opts)) {
usb_put_function(f_fastboot);
usb_put_function_instance(fi_fastboot);
}
@@ -219,7 +225,7 @@ static int multi_bind(struct usb_composite_dev *cdev)
if (ret)
return ret;
- if (gadget_multi_opts->fastboot_opts.files) {
+ if (fastboot_has_exports(gadget_multi_opts)) {
printf("%s: creating Fastboot function\n", __func__);
ret = multi_bind_fastboot(cdev);
if (ret)
@@ -259,7 +265,7 @@ unbind_dfu:
if (gadget_multi_opts->dfu_opts.files)
usb_put_function_instance(fi_dfu);
unbind_fastboot:
- if (gadget_multi_opts->fastboot_opts.files)
+ if (fastboot_has_exports(gadget_multi_opts))
usb_put_function_instance(fi_fastboot);
return ret;
@@ -312,8 +318,7 @@ unsigned usb_multi_count_functions(struct f_multi_opts *opts)
{
unsigned count = 0;
- count += !file_list_empty(opts->fastboot_opts.files) ||
- opts->fastboot_opts.export_bbu;
+ count += fastboot_has_exports(opts);
count += !file_list_empty(opts->dfu_opts.files);
count += !file_list_empty(opts->ums_opts.files);
count += opts->create_acm;
diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c
index bf8b6f1eb8..f71cf80b7d 100644
--- a/drivers/usb/imx/chipidea-imx.c
+++ b/drivers/usb/imx/chipidea-imx.c
@@ -260,8 +260,6 @@ static int imx_chipidea_probe(struct device_d *dev)
* devices which have only one.
*/
ci->clk = clk_get(dev, NULL);
- if (!IS_ERR(ci->clk))
- clk_enable(ci->clk);
/* Device trees are using both "phys" and "fsl,usbphy". Prefer the
* more modern former one but fall back to the old one.
@@ -302,6 +300,14 @@ static int imx_chipidea_probe(struct device_d *dev)
ci->data.drvdata = ci;
ci->data.usbphy = ci->usbphy;
+ /*
+ * Enable the clock after we ensured that all resources are available.
+ * This is crucial since the phy can be missing which and so the
+ * usb-controller <-> usb-phy communication is only partly initialized.
+ * This can trigger strange system hangs at least on i.MX8M SoCs.
+ */
+ clk_enable(ci->clk);
+
if ((ci->flags & MXC_EHCI_PORTSC_MASK) == MXC_EHCI_MODE_HSIC)
imx_chipidea_port_init(ci);
diff --git a/drivers/video/stm32_ltdc.c b/drivers/video/stm32_ltdc.c
index 645c20b554..9dc35ade61 100644
--- a/drivers/video/stm32_ltdc.c
+++ b/drivers/video/stm32_ltdc.c
@@ -98,7 +98,7 @@ static void ltdc_set_mode(struct ltdc_fb *priv,
val |= GCR_HSPOL;
if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
val |= GCR_VSPOL;
- if (mode->display_flags & DISPLAY_FLAGS_DE_HIGH)
+ if (mode->display_flags & DISPLAY_FLAGS_DE_LOW)
val |= GCR_DEPOL;
if (mode->display_flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
val |= GCR_PCPOL;
diff --git a/drivers/watchdog/imxwd.c b/drivers/watchdog/imxwd.c
index 31ea388c2c..dba92cb46a 100644
--- a/drivers/watchdog/imxwd.c
+++ b/drivers/watchdog/imxwd.c
@@ -239,18 +239,17 @@ static int imx_wd_probe(struct device_d *dev)
priv = xzalloc(sizeof(struct imx_wd));
iores = dev_request_mem_resource(dev, 0);
- if (IS_ERR(iores)) {
- dev_err(dev, "could not get memory region\n");
- return PTR_ERR(iores);
- }
+ if (IS_ERR(iores))
+ return dev_err_probe(dev, PTR_ERR(iores),
+ "could not get memory region\n");
clk = clk_get(dev, NULL);
if (IS_ERR(clk))
- return PTR_ERR(clk);
+ return dev_err_probe(dev, PTR_ERR(clk), "Failed to get clk\n");
ret = clk_enable(clk);
if (ret)
- return ret;
+ return dev_err_probe(dev, ret, "Failed to enable clk\n");
priv->base = IOMEM(iores->start);
priv->ops = ops;
@@ -272,14 +271,17 @@ static int imx_wd_probe(struct device_d *dev)
}
ret = watchdog_register(&priv->wd);
- if (ret)
+ if (ret) {
+ dev_err_probe(dev, ret, "Failed to register watchdog device\n");
goto on_error;
+ }
}
if (priv->ops->init) {
ret = priv->ops->init(priv);
if (ret) {
- dev_err(dev, "Failed to init watchdog device %d\n", ret);
+ dev_err_probe(dev, ret,
+ "Failed to init watchdog device\n");
goto error_unregister;
}
}