diff options
Diffstat (limited to 'drivers')
50 files changed, 947 insertions, 430 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 2008f6caf2..e7288f6a61 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -285,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); @@ -335,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); @@ -575,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 @@ -586,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) @@ -603,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; @@ -613,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/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/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 **)®s); + 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/core.c b/drivers/regulator/core.c index 60432e0c3d..4876f0f44b 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -75,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) @@ -85,10 +86,14 @@ 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; diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index d21fdbbe71..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,18 +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/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/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; } } |