summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Kconfig1
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/aiodev/Kconfig7
-rw-r--r--drivers/aiodev/Makefile1
-rw-r--r--drivers/aiodev/stm32-adc-core.c211
-rw-r--r--drivers/aiodev/stm32-adc-core.h52
-rw-r--r--drivers/aiodev/stm32-adc.c374
-rw-r--r--drivers/ata/ahci.c12
-rw-r--r--drivers/ata/disk_ata_drive.c10
-rw-r--r--drivers/ata/disk_bios_drive.c16
-rw-r--r--drivers/ata/ide-sff.c12
-rw-r--r--drivers/block/efi-block-io.c8
-rw-r--r--drivers/clk/clk-divider.c2
-rw-r--r--drivers/clk/clk-qoric.c2
-rw-r--r--drivers/clk/clk-stm32mp1.c2
-rw-r--r--drivers/clk/imx/clk-frac-pll.c2
-rw-r--r--drivers/clk/imx/clk-pfd.c2
-rw-r--r--drivers/clk/imx/clk-pll14xx.c2
-rw-r--r--drivers/clk/imx/clk-pllv1.c2
-rw-r--r--drivers/clk/imx/clk-pllv2.c2
-rw-r--r--drivers/clk/imx/clk-pllv3.c2
-rw-r--r--drivers/clk/imx/clk-sccg-pll.c2
-rw-r--r--drivers/clk/mxs/clk-frac.c2
-rw-r--r--drivers/clk/mxs/clk-ref.c2
-rw-r--r--drivers/clk/rockchip/clk-pll.c2
-rw-r--r--drivers/clk/socfpga/clk-pll-a10.c2
-rw-r--r--drivers/clk/tegra/clk-divider.c2
-rw-r--r--drivers/clk/tegra/clk-pll.c2
-rw-r--r--drivers/crypto/caam/caamrng.c16
-rw-r--r--drivers/ddr/fsl/util.c2
-rw-r--r--drivers/gpio/gpio-orion.c12
-rw-r--r--drivers/led/led-pwm.c2
-rw-r--r--drivers/mci/dw_mmc.c2
-rw-r--r--drivers/mci/imx-esdhc-pbl.c2
-rw-r--r--drivers/mci/mci-core.c38
-rw-r--r--drivers/mfd/rave-sp.c10
-rw-r--r--drivers/mtd/mtdconcat.c2
-rw-r--r--drivers/mtd/nand/bbt.c6
-rw-r--r--drivers/mtd/nand/nand_s3c24xx.c2
-rw-r--r--drivers/mtd/ubi/debug.c10
-rw-r--r--drivers/mtd/ubi/kapi.c2
-rw-r--r--drivers/mtd/ubi/ubi-barebox.h2
-rw-r--r--drivers/net/smc911x.c2
-rw-r--r--drivers/nvme/host/core.c12
-rw-r--r--drivers/nvmem/core.c15
-rw-r--r--drivers/of/base.c2
-rw-r--r--drivers/of/overlay.c11
-rw-r--r--drivers/of/partition.c3
-rw-r--r--drivers/phy/phy-stm32-usbphyc.c2
-rw-r--r--drivers/pwm/pwm-imx.c2
-rw-r--r--drivers/pwm/pwm-mxs.c2
-rw-r--r--drivers/pwm/pxa_pwm.c2
-rw-r--r--drivers/regulator/Kconfig9
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/core.c30
-rw-r--r--drivers/regulator/helpers.c25
-rw-r--r--drivers/regulator/stm32-vrefbuf.c220
-rw-r--r--drivers/serial/serial_ar933x.c2
-rw-r--r--drivers/sound/Kconfig38
-rw-r--r--drivers/sound/Makefile5
-rw-r--r--drivers/sound/core.c121
-rw-r--r--drivers/sound/gpio-beeper.c77
-rw-r--r--drivers/sound/pwm-beeper.c124
-rw-r--r--drivers/sound/sdl.c87
-rw-r--r--drivers/sound/synth.c43
-rw-r--r--drivers/usb/gadget/dfu.c388
-rw-r--r--drivers/usb/otg/otgdev.c63
-rw-r--r--drivers/usb/storage/usb.c25
-rw-r--r--drivers/video/Kconfig1
-rw-r--r--drivers/video/backlight-pwm.c2
-rw-r--r--drivers/video/imx-ipu-fb.c2
-rw-r--r--drivers/video/imx-ipu-v3/imx-hdmi.c2
-rw-r--r--drivers/video/imx-ipu-v3/imx-ldb.c2
-rw-r--r--drivers/video/imx-ipu-v3/ipu-di.c2
-rw-r--r--drivers/video/imx-ipu-v3/ipufb.c2
-rw-r--r--drivers/video/imx.c2
-rw-r--r--drivers/video/pxa.c2
-rw-r--r--drivers/video/sdl.c37
-rw-r--r--drivers/video/tc358767.c5
-rw-r--r--drivers/watchdog/stpmic1_wdt.c4
-rw-r--r--drivers/watchdog/wd_core.c29
81 files changed, 1926 insertions, 322 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig
index dda2405780..0b87c2af2a 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -13,6 +13,7 @@ source "drivers/mtd/Kconfig"
source "drivers/ata/Kconfig"
source "drivers/usb/Kconfig"
source "drivers/video/Kconfig"
+source "drivers/sound/Kconfig"
source "drivers/mci/Kconfig"
source "drivers/clk/Kconfig"
source "drivers/clocksource/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 5a03bdceab..fab3790288 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -43,3 +43,4 @@ obj-y += soc/imx/
obj-y += nvme/
obj-y += ddr/
obj-y += power/
+obj-$(CONFIG_SOUND) += sound/
diff --git a/drivers/aiodev/Kconfig b/drivers/aiodev/Kconfig
index 5fb445c096..88d013aad0 100644
--- a/drivers/aiodev/Kconfig
+++ b/drivers/aiodev/Kconfig
@@ -43,4 +43,11 @@ config AM335X_ADC
rather than continuous sampling with DMA, etc. ADC channels should be
configured via device tree, using the kernel bindings.
+config STM32_ADC
+ tristate "STM32 ADC driver"
+ depends on ARCH_STM32MP || COMPILE_TEST
+ help
+ Support for ADC on STM32. Supports simple one-shot readings
+ rather than continuous sampling with DMA, etc. ADC channels should be
+ configured via device tree, using the kernel bindings.
endif
diff --git a/drivers/aiodev/Makefile b/drivers/aiodev/Makefile
index 5f48b2022a..52652f67b7 100644
--- a/drivers/aiodev/Makefile
+++ b/drivers/aiodev/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_LM75) += lm75.o
obj-$(CONFIG_MC13XXX_ADC) += mc13xxx_adc.o
obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o
obj-$(CONFIG_AM335X_ADC) += am335x_adc.o
+obj-$(CONFIG_STM32_ADC) += stm32-adc.o stm32-adc-core.o
diff --git a/drivers/aiodev/stm32-adc-core.c b/drivers/aiodev/stm32-adc-core.c
new file mode 100644
index 0000000000..410e2a894e
--- /dev/null
+++ b/drivers/aiodev/stm32-adc-core.c
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Author: Fabrice Gasnier <fabrice.gasnier@st.com>
+ *
+ * Originally based on the Linux kernel v4.18 drivers/iio/adc/stm32-adc-core.c.
+ */
+
+#include <common.h>
+#include <linux/clk.h>
+#include <regulator.h>
+#include <linux/bitops.h>
+#include "stm32-adc-core.h"
+
+/* STM32H7 - common registers for all ADC instances */
+#define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08)
+
+/* STM32H7_ADC_CCR - bit fields */
+#define STM32H7_PRESC_SHIFT 18
+#define STM32H7_PRESC_MASK GENMASK(21, 18)
+#define STM32H7_CKMODE_SHIFT 16
+#define STM32H7_CKMODE_MASK GENMASK(17, 16)
+
+/* STM32 H7 maximum analog clock rate (from datasheet) */
+#define STM32H7_ADC_MAX_CLK_RATE 36000000
+
+/**
+ * struct stm32h7_adc_ck_spec - specification for stm32h7 adc clock
+ * @ckmode: ADC clock mode, Async or sync with prescaler.
+ * @presc: prescaler bitfield for async clock mode
+ * @div: prescaler division ratio
+ */
+struct stm32h7_adc_ck_spec {
+ u32 ckmode;
+ u32 presc;
+ int div;
+};
+
+static const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = {
+ /* 00: CK_ADC[1..3]: Asynchronous clock modes */
+ { 0, 0, 1 },
+ { 0, 1, 2 },
+ { 0, 2, 4 },
+ { 0, 3, 6 },
+ { 0, 4, 8 },
+ { 0, 5, 10 },
+ { 0, 6, 12 },
+ { 0, 7, 16 },
+ { 0, 8, 32 },
+ { 0, 9, 64 },
+ { 0, 10, 128 },
+ { 0, 11, 256 },
+ /* HCLK used: Synchronous clock modes (1, 2 or 4 prescaler) */
+ { 1, 0, 1 },
+ { 2, 0, 2 },
+ { 3, 0, 4 },
+};
+
+static int stm32h7_adc_clk_sel(struct device_d *dev,
+ struct stm32_adc_common *common)
+{
+ u32 ckmode, presc;
+ unsigned long rate;
+ unsigned int i;
+ int div;
+
+ /* stm32h7 bus clock is common for all ADC instances (mandatory) */
+ if (!common->bclk) {
+ dev_err(dev, "No bclk clock found\n");
+ return -ENOENT;
+ }
+
+ /*
+ * stm32h7 can use either 'bus' or 'adc' clock for analog circuitry.
+ * So, choice is to have bus clock mandatory and adc clock optional.
+ * If optional 'adc' clock has been found, then try to use it first.
+ */
+ if (common->aclk) {
+ /*
+ * Asynchronous clock modes (e.g. ckmode == 0)
+ * From spec: PLL output musn't exceed max rate
+ */
+ rate = clk_get_rate(common->aclk);
+ if (!rate) {
+ dev_err(dev, "Invalid aclk rate: 0\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
+ ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
+ presc = stm32h7_adc_ckmodes_spec[i].presc;
+ div = stm32h7_adc_ckmodes_spec[i].div;
+
+ if (ckmode)
+ continue;
+
+ if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
+ goto out;
+ }
+ }
+
+ /* Synchronous clock modes (e.g. ckmode is 1, 2 or 3) */
+ rate = clk_get_rate(common->bclk);
+ if (!rate) {
+ dev_err(dev, "Invalid bus clock rate: 0\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
+ ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
+ presc = stm32h7_adc_ckmodes_spec[i].presc;
+ div = stm32h7_adc_ckmodes_spec[i].div;
+
+ if (!ckmode)
+ continue;
+
+ if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
+ goto out;
+ }
+
+ dev_err(dev, "clk selection failed\n");
+ return -EINVAL;
+
+out:
+ /* rate used later by each ADC instance to control BOOST mode */
+ common->rate = rate / div;
+
+ /* Set common clock mode and prescaler */
+ clrsetbits_le32(common->base + STM32H7_ADC_CCR,
+ STM32H7_CKMODE_MASK | STM32H7_PRESC_MASK,
+ ckmode << STM32H7_CKMODE_SHIFT |
+ presc << STM32H7_PRESC_SHIFT);
+
+ dev_dbg(dev, "Using %s clock/%d source at %ld kHz\n",
+ ckmode ? "bus" : "adc", div, common->rate / 1000);
+
+ return 0;
+}
+
+static int stm32_adc_core_probe(struct device_d *dev)
+{
+ struct stm32_adc_common *common;
+ int ret;
+
+ common = xzalloc(sizeof(*common));
+
+ common->vref = regulator_get(dev, "vref");
+ if (IS_ERR(common->vref)) {
+ dev_err(dev, "can't get vref-supply: %pe\n", common->vref);
+ return PTR_ERR(common->vref);
+ }
+
+ ret = regulator_get_voltage(common->vref);
+ if (ret < 0) {
+ dev_err(dev, "can't get vref-supply value: %d\n", ret);
+ return ret;
+ }
+ common->vref_uv = ret;
+
+ common->aclk = clk_get(dev, "adc");
+ if (!IS_ERR(common->aclk)) {
+ ret = clk_enable(common->aclk);
+ if (ret) {
+ dev_err(dev, "Can't enable aclk: %d\n", ret);
+ return ret;
+ }
+ }
+
+ common->bclk = clk_get(dev, "bus");
+ if (!IS_ERR(common->bclk)) {
+ ret = clk_enable(common->bclk);
+ if (ret) {
+ dev_err(dev, "Can't enable bclk: %d\n", ret);
+ goto err_aclk_disable;
+ }
+ }
+
+ common->base = dev_request_mem_region(dev, 0);
+ if (IS_ERR(common->base)) {
+ dev_err(dev, "can't get address\n");
+ return -ENOENT;
+ }
+
+ ret = stm32h7_adc_clk_sel(dev, common);
+ if (ret)
+ goto err_bclk_disable;
+
+ dev->priv = common;
+ return of_platform_populate(dev->device_node, NULL, dev);
+
+err_bclk_disable:
+ clk_disable(common->bclk);
+
+err_aclk_disable:
+ clk_disable(common->aclk);
+
+ return ret;
+}
+
+static const struct of_device_id stm32_adc_core_ids[] = {
+ { .compatible = "st,stm32h7-adc-core" },
+ { .compatible = "st,stm32mp1-adc-core" },
+ {}
+};
+
+static struct driver_d stm32_adc_core_driver = {
+ .name = "stm32-adc-core",
+ .probe = stm32_adc_core_probe,
+ .of_compatible = DRV_OF_COMPAT(stm32_adc_core_ids),
+};
+device_platform_driver(stm32_adc_core_driver);
diff --git a/drivers/aiodev/stm32-adc-core.h b/drivers/aiodev/stm32-adc-core.h
new file mode 100644
index 0000000000..de6c0b9495
--- /dev/null
+++ b/drivers/aiodev/stm32-adc-core.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
+ *
+ * Originally based on the Linux kernel v4.18 drivers/iio/adc/stm32-adc-core.h.
+ */
+
+#ifndef __STM32_ADC_H
+#define __STM32_ADC_H
+
+/*
+ * STM32 - ADC global register map
+ * ________________________________________________________
+ * | Offset | Register |
+ * --------------------------------------------------------
+ * | 0x000 | Master ADC1 |
+ * --------------------------------------------------------
+ * | 0x100 | Slave ADC2 |
+ * --------------------------------------------------------
+ * | 0x200 | Slave ADC3 |
+ * --------------------------------------------------------
+ * | 0x300 | Master & Slave common regs |
+ * --------------------------------------------------------
+ */
+#define STM32_ADC_MAX_ADCS 3
+#define STM32_ADCX_COMN_OFFSET 0x300
+
+#include <linux/types.h>
+
+struct regulator;
+struct clk;
+
+/**
+ * struct stm32_adc_common - stm32 ADC driver common data (for all instances)
+ * @base: control registers base cpu addr
+ * @rate: clock rate used for analog circuitry
+ * @aclk: clock for the analog circuitry
+ * @bclk: bus clock common for all ADCs
+ * @vref: regulator reference
+ * @vref_uv: reference supply voltage (uV)
+ */
+struct stm32_adc_common {
+ void __iomem *base;
+ unsigned long rate;
+ struct clk *aclk;
+ struct clk *bclk;
+ struct regulator *vref;
+ int vref_uv;
+};
+
+#endif
diff --git a/drivers/aiodev/stm32-adc.c b/drivers/aiodev/stm32-adc.c
new file mode 100644
index 0000000000..c99b995eaf
--- /dev/null
+++ b/drivers/aiodev/stm32-adc.c
@@ -0,0 +1,374 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Author: Fabrice Gasnier <fabrice.gasnier@st.com>
+ *
+ * Originally based on the Linux kernel v4.18 drivers/iio/adc/stm32-adc.c.
+ */
+
+#include <common.h>
+#include <linux/bitops.h>
+#include <linux/iopoll.h>
+#include <aiodev.h>
+#include <regulator.h>
+#include <linux/math64.h>
+#include "stm32-adc-core.h"
+
+/* STM32H7 - Registers for each ADC instance */
+#define STM32H7_ADC_ISR 0x00
+#define STM32H7_ADC_CR 0x08
+#define STM32H7_ADC_CFGR 0x0C
+#define STM32H7_ADC_SMPR1 0x14
+#define STM32H7_ADC_SMPR2 0x18
+#define STM32H7_ADC_PCSEL 0x1C
+#define STM32H7_ADC_SQR1 0x30
+#define STM32H7_ADC_DR 0x40
+#define STM32H7_ADC_DIFSEL 0xC0
+
+/* STM32H7_ADC_ISR - bit fields */
+#define STM32MP1_VREGREADY BIT(12)
+#define STM32H7_EOC BIT(2)
+#define STM32H7_ADRDY BIT(0)
+
+/* STM32H7_ADC_CR - bit fields */
+#define STM32H7_DEEPPWD BIT(29)
+#define STM32H7_ADVREGEN BIT(28)
+#define STM32H7_BOOST BIT(8)
+#define STM32H7_ADSTART BIT(2)
+#define STM32H7_ADDIS BIT(1)
+#define STM32H7_ADEN BIT(0)
+
+/* STM32H7_ADC_CFGR bit fields */
+#define STM32H7_EXTEN GENMASK(11, 10)
+#define STM32H7_DMNGT GENMASK(1, 0)
+
+/* STM32H7_ADC_SQR1 - bit fields */
+#define STM32H7_SQ1_SHIFT 6
+
+/* BOOST bit must be set on STM32H7 when ADC clock is above 20MHz */
+#define STM32H7_BOOST_CLKRATE 20000000UL
+
+#define STM32_ADC_CH_MAX 20 /* max number of channels */
+#define STM32_ADC_MAX_SMP 7 /* SMPx range is [0..7] */
+#define STM32_ADC_TIMEOUT_US 100000
+
+struct stm32_adc_regs {
+ int reg;
+ int mask;
+ int shift;
+};
+
+struct stm32_adc_cfg {
+ unsigned int max_channels;
+ unsigned int num_bits;
+ bool has_vregready;
+ const struct stm32_adc_regs *smp_bits;
+ const unsigned int *smp_cycles;
+};
+
+struct stm32_adc {
+ struct stm32_adc_common *common;
+ void __iomem *regs;
+ const struct stm32_adc_cfg *cfg;
+ u32 channel_mask;
+ u32 data_mask;
+ struct aiodevice aiodev;
+ void __iomem *base;
+ struct aiochannel *channels;
+ u32 *channel_map;
+ u32 smpr_val[2];
+};
+
+static void stm32_adc_stop(struct stm32_adc *adc)
+{
+ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADDIS);
+ clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
+ /* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */
+ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
+
+ regulator_disable(adc->common->vref);
+}
+
+static int stm32_adc_start_channel(struct stm32_adc *adc, int channel)
+{
+ struct device_d *dev = adc->aiodev.hwdev;
+ struct stm32_adc_common *common = adc->common;
+ int ret;
+ u32 val;
+
+ ret = regulator_enable(common->vref);
+ if (ret)
+ return ret;
+
+ /* Exit deep power down, then enable ADC voltage regulator */
+ clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
+ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADVREGEN);
+ if (common->rate > STM32H7_BOOST_CLKRATE)
+ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
+
+ /* Wait for startup time */
+ if (!adc->cfg->has_vregready) {
+ udelay(20);
+ } else {
+ ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
+ val & STM32MP1_VREGREADY,
+ STM32_ADC_TIMEOUT_US);
+ if (ret < 0) {
+ stm32_adc_stop(adc);
+ dev_err(dev, "Failed to enable vreg: %d\n", ret);
+ return ret;
+ }
+ }
+
+ /* Only use single ended channels */
+ writel(0, adc->regs + STM32H7_ADC_DIFSEL);
+
+ /* Enable ADC, Poll for ADRDY to be set (after adc startup time) */
+ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADEN);
+ ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
+ val & STM32H7_ADRDY, STM32_ADC_TIMEOUT_US);
+ if (ret < 0) {
+ stm32_adc_stop(adc);
+ dev_err(dev, "Failed to enable ADC: %d\n", ret);
+ return ret;
+ }
+
+ /* Preselect channels */
+ writel(adc->channel_mask, adc->regs + STM32H7_ADC_PCSEL);
+
+ /* Apply sampling time settings */
+ writel(adc->smpr_val[0], adc->regs + STM32H7_ADC_SMPR1);
+ writel(adc->smpr_val[1], adc->regs + STM32H7_ADC_SMPR2);
+
+ /* Program regular sequence: chan in SQ1 & len = 0 for one channel */
+ writel(channel << STM32H7_SQ1_SHIFT, adc->regs + STM32H7_ADC_SQR1);
+
+ /* Trigger detection disabled (conversion can be launched in SW) */
+ clrbits_le32(adc->regs + STM32H7_ADC_CFGR, STM32H7_EXTEN |
+ STM32H7_DMNGT);
+
+ return 0;
+}
+
+static int stm32_adc_channel_data(struct stm32_adc *adc, int channel,
+ int *data)
+{
+ struct device_d *dev = &adc->aiodev.dev;
+ int ret;
+ u32 val;
+
+ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADSTART);
+ ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
+ val & STM32H7_EOC, STM32_ADC_TIMEOUT_US);
+ if (ret < 0) {
+ dev_err(dev, "conversion timed out: %d\n", ret);
+ return ret;
+ }
+
+ *data = readl(adc->regs + STM32H7_ADC_DR);
+
+ return 0;
+}
+
+static int stm32_adc_channel_single_shot(struct aiochannel *chan, int *data)
+{
+ struct stm32_adc *adc = container_of(chan->aiodev, struct stm32_adc, aiodev);
+ int ret, index;
+ s64 raw64;
+
+ index = adc->channel_map[chan->index];
+
+ ret = stm32_adc_start_channel(adc, index);
+ if (ret)
+ return ret;
+
+ ret = stm32_adc_channel_data(adc, index, data);
+ if (ret)
+ return ret;
+
+ raw64 = *data;
+ raw64 *= adc->common->vref_uv;
+ *data = div_s64(raw64, adc->data_mask);
+
+ return 0;
+}
+
+static void stm32_adc_smpr_init(struct stm32_adc *adc, int channel, u32 smp_ns)
+{
+ const struct stm32_adc_regs *smpr = &adc->cfg->smp_bits[channel];
+ u32 period_ns, shift = smpr->shift, mask = smpr->mask;
+ unsigned int smp, r = smpr->reg;
+
+ /* Determine sampling time (ADC clock cycles) */
+ period_ns = NSEC_PER_SEC / adc->common->rate;
+ for (smp = 0; smp <= STM32_ADC_MAX_SMP; smp++)
+ if ((period_ns * adc->cfg->smp_cycles[smp]) >= smp_ns)
+ break;
+ if (smp > STM32_ADC_MAX_SMP)
+ smp = STM32_ADC_MAX_SMP;
+
+ /* pre-build sampling time registers (e.g. smpr1, smpr2) */
+ adc->smpr_val[r] = (adc->smpr_val[r] & ~mask) | (smp << shift);
+}
+
+static int stm32_adc_chan_of_init(struct device_d *dev, struct stm32_adc *adc)
+{
+ unsigned int i;
+ int num_channels = 0, num_times = 0;
+ u32 smp = 0xffffffff; /* Set sampling time to max value by default */
+ int ret;
+
+ /* Retrieve single ended channels listed in device tree */
+ of_get_property(dev->device_node, "st,adc-channels", &num_channels);
+ num_channels /= sizeof(__be32);
+
+ if (num_channels > adc->cfg->max_channels) {
+ dev_err(dev, "too many st,adc-channels: %d\n", num_channels);
+ return -EINVAL;
+ }
+
+ /* Optional sample time is provided either for each, or all channels */
+ of_get_property(dev->device_node, "st,min-sample-time-nsecs", &num_times);
+ num_times /= sizeof(__be32);
+ if (num_times > 1 && num_times != num_channels) {
+ dev_err(dev, "Invalid st,min-sample-time-nsecs\n");
+ return -EINVAL;
+ }
+
+ adc->channels = calloc(sizeof(*adc->channels), num_channels);
+ if (!adc->channels)
+ return -ENOMEM;
+
+ adc->aiodev.channels = calloc(sizeof(*adc->aiodev.channels), num_channels);
+ if (!adc->aiodev.channels)
+ return -ENOMEM;
+
+ adc->channel_map = calloc(sizeof(u32), num_channels);
+
+ adc->aiodev.num_channels = num_channels;
+ adc->aiodev.hwdev = dev;
+ adc->aiodev.read = stm32_adc_channel_single_shot;
+
+ for (i = 0; i < num_channels; i++) {
+ u32 chan;
+
+ ret = of_property_read_u32_index(dev->device_node, "st,adc-channels", i, &chan);
+ if (ret)
+ return ret;
+
+ if (chan >= adc->cfg->max_channels) {
+ dev_err(dev, "bad channel %u\n", chan);
+ return -EINVAL;
+ }
+
+ adc->channel_mask |= 1 << chan;
+
+ adc->aiodev.channels[i] = &adc->channels[i];
+ adc->channels[i].unit = "uV";
+ adc->channel_map[i] = chan;
+
+ /*
+ * Using of_property_read_u32_index(), smp value will only be
+ * modified if valid u32 value can be decoded. This allows to
+ * get either no value, 1 shared value for all indexes, or one
+ * value per channel.
+ */
+ of_property_read_u32_index(dev->device_node, "st,min-sample-time-nsecs",
+ i, &smp);
+ /* Prepare sampling time settings */
+ stm32_adc_smpr_init(adc, chan, smp);
+ }
+
+ adc->data_mask = (1 << adc->cfg->num_bits) - 1;
+
+ ret = aiodevice_register(&adc->aiodev);
+ if (ret < 0)
+ dev_err(dev, "Failed to register aiodev\n");
+
+ return ret;
+}
+
+static int stm32_adc_probe(struct device_d *dev)
+{
+ struct stm32_adc_common *common = dev->parent->priv;
+ struct stm32_adc *adc;
+ u32 offset;
+ int ret;
+
+ ret = of_property_read_u32(dev->device_node, "reg", &offset);
+ if (ret) {
+ dev_err(dev, "Can't read reg property\n");
+ return ret;
+ }
+
+ adc = xzalloc(sizeof(*adc));
+
+ adc->regs = common->base + offset;
+ adc->cfg = device_get_match_data(dev);
+ adc->common = common;
+
+ return stm32_adc_chan_of_init(dev, adc);
+}
+
+/*
+ * stm32h7_smp_bits - describe sampling time register index & bit fields
+ * Sorted so it can be indexed by channel number.
+ */
+static const struct stm32_adc_regs stm32h7_smp_bits[] = {
+ /* STM32H7_ADC_SMPR1, smpr[] index, mask, shift for SMP0 to SMP9 */
+ { 0, GENMASK(2, 0), 0 },
+ { 0, GENMASK(5, 3), 3 },
+ { 0, GENMASK(8, 6), 6 },
+ { 0, GENMASK(11, 9), 9 },
+ { 0, GENMASK(14, 12), 12 },
+ { 0, GENMASK(17, 15), 15 },
+ { 0, GENMASK(20, 18), 18 },
+ { 0, GENMASK(23, 21), 21 },
+ { 0, GENMASK(26, 24), 24 },
+ { 0, GENMASK(29, 27), 27 },
+ /* STM32H7_ADC_SMPR2, smpr[] index, mask, shift for SMP10 to SMP19 */
+ { 1, GENMASK(2, 0), 0 },
+ { 1, GENMASK(5, 3), 3 },
+ { 1, GENMASK(8, 6), 6 },
+ { 1, GENMASK(11, 9), 9 },
+ { 1, GENMASK(14, 12), 12 },
+ { 1, GENMASK(17, 15), 15 },
+ { 1, GENMASK(20, 18), 18 },
+ { 1, GENMASK(23, 21), 21 },
+ { 1, GENMASK(26, 24), 24 },
+ { 1, GENMASK(29, 27), 27 },
+};
+
+/* STM32H7 programmable sampling time (ADC clock cycles, rounded down) */
+static const unsigned int stm32h7_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = {
+ 1, 2, 8, 16, 32, 64, 387, 810,
+};
+
+static const struct stm32_adc_cfg stm32h7_adc_cfg = {
+ .num_bits = 16,
+ .max_channels = STM32_ADC_CH_MAX,
+ .smp_bits = stm32h7_smp_bits,
+ .smp_cycles = stm32h7_adc_smp_cycles,
+};
+
+
+static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
+ .num_bits = 16,
+ .max_channels = STM32_ADC_CH_MAX,
+ .smp_bits = stm32h7_smp_bits,
+ .smp_cycles = stm32h7_adc_smp_cycles,
+ .has_vregready = true,
+};
+
+static const struct of_device_id stm32_adc_match[] = {
+ { .compatible = "st,stm32h7-adc", .data = &stm32h7_adc_cfg },
+ { .compatible = "st,stm32mp1-adc", .data = &stm32mp1_adc_cfg },
+ {}
+};
+
+static struct driver_d stm32_adc_driver = {
+ .name = "stm32-adc",
+ .probe = stm32_adc_probe,
+ .of_compatible = DRV_OF_COMPAT(stm32_adc_match),
+};
+device_platform_driver(stm32_adc_driver);
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 049a36bb44..6d251f248a 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -215,7 +215,7 @@ static int ahci_read_id(struct ata_port *ata, void *buf)
}
static int ahci_rw(struct ata_port *ata, void *rbuf, const void *wbuf,
- unsigned int block, int num_blocks)
+ sector_t block, blkcnt_t num_blocks)
{
struct ahci_port *ahci = container_of(ata, struct ahci_port, ata);
u8 fis[20];
@@ -237,7 +237,7 @@ static int ahci_rw(struct ata_port *ata, void *rbuf, const void *wbuf,
while (num_blocks) {
int now;
- now = min(MAX_SATA_BLOCKS_READ_WRITE, num_blocks);
+ now = min_t(blkcnt_t, MAX_SATA_BLOCKS_READ_WRITE, num_blocks);
fis[4] = (block >> 0) & 0xff;
fis[5] = (block >> 8) & 0xff;
@@ -270,14 +270,14 @@ static int ahci_rw(struct ata_port *ata, void *rbuf, const void *wbuf,
return 0;
}
-static int ahci_read(struct ata_port *ata, void *buf, unsigned int block,
- int num_blocks)
+static int ahci_read(struct ata_port *ata, void *buf, sector_t block,
+ blkcnt_t num_blocks)
{
return ahci_rw(ata, buf, NULL, block, num_blocks);
}
-static int ahci_write(struct ata_port *ata, const void *buf, unsigned int block,
- int num_blocks)
+static int ahci_write(struct ata_port *ata, const void *buf, sector_t block,
+ blkcnt_t num_blocks)
{
return ahci_rw(ata, NULL, buf, block, num_blocks);
}
diff --git a/drivers/ata/disk_ata_drive.c b/drivers/ata/disk_ata_drive.c
index 11f7151e51..3d9503fe7e 100644
--- a/drivers/ata/disk_ata_drive.c
+++ b/drivers/ata/disk_ata_drive.c
@@ -26,7 +26,7 @@
#include <disks.h>
#include <dma.h>
-static uint64_t ata_id_n_sectors(uint16_t *id)
+static blkcnt_t ata_id_n_sectors(uint16_t *id)
{
if (ata_id_has_lba(id)) {
if (ata_id_has_lba48(id))
@@ -75,7 +75,7 @@ static void __maybe_unused ata_dump_id(uint16_t *id)
unsigned char serial[ATA_ID_SERNO_LEN + 1];
unsigned char firmware[ATA_ID_FW_REV_LEN + 1];
unsigned char product[ATA_ID_PROD_LEN + 1];
- uint64_t n_sectors;
+ sector_t n_sectors;
/* Serial number */
ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial));
@@ -165,8 +165,8 @@ static void ata_fix_endianess(uint16_t *buf, unsigned wds)
* @note Due to 'block' is of type 'int' only small disks can be handled!
* @todo Optimize the read loop
*/
-static int ata_read(struct block_device *blk, void *buffer, int block,
- int num_blocks)
+static int ata_read(struct block_device *blk, void *buffer, sector_t block,
+ blkcnt_t num_blocks)
{
struct ata_port *port = container_of(blk, struct ata_port, blk);
@@ -187,7 +187,7 @@ static int ata_read(struct block_device *blk, void *buffer, int block,
* @todo Optimize the write loop
*/
static int __maybe_unused ata_write(struct block_device *blk,
- const void *buffer, int block, int num_blocks)
+ const void *buffer, sector_t block, blkcnt_t num_blocks)
{
struct ata_port *port = container_of(blk, struct ata_port, blk);
diff --git a/drivers/ata/disk_bios_drive.c b/drivers/ata/disk_bios_drive.c
index 363af3c6dd..8f522eeba6 100644
--- a/drivers/ata/disk_bios_drive.c
+++ b/drivers/ata/disk_bios_drive.c
@@ -115,7 +115,7 @@ static struct DAPS bios_daps __attribute__((aligned(16)));
* @param buffer Buffer to read from or write to (in the low memory area)
* @return 0 on success, anything else on failure
*/
-static int biosdisk_bios_call(struct media_access *media, int cmd, uint64_t sector_start, unsigned sector_count, void *buffer)
+static int biosdisk_bios_call(struct media_access *media, int cmd, sector_t sector_start, blkcnt_t sector_count, void *buffer)
{
int rc;
@@ -150,12 +150,12 @@ static int biosdisk_bios_call(struct media_access *media, int cmd, uint64_t sect
*
* @note Due to 'block' is of type 'int' only small disks can be handled!
*/
-static int biosdisk_read(struct block_device *blk, void *buffer, int block,
- int num_blocks)
+static int biosdisk_read(struct block_device *blk, void *buffer, sector_t block,
+ blkcnt_t num_blocks)
{
int rc;
- uint64_t sector_start = block;
- unsigned sector_count = num_blocks;
+ sector_t sector_start = block;
+ blkcnt_t sector_count = num_blocks;
struct media_access *media = to_media_access(blk);
while (sector_count >= SECTORS_AT_ONCE) {
@@ -191,11 +191,11 @@ static int biosdisk_read(struct block_device *blk, void *buffer, int block,
* @note Due to 'block' is of type 'int' only small disks can be handled!
*/
static int __maybe_unused biosdisk_write(struct block_device *blk,
- const void *buffer, int block, int num_blocks)
+ const void *buffer, sector_t block, blkcnt_t num_blocks)
{
int rc;
- uint64_t sector_start = block;
- unsigned sector_count = num_blocks;
+ sector_t sector_start = block;
+ blkcnt_t sector_count = num_blocks;
struct media_access *media = to_media_access(blk);
while (sector_count >= SECTORS_AT_ONCE) {
diff --git a/drivers/ata/ide-sff.c b/drivers/ata/ide-sff.c
index b7c8847266..a735c8c32c 100644
--- a/drivers/ata/ide-sff.c
+++ b/drivers/ata/ide-sff.c
@@ -138,7 +138,7 @@ static int ata_wait_ready(struct ide_port *ide, unsigned timeout)
* @param num Sector number
*/
static int ata_set_lba_sector(struct ata_port *port, unsigned drive,
- uint64_t num)
+ sector_t num)
{
struct ide_port *ide = to_ata_drive_access(port);
@@ -324,11 +324,11 @@ static int ide_reset(struct ata_port *port)
* @note Due to 'block' is of type 'int' only small disks can be handled!
* @todo Optimize the read loop
*/
-static int ide_read(struct ata_port *port, void *buffer, unsigned int block,
- int num_blocks)
+static int ide_read(struct ata_port *port, void *buffer, sector_t block,
+ blkcnt_t num_blocks)
{
int rc;
- uint64_t sector = block;
+ sector_t sector = block;
struct ide_port *ide = to_ata_drive_access(port);
while (num_blocks) {
@@ -372,10 +372,10 @@ static int ide_read(struct ata_port *port, void *buffer, unsigned int block,
* @todo Optimize the write loop
*/
static int __maybe_unused ide_write(struct ata_port *port,
- const void *buffer, unsigned int block, int num_blocks)
+ const void *buffer, sector_t block, blkcnt_t num_blocks)
{
int rc;
- uint64_t sector = block;
+ sector_t sector = block;
struct ide_port *ide = to_ata_drive_access(port);
while (num_blocks) {
diff --git a/drivers/block/efi-block-io.c b/drivers/block/efi-block-io.c
index 30db486876..4768c219ed 100644
--- a/drivers/block/efi-block-io.c
+++ b/drivers/block/efi-block-io.c
@@ -28,7 +28,7 @@ struct efi_block_io_media{
bool write_caching;
u32 block_size;
u32 io_align;
- u64 last_block;
+ sector_t last_block;
u64 lowest_aligned_lba; /* added in Revision 2 */
u32 logical_blocks_per_physical_block; /* added in Revision 2 */
u32 optimal_transfer_length_granularity; /* added in Revision 3 */
@@ -53,8 +53,8 @@ struct efi_bio_priv {
u32 media_id;
};
-static int efi_bio_read(struct block_device *blk, void *buffer, int block,
- int num_blocks)
+static int efi_bio_read(struct block_device *blk, void *buffer, sector_t block,
+ blkcnt_t num_blocks)
{
struct efi_bio_priv *priv = container_of(blk, struct efi_bio_priv, blk);
efi_status_t efiret;
@@ -69,7 +69,7 @@ static int efi_bio_read(struct block_device *blk, void *buffer, int block,
}
static int efi_bio_write(struct block_device *blk,
- const void *buffer, int block, int num_blocks)
+ const void *buffer, sector_t block, blkcnt_t num_blocks)
{
struct efi_bio_priv *priv = container_of(blk, struct efi_bio_priv, blk);
efi_status_t efiret;
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index cad902fd32..9c2e50e4a5 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -10,7 +10,7 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/log2.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
{
diff --git a/drivers/clk/clk-qoric.c b/drivers/clk/clk-qoric.c
index b3e0780bc8..5bf677d94e 100644
--- a/drivers/clk/clk-qoric.c
+++ b/drivers/clk/clk-qoric.c
@@ -13,7 +13,7 @@
#include <linux/kernel.h>
#include <of_address.h>
#include <of.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#define PLL_DIV1 0
#define PLL_DIV2 1
diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c
index 6016c5bfd0..2380bd0c21 100644
--- a/drivers/clk/clk-stm32mp1.c
+++ b/drivers/clk/clk-stm32mp1.c
@@ -10,7 +10,7 @@
#include <io.h>
#include <of.h>
#include <of_address.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
diff --git a/drivers/clk/imx/clk-frac-pll.c b/drivers/clk/imx/clk-frac-pll.c
index 2195762c8b..48866eadf0 100644
--- a/drivers/clk/imx/clk-frac-pll.c
+++ b/drivers/clk/imx/clk-frac-pll.c
@@ -8,7 +8,7 @@
#include <malloc.h>
#include <linux/clk.h>
#include <linux/err.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
diff --git a/drivers/clk/imx/clk-pfd.c b/drivers/clk/imx/clk-pfd.c
index eb2b1700ae..a7ca664524 100644
--- a/drivers/clk/imx/clk-pfd.c
+++ b/drivers/clk/imx/clk-pfd.c
@@ -12,7 +12,7 @@
#include <linux/clkdev.h>
#include <linux/err.h>
#include <malloc.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c
index 6ba519516b..3fd5a49ee7 100644
--- a/drivers/clk/imx/clk-pll14xx.c
+++ b/drivers/clk/imx/clk-pll14xx.c
@@ -14,7 +14,7 @@
#include <malloc.h>
#include <clock.h>
#include <soc/imx8m/clk-early.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
diff --git a/drivers/clk/imx/clk-pllv1.c b/drivers/clk/imx/clk-pllv1.c
index 9b5d28f22f..283ae843a7 100644
--- a/drivers/clk/imx/clk-pllv1.c
+++ b/drivers/clk/imx/clk-pllv1.c
@@ -8,7 +8,7 @@
#include <linux/clkdev.h>
#include <linux/err.h>
#include <malloc.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
diff --git a/drivers/clk/imx/clk-pllv2.c b/drivers/clk/imx/clk-pllv2.c
index 56005ca725..6af2d71352 100644
--- a/drivers/clk/imx/clk-pllv2.c
+++ b/drivers/clk/imx/clk-pllv2.c
@@ -8,7 +8,7 @@
#include <linux/clkdev.h>
#include <linux/err.h>
#include <malloc.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c
index e10b61b040..51e620a040 100644
--- a/drivers/clk/imx/clk-pllv3.c
+++ b/drivers/clk/imx/clk-pllv3.c
@@ -9,7 +9,7 @@
#include <linux/err.h>
#include <malloc.h>
#include <clock.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
diff --git a/drivers/clk/imx/clk-sccg-pll.c b/drivers/clk/imx/clk-sccg-pll.c
index aabab27a22..755ece0e12 100644
--- a/drivers/clk/imx/clk-sccg-pll.c
+++ b/drivers/clk/imx/clk-sccg-pll.c
@@ -12,7 +12,7 @@
#include <linux/err.h>
#include <malloc.h>
#include <clock.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
diff --git a/drivers/clk/mxs/clk-frac.c b/drivers/clk/mxs/clk-frac.c
index 21e572ff6f..a9d390121e 100644
--- a/drivers/clk/mxs/clk-frac.c
+++ b/drivers/clk/mxs/clk-frac.c
@@ -7,7 +7,7 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <io.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
diff --git a/drivers/clk/mxs/clk-ref.c b/drivers/clk/mxs/clk-ref.c
index 16a2fc2991..69361f9ac3 100644
--- a/drivers/clk/mxs/clk-ref.c
+++ b/drivers/clk/mxs/clk-ref.c
@@ -7,7 +7,7 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <io.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index 8d3fd6cf1c..6bb8156f8c 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -4,7 +4,7 @@
* Author: Heiko Stuebner <heiko@sntech.de>
*/
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <common.h>
#include <io.h>
#include <linux/list.h>
diff --git a/drivers/clk/socfpga/clk-pll-a10.c b/drivers/clk/socfpga/clk-pll-a10.c
index 12d6ef6fc3..fcf31e9ea1 100644
--- a/drivers/clk/socfpga/clk-pll-a10.c
+++ b/drivers/clk/socfpga/clk-pll-a10.c
@@ -7,7 +7,7 @@
#include <malloc.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
diff --git a/drivers/clk/tegra/clk-divider.c b/drivers/clk/tegra/clk-divider.c
index 28a1342bbf..cc8b85520c 100644
--- a/drivers/clk/tegra/clk-divider.c
+++ b/drivers/clk/tegra/clk-divider.c
@@ -8,7 +8,7 @@
#include <common.h>
#include <io.h>
#include <malloc.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <linux/clk.h>
#include <linux/err.h>
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 3ac49cae47..832b3c5ea1 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -9,7 +9,7 @@
#include <clock.h>
#include <io.h>
#include <malloc.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <linux/clk.h>
#include <linux/err.h>
diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c
index 39a90568df..5d8cfb8bff 100644
--- a/drivers/crypto/caam/caamrng.c
+++ b/drivers/crypto/caam/caamrng.c
@@ -91,10 +91,8 @@ static void rng_done(struct device_d *jrdev, u32 *desc, u32 err, void *context)
/* Buffer refilled, invalidate cache */
dma_sync_single_for_cpu(bd->addr, RN_BUF_SIZE, DMA_FROM_DEVICE);
-#ifdef DEBUG
- print_hex_dump(KERN_ERR, "rng refreshed buf@: ",
- DUMP_PREFIX_OFFSET, 16, 4, bd->buf, RN_BUF_SIZE, 1);
-#endif
+ print_hex_dump_debug("rng refreshed buf@: ", DUMP_PREFIX_OFFSET,
+ 16, 4, bd->buf, RN_BUF_SIZE, 1);
}
static inline int submit_job(struct caam_rng_ctx *ctx, int to_current)
@@ -186,10 +184,9 @@ static inline int rng_create_sh_desc(struct caam_rng_ctx *ctx)
dma_sync_single_for_device((unsigned long)desc, desc_bytes(desc),
DMA_TO_DEVICE);
-#ifdef DEBUG
- print_hex_dump(KERN_ERR, "rng shdesc@: ", DUMP_PREFIX_OFFSET, 16, 4,
+
+ print_hex_dump_debug("rng shdesc@: ", DUMP_PREFIX_OFFSET, 16, 4,
desc, desc_bytes(desc), 1);
-#endif
return 0;
}
@@ -203,10 +200,9 @@ static inline int rng_create_job_desc(struct caam_rng_ctx *ctx, int buf_id)
HDR_REVERSE);
append_seq_out_ptr_intlen(desc, bd->addr, RN_BUF_SIZE, 0);
-#ifdef DEBUG
- print_hex_dump(KERN_ERR, "rng job desc@: ", DUMP_PREFIX_OFFSET, 16, 4,
+
+ print_hex_dump_debug("rng job desc@: ", DUMP_PREFIX_OFFSET, 16, 4,
desc, desc_bytes(desc), 1);
-#endif
return 0;
}
diff --git a/drivers/ddr/fsl/util.c b/drivers/ddr/fsl/util.c
index 977d22dcaa..1775b08be3 100644
--- a/drivers/ddr/fsl/util.c
+++ b/drivers/ddr/fsl/util.c
@@ -8,7 +8,7 @@
#include <soc/fsl/fsl_immap.h>
#include <io.h>
#include <soc/fsl/immap_lsch2.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "fsl_ddr.h"
/* To avoid 64-bit full-divides, we factor this here */
diff --git a/drivers/gpio/gpio-orion.c b/drivers/gpio/gpio-orion.c
index 63ef966edf..ba2729d1f0 100644
--- a/drivers/gpio/gpio-orion.c
+++ b/drivers/gpio/gpio-orion.c
@@ -91,10 +91,7 @@ static int orion_gpio_probe(struct device_d *dev)
{
struct resource *iores;
struct orion_gpio_chip *gpio;
-
- dev->id = of_alias_get_id(dev->device_node, "gpio");
- if (dev->id < 0)
- return dev->id;
+ int id;
gpio = xzalloc(sizeof(*gpio));
iores = dev_request_mem_resource(dev, 0);
@@ -105,7 +102,12 @@ static int orion_gpio_probe(struct device_d *dev)
gpio->regs = IOMEM(iores->start);
gpio->chip.dev = dev;
gpio->chip.ops = &orion_gpio_ops;
- gpio->chip.base = dev->id * 32;
+
+ id = of_alias_get_id(dev->device_node, "gpio");
+ if (id < 0)
+ return id;
+
+ gpio->chip.base = id * 32;
gpio->chip.ngpio = 32;
of_property_read_u32(dev->device_node, "ngpios", &gpio->chip.ngpio);
diff --git a/drivers/led/led-pwm.c b/drivers/led/led-pwm.c
index d8866bf757..90c2ca929a 100644
--- a/drivers/led/led-pwm.c
+++ b/drivers/led/led-pwm.c
@@ -20,7 +20,7 @@
#include <led.h>
#include <pwm.h>
#include <of.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
struct pwmled {
bool active_low;
diff --git a/drivers/mci/dw_mmc.c b/drivers/mci/dw_mmc.c
index 8249403eb7..7979568841 100644
--- a/drivers/mci/dw_mmc.c
+++ b/drivers/mci/dw_mmc.c
@@ -19,7 +19,7 @@
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/err.h>
-#include <asm-generic/errno.h>
+#include <errno.h>
#include "dw_mmc.h"
diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
index 0cb32b46f1..c3a8b377e2 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -6,7 +6,7 @@
#include <io.h>
#include <mci.h>
#include <linux/sizes.h>
-#include <asm-generic/sections.h>
+#include <asm/sections.h>
#include <asm/cache.h>
#include <mach/xload.h>
#ifdef CONFIG_ARCH_IMX
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index f9066e3a1e..017f25d35f 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -14,7 +14,7 @@
#include <mci.h>
#include <malloc.h>
#include <errno.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <asm/byteorder.h>
#include <block.h>
#include <disks.h>
@@ -398,16 +398,16 @@ int mci_switch(struct mci *mci, unsigned index, unsigned value)
return mci_send_cmd(mci, &cmd, NULL);
}
-static int mci_calc_blk_cnt(uint64_t cap, unsigned shift)
+static blkcnt_t mci_calc_blk_cnt(blkcnt_t cap, unsigned shift)
{
- unsigned ret = cap >> shift;
+ blkcnt_t ret = cap >> shift;
if (ret > 0x7fffffff) {
pr_warn("Limiting card size due to 31 bit contraints\n");
return 0x7fffffff;
}
- return (int)ret;
+ return ret;
}
static void mci_part_add(struct mci *mci, uint64_t size,
@@ -1342,14 +1342,14 @@ static int mci_blk_part_switch(struct mci_part *part)
* This routine expects the buffer has the correct size to read all data!
*/
static int __maybe_unused mci_sd_write(struct block_device *blk,
- const void *buffer, int block, int num_blocks)
+ const void *buffer, sector_t block, blkcnt_t num_blocks)
{
struct mci_part *part = container_of(blk, struct mci_part, blk);
struct mci *mci = part->mci;
struct mci_host *host = mci->host;
int rc;
- unsigned max_req_block = num_blocks;
- int write_block;
+ blkcnt_t max_req_block = num_blocks;
+ blkcnt_t write_block;
if (mci->host->max_req_size)
max_req_block = mci->host->max_req_size / mci->write_bl_len;
@@ -1361,7 +1361,7 @@ static int __maybe_unused mci_sd_write(struct block_device *blk,
return -EPERM;
}
- dev_dbg(&mci->dev, "%s: Write %d block(s), starting at %d\n",
+ dev_dbg(&mci->dev, "%s: Write %llu block(s), starting at %llu\n",
__func__, num_blocks, block);
if (mci->write_bl_len != SECTOR_SIZE) {
@@ -1372,15 +1372,15 @@ static int __maybe_unused mci_sd_write(struct block_device *blk,
/* size of the block number field in the MMC/SD command is 32 bit only */
if (block > MAX_BUFFER_NUMBER) {
- dev_dbg(&mci->dev, "Cannot handle block number %d. Too large!\n", block);
+ dev_dbg(&mci->dev, "Cannot handle block number %llu. Too large!\n", block);
return -EINVAL;
}
while (num_blocks) {
- write_block = min_t(int, num_blocks, max_req_block);
+ write_block = min(num_blocks, max_req_block);
rc = mci_block_write(mci, buffer, block, write_block);
if (rc != 0) {
- dev_dbg(&mci->dev, "Writing block %d failed with %d\n", block, rc);
+ dev_dbg(&mci->dev, "Writing block %llu failed with %d\n", block, rc);
return rc;
}
num_blocks -= write_block;
@@ -1401,13 +1401,13 @@ static int __maybe_unused mci_sd_write(struct block_device *blk,
*
* This routine expects the buffer has the correct size to store all data!
*/
-static int mci_sd_read(struct block_device *blk, void *buffer, int block,
- int num_blocks)
+static int mci_sd_read(struct block_device *blk, void *buffer, sector_t block,
+ blkcnt_t num_blocks)
{
struct mci_part *part = container_of(blk, struct mci_part, blk);
struct mci *mci = part->mci;
- unsigned max_req_block = num_blocks;
- int read_block;
+ blkcnt_t max_req_block = num_blocks;
+ blkcnt_t read_block;
int rc;
if (mci->host->max_req_size)
@@ -1415,7 +1415,7 @@ static int mci_sd_read(struct block_device *blk, void *buffer, int block,
mci_blk_part_switch(part);
- dev_dbg(&mci->dev, "%s: Read %d block(s), starting at %d\n",
+ dev_dbg(&mci->dev, "%s: Read %llu block(s), starting at %llu\n",
__func__, num_blocks, block);
if (mci->read_bl_len != SECTOR_SIZE) {
@@ -1425,15 +1425,15 @@ static int mci_sd_read(struct block_device *blk, void *buffer, int block,
}
if (block > MAX_BUFFER_NUMBER) {
- dev_err(&mci->dev, "Cannot handle block number %d. Too large!\n", block);
+ dev_err(&mci->dev, "Cannot handle block number %llu. Too large!\n", block);
return -EINVAL;
}
while (num_blocks) {
- read_block = min_t(int, num_blocks, max_req_block);
+ read_block = min(num_blocks, max_req_block);
rc = mci_read_block(mci, buffer, block, read_block);
if (rc != 0) {
- dev_dbg(&mci->dev, "Reading block %d failed with %d\n", block, rc);
+ dev_dbg(&mci->dev, "Reading block %llu failed with %d\n", block, rc);
return rc;
}
num_blocks -= read_block;
diff --git a/drivers/mfd/rave-sp.c b/drivers/mfd/rave-sp.c
index 8fc46b66bb..ef569dd513 100644
--- a/drivers/mfd/rave-sp.c
+++ b/drivers/mfd/rave-sp.c
@@ -269,9 +269,8 @@ static int rave_sp_write(struct rave_sp *sp, const u8 *data, u8 data_size)
length = dest - frame;
- if (IS_ENABLED(DEBUG))
- print_hex_dump(0, "rave-sp tx: ", DUMP_PREFIX_NONE,
- 16, 1, frame, length, false);
+ print_hex_dump_debug("rave-sp tx: ", DUMP_PREFIX_NONE, 16, 1,
+ frame, length, false);
return serdev_device_write(sp->serdev, frame, length, SECOND);
}
@@ -406,9 +405,8 @@ static void rave_sp_receive_frame(struct rave_sp *sp,
struct device_d *dev = sp->serdev->dev;
u8 crc_calculated[checksum_length];
- if (IS_ENABLED(DEBUG))
- print_hex_dump(0, "rave-sp rx: ", DUMP_PREFIX_NONE,
- 16, 1, data, length, false);
+ print_hex_dump_debug("rave-sp rx: ", DUMP_PREFIX_NONE, 16, 1,
+ data, length, false);
if (unlikely(length <= checksum_length)) {
dev_warn(dev, "Dropping short frame\n");
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 3032c5a16d..8cd82327ba 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -27,7 +27,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/concat.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
/*
* Our storage structure:
diff --git a/drivers/mtd/nand/bbt.c b/drivers/mtd/nand/bbt.c
index 172ab5ffbc..8a78f9046f 100644
--- a/drivers/mtd/nand/bbt.c
+++ b/drivers/mtd/nand/bbt.c
@@ -113,18 +113,20 @@ int nanddev_bbt_set_block_status(struct nand_device *nand, unsigned int entry,
((entry * bits_per_block) / BITS_PER_LONG);
unsigned int offs = (entry * bits_per_block) % BITS_PER_LONG;
unsigned long val = status & GENMASK(bits_per_block - 1, 0);
+ unsigned long shift = ((bits_per_block + offs <= BITS_PER_LONG) ?
+ (offs + bits_per_block - 1) : (BITS_PER_LONG - 1));
if (entry >= nanddev_neraseblocks(nand))
return -ERANGE;
- pos[0] &= ~GENMASK(offs + bits_per_block - 1, offs);
+ pos[0] &= ~GENMASK(shift, offs);
pos[0] |= val << offs;
if (bits_per_block + offs > BITS_PER_LONG) {
unsigned int rbits = bits_per_block + offs - BITS_PER_LONG;
pos[1] &= ~GENMASK(rbits - 1, 0);
- pos[1] |= val >> rbits;
+ pos[1] |= (val >> (BITS_PER_LONG - offs));
}
return 0;
diff --git a/drivers/mtd/nand/nand_s3c24xx.c b/drivers/mtd/nand/nand_s3c24xx.c
index 59bd6c9fed..f1d1441f50 100644
--- a/drivers/mtd/nand/nand_s3c24xx.c
+++ b/drivers/mtd/nand/nand_s3c24xx.c
@@ -32,7 +32,7 @@
#include <mach/s3c-iomap.h>
#include <mach/s3c24xx-nand.h>
#include <io.h>
-#include <asm-generic/errno.h>
+#include <errno.h>
#include <asm/sections.h>
#ifdef CONFIG_S3C_NAND_BOOT
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index 6ae797c2bf..75d6b69f09 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -42,7 +42,7 @@ void ubi_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len)
ubi_msg(ubi, "dumping %d bytes of data from PEB %d, offset %d",
len, pnum, offset);
- print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
+ print_hex_dump_debug("", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
out:
vfree(buf);
return;
@@ -63,8 +63,8 @@ void ubi_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
pr_err("\timage_seq %d\n", be32_to_cpu(ec_hdr->image_seq));
pr_err("\thdr_crc %#08x\n", be32_to_cpu(ec_hdr->hdr_crc));
pr_err("erase counter header hexdump:\n");
- print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
- ec_hdr, UBI_EC_HDR_SIZE, 1);
+ print_hex_dump_debug("", DUMP_PREFIX_OFFSET, 32, 1,
+ ec_hdr, UBI_EC_HDR_SIZE, 1);
}
/**
@@ -88,8 +88,8 @@ void ubi_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
(unsigned long long)be64_to_cpu(vid_hdr->sqnum));
pr_err("\thdr_crc %08x\n", be32_to_cpu(vid_hdr->hdr_crc));
pr_err("Volume identifier header hexdump:\n");
- print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
- vid_hdr, UBI_VID_HDR_SIZE, 1);
+ print_hex_dump_debug("", DUMP_PREFIX_OFFSET, 32, 1,
+ vid_hdr, UBI_VID_HDR_SIZE, 1);
}
/**
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index e1cab763eb..e1781f3f20 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -17,7 +17,7 @@
/* This file mostly implements UBI kernel API functions */
#include <linux/err.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "ubi.h"
/**
diff --git a/drivers/mtd/ubi/ubi-barebox.h b/drivers/mtd/ubi/ubi-barebox.h
index 7ee87ffd3e..5b2d4a72c8 100644
--- a/drivers/mtd/ubi/ubi-barebox.h
+++ b/drivers/mtd/ubi/ubi-barebox.h
@@ -17,7 +17,7 @@
#include <common.h>
#include <malloc.h>
#include <crc.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <errno.h>
#include <linux/err.h>
#include <linux/types.h>
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index ea7cea5f1b..1edc16ce44 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -541,7 +541,7 @@ static int smc911x_probe(struct device_d *dev)
* forbidden while this bit isn't set. Try for 100ms
*/
ret = wait_on_timeout(100 * MSECOND, smc911x_reg_read(priv, PMT_CTRL) & PMT_CTRL_READY);
- if (!ret) {
+ if (ret) {
dev_err(dev, "Device not READY in 100ms aborting\n");
return -ENODEV;
}
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 257679fae8..a27a409cf5 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -222,7 +222,7 @@ static void __nvme_revalidate_disk(struct block_device *blk,
}
static void nvme_setup_rw(struct nvme_ns *ns, struct nvme_command *cmnd,
- int block, int num_block)
+ sector_t block, blkcnt_t num_block)
{
cmnd->rw.nsid = cpu_to_le32(ns->head->ns_id);
cmnd->rw.slba = cpu_to_le64(nvme_block_nr(ns, block));
@@ -239,7 +239,7 @@ static void nvme_setup_flush(struct nvme_ns *ns, struct nvme_command *cmnd)
}
static int nvme_submit_sync_rw(struct nvme_ns *ns, struct nvme_command *cmnd,
- void *buffer, int block, int num_blocks)
+ void *buffer, sector_t block, blkcnt_t num_blocks)
{
/*
* ns->ctrl->max_hw_sectors is in units of 512 bytes, so we
@@ -251,7 +251,7 @@ static int nvme_submit_sync_rw(struct nvme_ns *ns, struct nvme_command *cmnd,
if (num_blocks > max_hw_sectors) {
while (num_blocks) {
- const int chunk = min_t(int, num_blocks,
+ const u32 chunk = min_t(blkcnt_t, num_blocks,
max_hw_sectors);
ret = nvme_submit_sync_rw(ns, cmnd, buffer, block,
@@ -275,7 +275,7 @@ static int nvme_submit_sync_rw(struct nvme_ns *ns, struct nvme_command *cmnd,
if (ret) {
dev_err(ns->ctrl->dev,
- "I/O failed: block: %d, num blocks: %d, status code type: %xh, status code %02xh\n",
+ "I/O failed: block: %llu, num blocks: %llu, status code type: %xh, status code %02xh\n",
block, num_blocks, (ret >> 8) & 0xf,
ret & 0xff);
return -EIO;
@@ -286,7 +286,7 @@ static int nvme_submit_sync_rw(struct nvme_ns *ns, struct nvme_command *cmnd,
static int nvme_block_device_read(struct block_device *blk, void *buffer,
- int block, int num_blocks)
+ sector_t block, blkcnt_t num_blocks)
{
struct nvme_ns *ns = to_nvme_ns(blk);
struct nvme_command cmnd = { };
@@ -298,7 +298,7 @@ static int nvme_block_device_read(struct block_device *blk, void *buffer,
static int __maybe_unused
nvme_block_device_write(struct block_device *blk, const void *buffer,
- int block, int num_blocks)
+ sector_t block, blkcnt_t num_blocks)
{
struct nvme_ns *ns = to_nvme_ns(blk);
struct nvme_command cmnd = { };
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 06e1414769..2a1c4b6941 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -48,12 +48,6 @@ struct nvmem_cell {
static LIST_HEAD(nvmem_cells);
static LIST_HEAD(nvmem_devs);
-int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
- size_t bytes, void *buf);
-int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
- size_t bytes, const void *buf);
-
-
static ssize_t nvmem_cdev_read(struct cdev *cdev, void *buf, size_t count,
loff_t offset, unsigned long flags)
{
@@ -129,7 +123,7 @@ static struct nvmem_device *of_nvmem_find(struct device_node *nvmem_np)
return NULL;
list_for_each_entry(dev, &nvmem_devs, node)
- if (dev->dev.device_node->name && !strcmp(dev->dev.device_node->name, nvmem_np->name))
+ if (dev->dev.device_node == nvmem_np)
return dev;
return NULL;
@@ -290,13 +284,14 @@ struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id)
{
struct device_node *nvmem_np;
- int index;
+ int index = 0;
- index = of_property_match_string(np, "nvmem-names", id);
+ if (id)
+ index = of_property_match_string(np, "nvmem-names", id);
nvmem_np = of_parse_phandle(np, "nvmem", index);
if (!nvmem_np)
- return ERR_PTR(-EINVAL);
+ return ERR_PTR(-ENOENT);
return __nvmem_device_get(nvmem_np, NULL, NULL);
}
diff --git a/drivers/of/base.c b/drivers/of/base.c
index edb0a8e71a..8759099d74 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1704,8 +1704,8 @@ void barebox_register_of(struct device_node *root)
if (root_node)
return;
- of_fix_tree(root);
of_set_root_node(root);
+ of_fix_tree(root);
if (IS_ENABLED(CONFIG_OFDEVICE))
of_probe();
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index 8bf632c1e7..8f4ee3f0a2 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -109,7 +109,7 @@ static char *of_overlay_fix_path(struct device_node *root,
}
static void of_overlay_apply_symbols(struct device_node *root,
- struct device_node *overlay)
+ struct device_node *overlay)
{
const char *old_path;
char *new_path;
@@ -120,8 +120,13 @@ static void of_overlay_apply_symbols(struct device_node *root,
root_symbols = of_get_child_by_name(root, "__symbols__");
overlay_symbols = of_get_child_by_name(overlay, "__symbols__");
- if (!overlay_symbols || !root_symbols) {
- pr_info("overlay/root doesn't have a __symbols__ node\n");
+ if (!overlay_symbols) {
+ pr_debug("overlay doesn't have a __symbols__ node\n");
+ return;
+ }
+
+ if (!root_symbols) {
+ pr_info("root doesn't have a __symbols__ node\n");
return;
}
diff --git a/drivers/of/partition.c b/drivers/of/partition.c
index 65c24c5426..b71716218b 100644
--- a/drivers/of/partition.c
+++ b/drivers/of/partition.c
@@ -235,6 +235,9 @@ static int of_partition_fixup(struct device_node *root, void *ctx)
struct device_node *np;
char *name;
+ if (!cdev->device_node)
+ return -EINVAL;
+
name = of_get_reproducible_name(cdev->device_node);
np = of_find_node_by_reproducible_name(root, name);
free(name);
diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c
index d9eaa8a754..d1e064440e 100644
--- a/drivers/phy/phy-stm32-usbphyc.c
+++ b/drivers/phy/phy-stm32-usbphyc.c
@@ -12,7 +12,7 @@
#include <io.h>
#include <linux/phy/phy.h>
#include <linux/reset.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <usb/phy.h>
#define STM32_USBPHYC_PLL 0x0
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 8407b2f5e1..6dd6e3eb95 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -15,7 +15,7 @@
#include <pwm.h>
#include <linux/clk.h>
#include <linux/err.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
/* i.MX1 and i.MX21 share the same PWM function block: */
diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c
index 08819b43bc..8f77ca07a6 100644
--- a/drivers/pwm/pwm-mxs.c
+++ b/drivers/pwm/pwm-mxs.c
@@ -9,7 +9,7 @@
#include <stmp-device.h>
#include <linux/clk.h>
#include <linux/err.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#define SET 0x4
#define CLR 0x8
diff --git a/drivers/pwm/pxa_pwm.c b/drivers/pwm/pxa_pwm.c
index dc8e41464b..61c4b8da43 100644
--- a/drivers/pwm/pxa_pwm.c
+++ b/drivers/pwm/pxa_pwm.c
@@ -17,7 +17,7 @@
#include <mach/clock.h>
#include <mach/pxa-regs.h>
#include <mach/regs-pwm.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <linux/compiler.h>
/* PWM registers and bits definitions */
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 1ce057180a..9be81832f2 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -28,6 +28,15 @@ config REGULATOR_STM32_PWR
This driver supports internal regulators (1V1, 1V8, 3V3) in the
STMicroelectronics STM32 chips.
+config REGULATOR_STM32_VREFBUF
+ tristate "STMicroelectronics STM32 VREFBUF"
+ depends on ARCH_STM32MP || COMPILE_TEST
+ help
+ This driver supports STMicroelectronics STM32 VREFBUF (voltage
+ reference buffer) which can be used as voltage reference for
+ internal ADCs, DACs and also for external components through
+ dedicated Vref+ pin.
+
config REGULATOR_STPMIC1
tristate "STMicroelectronics STPMIC1 PMIC Regulators"
depends on MFD_STPMIC1
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 4d0bba6c52..67859bb79e 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_REGULATOR_PFUZE) += pfuze.o
obj-$(CONFIG_REGULATOR_STPMIC1) += stpmic1_regulator.o
obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
obj-$(CONFIG_REGULATOR_STM32_PWR) += stm32-pwr.o
+obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 6ea21a4609..ac3a9b048e 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -176,6 +176,12 @@ int of_regulator_register(struct regulator_dev *rd, struct device_node *node)
ri->node = node;
+ if (rd->desc->off_on_delay)
+ ri->enable_time_us = rd->desc->off_on_delay;
+
+ if (rd->desc->fixed_uV && rd->desc->n_voltages == 1)
+ ri->min_uv = ri->max_uv = rd->desc->fixed_uV;
+
of_property_read_u32(node, "regulator-enable-ramp-delay",
&ri->enable_time_us);
of_property_read_u32(node, "regulator-min-microvolt",
@@ -539,6 +545,30 @@ void regulator_bulk_free(int num_consumers,
}
EXPORT_SYMBOL_GPL(regulator_bulk_free);
+int regulator_get_voltage(struct regulator *regulator)
+{
+ struct regulator_dev *rdev = regulator->ri->rdev;
+ int sel, ret;
+
+ if (rdev->desc->ops->get_voltage_sel) {
+ sel = rdev->desc->ops->get_voltage_sel(rdev);
+ if (sel < 0)
+ return sel;
+ ret = rdev->desc->ops->list_voltage(rdev, sel);
+ } else if (rdev->desc->ops->get_voltage) {
+ ret = rdev->desc->ops->get_voltage(rdev);
+ } else if (rdev->desc->ops->list_voltage) {
+ 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 {
+ return -EINVAL;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_get_voltage_rdev);
+
static void regulator_print_one(struct regulator_internal *ri)
{
struct regulator *r;
diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
index c4877cecf7..e741944ce7 100644
--- a/drivers/regulator/helpers.c
+++ b/drivers/regulator/helpers.c
@@ -369,4 +369,29 @@ int regulator_map_voltage_iterate(struct regulator_dev *rdev,
}
EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate);
+/**
+ * regulator_list_voltage_table - List voltages with table based mapping
+ *
+ * @rdev: Regulator device
+ * @selector: Selector to convert into a voltage
+ *
+ * Regulators with table based mapping between voltages and
+ * selectors can set volt_table in the regulator descriptor
+ * and then use this function as their list_voltage() operation.
+ */
+int regulator_list_voltage_table(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ if (!rdev->desc->volt_table) {
+ BUG_ON(!rdev->desc->volt_table);
+ return -EINVAL;
+ }
+ if (selector >= rdev->desc->n_voltages)
+ return -EINVAL;
+ if (selector < rdev->desc->linear_min_sel)
+ return 0;
+
+ return rdev->desc->volt_table[selector];
+}
+EXPORT_SYMBOL_GPL(regulator_list_voltage_table);
diff --git a/drivers/regulator/stm32-vrefbuf.c b/drivers/regulator/stm32-vrefbuf.c
new file mode 100644
index 0000000000..3956b1f64f
--- /dev/null
+++ b/drivers/regulator/stm32-vrefbuf.c
@@ -0,0 +1,220 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) STMicroelectronics 2017
+ *
+ * Author: Fabrice Gasnier <fabrice.gasnier@st.com>
+ */
+
+#include <common.h>
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+#include <of.h>
+#include <regulator.h>
+
+/* STM32 VREFBUF registers */
+#define STM32_VREFBUF_CSR 0x00
+
+/* STM32 VREFBUF CSR bitfields */
+#define STM32_VRS GENMASK(6, 4)
+#define STM32_VRR BIT(3)
+#define STM32_HIZ BIT(1)
+#define STM32_ENVR BIT(0)
+
+#define STM32_VREFBUF_AUTO_SUSPEND_DELAY_MS 10
+
+#define readl_relaxed readl
+#define writel_relaxed writel
+
+struct stm32_vrefbuf {
+ void __iomem *base;
+ struct clk *clk;
+ struct device_d *dev;
+ struct regulator_dev rdev;
+};
+
+struct stm32_vrefbuf_desc {
+ struct regulator_desc desc;
+ const char *supply_name;
+};
+
+static inline struct stm32_vrefbuf *to_stm32_vrefbuf(struct regulator_dev *rdev)
+{
+ return container_of(rdev, struct stm32_vrefbuf, rdev);
+}
+
+static const unsigned int stm32_vrefbuf_voltages[] = {
+ /* Matches resp. VRS = 000b, 001b, 010b, 011b */
+ 2500000, 2048000, 1800000, 1500000,
+};
+
+static int stm32_vrefbuf_enable(struct regulator_dev *rdev)
+{
+ struct stm32_vrefbuf *priv = to_stm32_vrefbuf(rdev);
+ u32 val;
+ int ret;
+
+ val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
+ val = (val & ~STM32_HIZ) | STM32_ENVR;
+ writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
+
+ /*
+ * Vrefbuf startup time depends on external capacitor: wait here for
+ * VRR to be set. That means output has reached expected value.
+ * ~650us sleep should be enough for caps up to 1.5uF. Use 10ms as
+ * arbitrary timeout.
+ */
+ ret = readl_poll_timeout(priv->base + STM32_VREFBUF_CSR, val,
+ val & STM32_VRR, 10000);
+ if (ret) {
+ dev_err(priv->dev, "stm32 vrefbuf timed out!\n");
+ val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
+ val = (val & ~STM32_ENVR) | STM32_HIZ;
+ writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
+ }
+
+ return ret;
+}
+
+static int stm32_vrefbuf_disable(struct regulator_dev *rdev)
+{
+ struct stm32_vrefbuf *priv = to_stm32_vrefbuf(rdev);
+ u32 val;
+
+ val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
+ val &= ~STM32_ENVR;
+ writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
+
+ return 0;
+}
+
+static int stm32_vrefbuf_is_enabled(struct regulator_dev *rdev)
+{
+ struct stm32_vrefbuf *priv = to_stm32_vrefbuf(rdev);
+ int ret;
+
+ ret = readl_relaxed(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR;
+
+ return ret;
+}
+
+static int stm32_vrefbuf_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned sel)
+{
+ struct stm32_vrefbuf *priv = to_stm32_vrefbuf(rdev);
+ u32 val;
+
+ val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
+ val = (val & ~STM32_VRS) | FIELD_PREP(STM32_VRS, sel);
+ writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
+
+ return 0;
+}
+
+static int stm32_vrefbuf_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct stm32_vrefbuf *priv = to_stm32_vrefbuf(rdev);
+ u32 val;
+ int ret;
+
+ val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
+ ret = FIELD_GET(STM32_VRS, val);
+
+ return ret;
+}
+
+static const struct regulator_ops stm32_vrefbuf_volt_ops = {
+ .enable = stm32_vrefbuf_enable,
+ .disable = stm32_vrefbuf_disable,
+ .is_enabled = stm32_vrefbuf_is_enabled,
+ .get_voltage_sel = stm32_vrefbuf_get_voltage_sel,
+ .set_voltage_sel = stm32_vrefbuf_set_voltage_sel,
+ .list_voltage = regulator_list_voltage_table,
+};
+
+static const struct stm32_vrefbuf_desc stm32_vrefbuf_regu = {
+ .desc = {
+ .volt_table = stm32_vrefbuf_voltages,
+ .n_voltages = ARRAY_SIZE(stm32_vrefbuf_voltages),
+ .ops = &stm32_vrefbuf_volt_ops,
+ .off_on_delay = 1000,
+ },
+ .supply_name = "vdda",
+};
+
+static int stm32_vrefbuf_probe(struct device_d *dev)
+{
+ struct stm32_vrefbuf *priv;
+ struct regulator_dev *rdev;
+ struct regulator *supply;
+ int ret;
+
+ supply = regulator_get(dev, stm32_vrefbuf_regu.supply_name);
+ if (IS_ERR(supply))
+ return PTR_ERR(supply);
+
+ priv = xzalloc(sizeof(*priv));
+ priv->dev = dev;
+
+ priv->base = dev_request_mem_region(dev, 0);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ priv->clk = clk_get(dev, NULL);
+ if (IS_ERR(priv->clk))
+ return PTR_ERR(priv->clk);
+
+ ret = clk_enable(priv->clk);
+ if (ret) {
+ dev_err(dev, "clk enable failed with error %d\n", ret);
+ return ret;
+ }
+
+ rdev = &priv->rdev;
+
+ rdev->dev = dev;
+ rdev->desc = &stm32_vrefbuf_regu.desc;
+
+ ret = of_regulator_register(rdev, dev->device_node);
+ if (ret) {
+ ret = PTR_ERR(rdev);
+ dev_err(dev, "register failed with error %d\n", ret);
+ goto err_clk_dis;
+ }
+
+ regulator_enable(supply);
+
+ dev->priv = priv;
+
+ return 0;
+
+err_clk_dis:
+ clk_disable(priv->clk);
+
+ return ret;
+}
+
+static void stm32_vrefbuf_remove(struct device_d *dev)
+{
+ struct stm32_vrefbuf *priv = dev->priv;
+
+ clk_disable(priv->clk);
+};
+
+static const struct of_device_id __maybe_unused stm32_vrefbuf_of_match[] = {
+ { .compatible = "st,stm32-vrefbuf", },
+ {},
+};
+
+static struct driver_d stm32_vrefbuf_driver = {
+ .probe = stm32_vrefbuf_probe,
+ .name = "stm32-vrefbuf",
+ .remove = stm32_vrefbuf_remove,
+ .of_compatible = stm32_vrefbuf_of_match,
+};
+device_platform_driver(stm32_vrefbuf_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics STM32 VREFBUF driver");
+MODULE_ALIAS("platform:stm32-vrefbuf");
diff --git a/drivers/serial/serial_ar933x.c b/drivers/serial/serial_ar933x.c
index 2fe1b4f923..32ad1ba463 100644
--- a/drivers/serial/serial_ar933x.c
+++ b/drivers/serial/serial_ar933x.c
@@ -18,7 +18,7 @@
#include <init.h>
#include <malloc.h>
#include <io.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <linux/clk.h>
#include <linux/err.h>
diff --git a/drivers/sound/Kconfig b/drivers/sound/Kconfig
new file mode 100644
index 0000000000..bf6f715200
--- /dev/null
+++ b/drivers/sound/Kconfig
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: GPL-2.0-only
+menuconfig SOUND
+ bool "Sound drivers"
+ select POLLER
+ help
+ Say Y here for sound support. At the moment that's just beep tones.
+ Tones are played asynchronously in a poller. Check the beep command
+ for how to exercise the API.
+
+if SOUND
+
+config SOUND_SDL
+ bool "SDL sound driver for sandbox"
+ depends on SANDBOX && OFDEVICE
+ select SDL
+
+config PWM_BEEPER
+ bool "PWM beeper support"
+ depends on PWM && OFDEVICE
+ help
+ Say Y here to get support for PWM based beeper devices.
+
+config GPIO_BEEPER
+ bool "GPIO beeper support"
+ depends on GPIOLIB && OFDEVICE
+ help
+ Say Y here to get support for GPIO based beeper devices.
+
+config SYNTH_SQUARES
+ bool "Synthesize square waves only"
+ help
+ For beeping on PCM sound cards, barebox needs to synthesize samples,
+ which can take too much poller time for crisp playback and/or quick
+ booting. If your playback stutters, say Y here. This will have all
+ synthesizers output a gain-adjusted square wave instead, which is
+ less time-consuming to compute.
+
+endif
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
new file mode 100644
index 0000000000..57d9cbd332
--- /dev/null
+++ b/drivers/sound/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-y += core.o synth.o
+obj-$(CONFIG_SOUND_SDL) += sdl.o
+obj-$(CONFIG_PWM_BEEPER) += pwm-beeper.o
+obj-$(CONFIG_GPIO_BEEPER) += gpio-beeper.o
diff --git a/drivers/sound/core.c b/drivers/sound/core.c
new file mode 100644
index 0000000000..801b1fade5
--- /dev/null
+++ b/drivers/sound/core.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: © 2021 Ahmad Fatoum
+
+#include <common.h>
+#include <linux/list.h>
+#include <sound.h>
+#include <poller.h>
+#include <linux/iopoll.h>
+
+static LIST_HEAD(card_list);
+
+struct beep {
+ int freq;
+ unsigned int us;
+ struct list_head list;
+};
+
+static int sound_card_do_beep(struct sound_card *card,
+ int freq, unsigned int us)
+{
+ if (freq == -1)
+ freq = card->bell_frequency;
+
+ return card->beep(card, freq, us);
+}
+
+static void sound_card_poller_cb(void *_card)
+{
+ struct sound_card *card = _card;
+ struct beep *beep;
+
+ beep = list_first_entry_or_null(&card->tune, struct beep, list);
+ if (!beep) {
+ sound_card_do_beep(card, 0, 0);
+ return;
+ }
+
+ list_del(&beep->list);
+
+ poller_call_async(&card->poller, beep->us * 1000ULL,
+ sound_card_poller_cb, card);
+ sound_card_do_beep(card, beep->freq, beep->us);
+
+ free(beep);
+}
+
+int sound_card_register(struct sound_card *card)
+{
+ if (!card->name)
+ return -EINVAL;
+
+ if (card->bell_frequency <= 0)
+ card->bell_frequency = 1000;
+
+ poller_async_register(&card->poller, card->name);
+ INIT_LIST_HEAD(&card->tune);
+
+ list_add_tail(&card->list, &card_list);
+ return 0;
+}
+
+struct sound_card *sound_card_get_default(void)
+{
+ return list_first_entry_or_null(&card_list, struct sound_card, list);
+}
+
+int sound_card_beep(struct sound_card *card, int freq, unsigned int us)
+{
+ struct beep *beep;
+ int ret;
+
+ if (!card)
+ return -ENODEV;
+
+ if (!poller_async_active(&card->poller)) {
+ ret = sound_card_do_beep(card, freq, us);
+ if (!ret)
+ poller_call_async(&card->poller, us * 1000ULL,
+ sound_card_poller_cb, card);
+
+ return ret;
+ }
+
+ beep = malloc(sizeof(*beep));
+ if (!beep)
+ return -ENOMEM;
+
+ beep->freq = freq;
+ beep->us = us;
+
+ list_add_tail(&beep->list, &card->tune);
+
+ return 0;
+}
+
+int sound_card_beep_wait(struct sound_card *card, unsigned timeout)
+{
+ bool active;
+ return read_poll_timeout(poller_async_active, active,
+ !active, timeout, &card->poller);
+}
+
+int sound_card_beep_cancel(struct sound_card *card)
+{
+ struct beep *beep, *tmp;
+ int ret;
+
+ if (!card)
+ return -ENODEV;
+
+ poller_async_cancel(&card->poller);
+
+ ret = card->beep(card, 0, 0);
+
+ list_for_each_entry_safe(beep, tmp, &card->tune, list) {
+ list_del(&beep->list);
+ free(beep);
+ }
+
+ return ret;
+}
diff --git a/drivers/sound/gpio-beeper.c b/drivers/sound/gpio-beeper.c
new file mode 100644
index 0000000000..86fd4a4ee6
--- /dev/null
+++ b/drivers/sound/gpio-beeper.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2021, Ahmad Fatoum
+ */
+
+#include <common.h>
+#include <regulator.h>
+#include <sound.h>
+#include <of.h>
+#include <gpio.h>
+#include <of_gpio.h>
+
+struct gpio_beeper {
+ int gpio;
+ struct sound_card card;
+};
+
+static int gpio_beeper_beep(struct sound_card *card, unsigned freq, unsigned duration)
+{
+ struct gpio_beeper *beeper = container_of(card, struct gpio_beeper, card);
+
+ gpio_set_active(beeper->gpio, freq);
+ return 0;
+}
+
+static int gpio_beeper_probe(struct device_d *dev)
+{
+ struct device_node *np = dev->device_node;
+ struct gpio_beeper *beeper;
+ struct sound_card *card;
+ enum of_gpio_flags of_flags;
+ unsigned long gpio_flags = GPIOF_OUT_INIT_ACTIVE;
+ int ret, gpio;
+
+ gpio = of_get_named_gpio_flags(np, "gpios", 0, &of_flags);
+ if (!gpio_is_valid(gpio))
+ return gpio;
+
+ if (of_flags & OF_GPIO_ACTIVE_LOW)
+ gpio_flags |= GPIOF_ACTIVE_LOW;
+
+ ret = gpio_request_one(gpio, gpio_flags, "gpio-beeper");
+ if (ret) {
+ dev_err(dev, "failed to request gpio %d: %d\n", gpio, ret);
+ return ret;
+ }
+
+ beeper = xzalloc(sizeof(*beeper));
+ beeper->gpio = gpio;
+ dev->priv = beeper;
+
+ card = &beeper->card;
+ card->name = np->full_name;
+ card->beep = gpio_beeper_beep;
+
+ return sound_card_register(card);
+}
+
+static void gpio_beeper_suspend(struct device_d *dev)
+{
+ struct gpio_beeper *beeper = dev->priv;
+
+ gpio_beeper_beep(&beeper->card, 0, 0);
+}
+
+static const struct of_device_id gpio_beeper_match[] = {
+ { .compatible = "gpio-beeper", },
+ { },
+};
+
+static struct driver_d gpio_beeper_driver = {
+ .name = "gpio-beeper",
+ .probe = gpio_beeper_probe,
+ .remove = gpio_beeper_suspend,
+ .of_compatible = gpio_beeper_match,
+};
+device_platform_driver(gpio_beeper_driver);
diff --git a/drivers/sound/pwm-beeper.c b/drivers/sound/pwm-beeper.c
new file mode 100644
index 0000000000..ef053f97cf
--- /dev/null
+++ b/drivers/sound/pwm-beeper.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
+ * Copyright (C) 2021, Ahmad Fatoum
+ */
+
+#include <common.h>
+#include <regulator.h>
+#include <sound.h>
+#include <of.h>
+#include <pwm.h>
+
+struct pwm_beeper {
+ struct pwm_device *pwm;
+ struct regulator *amplifier;
+ struct sound_card card;
+};
+
+#define HZ_TO_NANOSECONDS(x) (1000000000UL/(x))
+
+static int pwm_beeper_beep(struct sound_card *card, unsigned freq, unsigned duration)
+{
+ struct pwm_beeper *beeper = container_of(card, struct pwm_beeper, card);
+ struct pwm_state state;
+ int error = 0;
+
+ if (!freq) {
+ regulator_disable(beeper->amplifier);
+ goto pwm_disable;
+ }
+
+ pwm_get_state(beeper->pwm, &state);
+
+ state.p_enable = true;
+ state.period_ns = HZ_TO_NANOSECONDS(freq);
+ pwm_set_relative_duty_cycle(&state, 50, 100);
+
+ error = pwm_apply_state(beeper->pwm, &state);
+ if (error)
+ return error;
+
+ error = regulator_enable(beeper->amplifier);
+ if (error)
+ goto pwm_disable;
+
+ return 0;
+pwm_disable:
+ pwm_disable(beeper->pwm);
+ return error;
+}
+
+static int pwm_beeper_probe(struct device_d *dev)
+{
+ struct pwm_beeper *beeper;
+ struct sound_card *card;
+ struct pwm_state state;
+ u32 bell_frequency;
+ int error;
+
+ beeper = xzalloc(sizeof(*beeper));
+ dev->priv = beeper;
+
+ beeper->pwm = of_pwm_request(dev->device_node, NULL);
+ if (IS_ERR(beeper->pwm)) {
+ error = PTR_ERR(beeper->pwm);
+ if (error != -EPROBE_DEFER)
+ dev_err(dev, "Failed to request PWM device: %d\n",
+ error);
+ return error;
+ }
+
+ /* Sync up PWM state and ensure it is off. */
+ pwm_init_state(beeper->pwm, &state);
+ state.p_enable = false;
+ error = pwm_apply_state(beeper->pwm, &state);
+ if (error) {
+ dev_err(dev, "failed to apply initial PWM state: %d\n",
+ error);
+ return error;
+ }
+
+ beeper->amplifier = regulator_get(dev, "amp");
+ if (IS_ERR(beeper->amplifier)) {
+ error = PTR_ERR(beeper->amplifier);
+ if (error != -EPROBE_DEFER)
+ dev_err(dev, "Failed to get 'amp' regulator: %d\n",
+ error);
+ return error;
+ }
+
+ error = of_property_read_u32(dev->device_node, "beeper-hz", &bell_frequency);
+ if (error) {
+ bell_frequency = 1000;
+ dev_dbg(dev, "failed to parse 'beeper-hz' property, using default: %uHz\n",
+ bell_frequency);
+ }
+
+ card = &beeper->card;
+ card->name = dev->device_node->full_name;
+ card->bell_frequency = bell_frequency;
+ card->beep = pwm_beeper_beep;
+
+ return sound_card_register(card);
+}
+
+static void pwm_beeper_suspend(struct device_d *dev)
+{
+ struct pwm_beeper *beeper = dev->priv;
+
+ pwm_beeper_beep(&beeper->card, 0, 0);
+}
+
+static const struct of_device_id pwm_beeper_match[] = {
+ { .compatible = "pwm-beeper", },
+ { },
+};
+
+static struct driver_d pwm_beeper_driver = {
+ .name = "pwm-beeper",
+ .probe = pwm_beeper_probe,
+ .remove = pwm_beeper_suspend,
+ .of_compatible = pwm_beeper_match,
+};
+device_platform_driver(pwm_beeper_driver);
diff --git a/drivers/sound/sdl.c b/drivers/sound/sdl.c
new file mode 100644
index 0000000000..118d774295
--- /dev/null
+++ b/drivers/sound/sdl.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <errno.h>
+#include <driver.h>
+#include <mach/linux.h>
+#include <linux/time.h>
+#include <linux/math64.h>
+#include <of.h>
+#include <sound.h>
+
+#define AMPLITUDE 28000
+#define SAMPLERATE 44000ULL
+
+struct sandbox_sound {
+ struct sound_card card;
+};
+
+static int sandbox_sound_beep(struct sound_card *card, unsigned freq, unsigned duration)
+{
+ size_t nsamples = div_s64(SAMPLERATE * duration, USEC_PER_SEC);
+ int16_t *data;
+ int ret;
+
+ if (!freq) {
+ sdl_sound_stop();
+ return 0;
+ }
+
+ data = malloc(nsamples * sizeof(*data));
+ if (!data)
+ return -ENOMEM;
+
+ synth_sin(freq, AMPLITUDE, data, SAMPLERATE, nsamples);
+ ret = sdl_sound_play(data, nsamples);
+ if (ret)
+ ret = -EIO;
+ free(data);
+
+ return ret;
+}
+
+static int sandbox_sound_probe(struct device_d *dev)
+{
+ struct sandbox_sound *priv;
+ struct sound_card *card;
+ int ret;
+
+ priv = xzalloc(sizeof(*priv));
+
+ card = &priv->card;
+ card->name = "SDL-Audio";
+ card->beep = sandbox_sound_beep;
+
+ ret = sdl_sound_init(SAMPLERATE);
+ if (ret) {
+ ret = -ENODEV;
+ goto free_priv;
+ }
+
+ ret = sound_card_register(card);
+ if (ret)
+ goto sdl_sound_close;
+
+ dev_info(dev, "probed\n");
+ return 0;
+
+sdl_sound_close:
+ sdl_sound_close();
+free_priv:
+ free(priv);
+
+ return ret;
+}
+
+
+static __maybe_unused struct of_device_id sandbox_sound_dt_ids[] = {
+ { .compatible = "barebox,sandbox-sound" },
+ { /* sentinel */ }
+};
+
+static struct driver_d sandbox_sound_drv = {
+ .name = "sandbox-sound",
+ .of_compatible = sandbox_sound_dt_ids,
+ .probe = sandbox_sound_probe,
+};
+device_platform_driver(sandbox_sound_drv);
diff --git a/drivers/sound/synth.c b/drivers/sound/synth.c
new file mode 100644
index 0000000000..c9de62b516
--- /dev/null
+++ b/drivers/sound/synth.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Samsung Electronics, R. Chandrasekar <rcsekar@samsung.com>
+ * Copyright (C) 2021 Ahmad Fatoum
+ */
+
+#include <common.h>
+#include <linux/fixp-arith.h>
+#include <linux/math64.h>
+#include <sound.h>
+
+void __synth_sin(unsigned freq, s16 amplitude, s16 *stream,
+ unsigned sample_rate, unsigned nsamples)
+{
+ int64_t v = 0;
+ int i = 0;
+
+ for (i = 0; i < nsamples; i++) {
+ /* Assume RHS sign extension, true for GCC */
+ stream[i] = (fixp_sin32(div_s64(v * 360, sample_rate)) * (int64_t)amplitude) >> 31;
+ v += freq;
+ }
+}
+
+void __synth_square(unsigned freq, s16 amplitude, s16 *stream,
+ unsigned sample_rate, unsigned nsamples)
+{
+ unsigned period = freq ? sample_rate / freq : 0;
+ int half = period / 2;
+
+ while (nsamples) {
+ int i;
+
+ for (i = 0; nsamples && i < half; i++) {
+ nsamples--;
+ *stream++ = amplitude;
+ }
+ for (i = 0; nsamples && i < period - half; i++) {
+ nsamples--;
+ *stream++ = -amplitude;
+ }
+ }
+}
diff --git a/drivers/usb/gadget/dfu.c b/drivers/usb/gadget/dfu.c
index 7e23fa3157..bb0b34aa94 100644
--- a/drivers/usb/gadget/dfu.c
+++ b/drivers/usb/gadget/dfu.c
@@ -32,6 +32,7 @@
* checking?
* - make 'dnstate' attached to 'struct usb_device_instance'
*/
+#define pr_fmt(fmt) "dfu: " fmt
#include <dma.h>
#include <asm/byteorder.h>
@@ -54,6 +55,7 @@
#include <fs.h>
#include <ioctl.h>
#include <linux/mtd/mtd-abi.h>
+#include <work.h>
#define USB_DT_DFU 0x21
@@ -153,6 +155,7 @@ struct f_dfu {
u8 dfu_state;
u8 dfu_status;
struct usb_request *dnreq;
+ struct work_queue wq;
};
static inline struct f_dfu *func_to_dfu(struct usb_function *f)
@@ -173,6 +176,191 @@ static struct usb_gadget_strings *dfu_strings[] = {
};
static void dn_complete(struct usb_ep *ep, struct usb_request *req);
+static void up_complete(struct usb_ep *ep, struct usb_request *req);
+static void dfu_cleanup(struct f_dfu *dfu);
+
+struct dfu_work {
+ struct work_struct work;
+ struct f_dfu *dfu;
+ void (*task)(struct dfu_work *dw);
+ size_t len;
+ uint8_t *rbuf;
+ uint8_t wbuf[CONFIG_USBD_DFU_XFER_SIZE];
+};
+
+static void dfu_do_work(struct work_struct *w)
+{
+ struct dfu_work *dw = container_of(w, struct dfu_work, work);
+ struct f_dfu *dfu = dw->dfu;
+
+ if (dfu->dfu_state != DFU_STATE_dfuERROR && dfu->dfu_status == DFU_STATUS_OK)
+ dw->task(dw);
+ else
+ pr_debug("skip work\n");
+
+ free(dw);
+}
+
+static void dfu_work_cancel(struct work_struct *w)
+{
+ struct dfu_work *dw = container_of(w, struct dfu_work, work);
+
+ free(dw);
+}
+
+static void dfu_do_write(struct dfu_work *dw)
+{
+ struct f_dfu *dfu = dw->dfu;
+ ssize_t size, wlen = dw->len;
+ ssize_t ret;
+
+ pr_debug("do write\n");
+
+ if (prog_erase && (dfu_written + wlen) > dfu_erased) {
+ size = roundup(wlen, dfu_mtdinfo.erasesize);
+ ret = erase(dfufd, size, dfu_erased);
+ dfu_erased += size;
+ if (ret && ret != -ENOSYS) {
+ perror("erase");
+ dfu->dfu_state = DFU_STATE_dfuERROR;
+ dfu->dfu_status = DFU_STATUS_errERASE;
+ return;
+ }
+ }
+
+ dfu_written += wlen;
+ ret = write(dfufd, dw->wbuf, wlen);
+ if (ret < wlen) {
+ perror("write");
+ dfu->dfu_state = DFU_STATE_dfuERROR;
+ dfu->dfu_status = DFU_STATUS_errWRITE;
+ }
+}
+
+static void dfu_do_read(struct dfu_work *dw)
+{
+ struct f_dfu *dfu = dw->dfu;
+ struct usb_composite_dev *cdev = dfu->func.config->cdev;
+ ssize_t size, rlen = dw->len;
+
+ pr_debug("do read\n");
+
+ size = read(dfufd, dfu->dnreq->buf, rlen);
+ dfu->dnreq->length = size;
+ if (size < 0) {
+ perror("read");
+ dfu->dnreq->length = 0;
+ dfu->dfu_state = DFU_STATE_dfuERROR;
+ dfu->dfu_status = DFU_STATUS_errFILE;
+ } else if (size < rlen) {
+ /* this is the last chunk, go to IDLE and close file */
+ dfu_cleanup(dfu);
+ }
+
+ dfu->dnreq->complete = up_complete;
+ usb_ep_queue(cdev->gadget->ep0, dfu->dnreq);
+}
+
+static void dfu_do_open_dnload(struct dfu_work *dw)
+{
+ struct f_dfu *dfu = dw->dfu;
+ int ret;
+
+ pr_debug("do open dnload\n");
+
+ if (dfu_file_entry->flags & FILE_LIST_FLAG_SAFE) {
+ dfufd = open(DFU_TEMPFILE, O_WRONLY | O_CREAT);
+ } else {
+ unsigned flags = O_WRONLY;
+
+ if (dfu_file_entry->flags & FILE_LIST_FLAG_CREATE)
+ flags |= O_CREAT | O_TRUNC;
+
+ dfufd = open(dfu_file_entry->filename, flags);
+ }
+
+ if (dfufd < 0) {
+ perror("open");
+ dfu->dfu_state = DFU_STATE_dfuERROR;
+ dfu->dfu_status = DFU_STATUS_errFILE;
+ return;
+ }
+
+ if (!(dfu_file_entry->flags & FILE_LIST_FLAG_SAFE)) {
+ ret = ioctl(dfufd, MEMGETINFO, &dfu_mtdinfo);
+ if (!ret) /* file is on a mtd device */
+ prog_erase = 1;
+ }
+}
+
+static void dfu_do_open_upload(struct dfu_work *dw)
+{
+ struct f_dfu *dfu = dw->dfu;
+
+ pr_debug("do open upload\n");
+
+ dfufd = open(dfu_file_entry->filename, O_RDONLY);
+ if (dfufd < 0) {
+ perror("open");
+ dfu->dfu_state = DFU_STATE_dfuERROR;
+ dfu->dfu_status = DFU_STATUS_errFILE;
+ }
+}
+
+static void dfu_do_close(struct dfu_work *dw)
+{
+ struct stat s;
+
+ pr_debug("do close\n");
+
+ if (dfufd > 0) {
+ close(dfufd);
+ dfufd = -EINVAL;
+ }
+
+ if (!stat(DFU_TEMPFILE, &s))
+ unlink(DFU_TEMPFILE);
+}
+
+static void dfu_do_copy(struct dfu_work *dw)
+{
+ struct f_dfu *dfu = dw->dfu;
+ unsigned flags = O_WRONLY;
+ int ret, fd;
+
+ pr_debug("do copy\n");
+
+ if (dfu_file_entry->flags & FILE_LIST_FLAG_CREATE)
+ flags |= O_CREAT | O_TRUNC;
+
+ fd = open(dfu_file_entry->filename, flags);
+ if (fd < 0) {
+ perror("open");
+ dfu->dfu_state = DFU_STATE_dfuERROR;
+ dfu->dfu_status = DFU_STATUS_errERASE;
+ return;
+ }
+
+ ret = erase(fd, ERASE_SIZE_ALL, 0);
+ close(fd);
+ if (ret && ret != -ENOSYS) {
+ perror("erase");
+ dfu->dfu_state = DFU_STATE_dfuERROR;
+ dfu->dfu_status = DFU_STATUS_errERASE;
+ return;
+ }
+
+ ret = copy_file(DFU_TEMPFILE, dfu_file_entry->filename, 0);
+ if (ret) {
+ pr_err("copy file failed\n");
+ dfu->dfu_state = DFU_STATE_dfuERROR;
+ dfu->dfu_status = DFU_STATUS_errWRITE;
+ return;
+ }
+
+ dfu->dfu_state = DFU_STATE_dfuIDLE;
+ dfu_do_close(dw);
+}
static int
dfu_bind(struct usb_configuration *c, struct usb_function *f)
@@ -181,7 +369,7 @@ dfu_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_descriptor_header **header;
struct usb_interface_descriptor *desc;
struct file_list_entry *fentry;
- struct f_dfu *dfu = container_of(f, struct f_dfu, func);
+ struct f_dfu *dfu = func_to_dfu(f);
int i;
int status;
struct usb_string *us;
@@ -209,7 +397,7 @@ dfu_bind(struct usb_configuration *c, struct usb_function *f)
dfu->dnreq = usb_ep_alloc_request(c->cdev->gadget->ep0);
if (!dfu->dnreq) {
- printf("usb_ep_alloc_request failed\n");
+ pr_err("usb_ep_alloc_request failed\n");
status = -ENOMEM;
goto out;
}
@@ -223,6 +411,10 @@ dfu_bind(struct usb_configuration *c, struct usb_function *f)
goto out;
}
+ dfu->wq.fn = dfu_do_work;
+ dfu->wq.cancel = dfu_work_cancel;
+ wq_register(&dfu->wq);
+
/* allocate instance-specific interface IDs, and patch descriptors */
status = usb_interface_id(c, f);
if (status < 0)
@@ -254,7 +446,7 @@ dfu_bind(struct usb_configuration *c, struct usb_function *f)
i = 0;
file_list_for_each_entry(dfu_files, fentry) {
- printf("dfu: register alt%d(%s) with device %s\n",
+ pr_err("register alt%d(%s) with device %s\n",
i, fentry->name, fentry->filename);
i++;
}
@@ -278,6 +470,8 @@ dfu_unbind(struct usb_configuration *c, struct usb_function *f)
dfu_file_entry = NULL;
dfudetach = 0;
+ wq_unregister(&dfu->wq);
+
usb_free_all_descriptors(f);
dma_free(dfu->dnreq->buf);
@@ -320,47 +514,50 @@ static int dfu_status(struct usb_function *f, const struct usb_ctrlrequest *ctrl
static void dfu_cleanup(struct f_dfu *dfu)
{
- struct stat s;
+ struct dfu_work *dw;
+
+ pr_debug("dfu cleanup\n");
memset(&dfu_mtdinfo, 0, sizeof(dfu_mtdinfo));
dfu_written = 0;
dfu_erased = 0;
prog_erase = 0;
- if (dfufd > 0) {
- close(dfufd);
- dfufd = -EINVAL;
- }
+ dfu->dfu_state = DFU_STATE_dfuIDLE;
+ dfu->dfu_status = DFU_STATUS_OK;
- if (!stat(DFU_TEMPFILE, &s))
- unlink(DFU_TEMPFILE);
+ dw = xzalloc(sizeof(*dw));
+ dw->dfu = dfu;
+ dw->task = dfu_do_close;
+ wq_queue_work(&dfu->wq, &dw->work);
}
static void dn_complete(struct usb_ep *ep, struct usb_request *req)
{
struct f_dfu *dfu = req->context;
- loff_t size;
- int ret;
+ struct dfu_work *dw;
+
+ dw = xzalloc(sizeof(*dw));
+ dw->dfu = dfu;
+ dw->task = dfu_do_write;
+ dw->len = min_t(unsigned int, req->length, CONFIG_USBD_DFU_XFER_SIZE);
+ memcpy(dw->wbuf, req->buf, dw->len);
+ wq_queue_work(&dfu->wq, &dw->work);
+}
- if (prog_erase && (dfu_written + req->length) > dfu_erased) {
- size = roundup(req->length, dfu_mtdinfo.erasesize);
- ret = erase(dfufd, size, dfu_erased);
- dfu_erased += size;
- if (ret && ret != -ENOSYS) {
- perror("erase");
- dfu->dfu_status = DFU_STATUS_errERASE;
- dfu_cleanup(dfu);
- return;
- }
- }
+static int handle_manifest(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+ struct f_dfu *dfu = func_to_dfu(f);
+ struct dfu_work *dw;
- dfu_written += req->length;
- ret = write(dfufd, req->buf, req->length);
- if (ret < (int)req->length) {
- perror("write");
- dfu->dfu_status = DFU_STATUS_errWRITE;
- dfu_cleanup(dfu);
+ if (dfu_file_entry->flags & FILE_LIST_FLAG_SAFE) {
+ dw = xzalloc(sizeof(*dw));
+ dw->dfu = dfu;
+ dw->task = dfu_do_copy;
+ wq_queue_work(&dfu->wq, &dw->work);
}
+
+ return 0;
}
static int handle_dnload(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
@@ -370,12 +567,8 @@ static int handle_dnload(struct usb_function *f, const struct usb_ctrlrequest *c
u16 w_length = le16_to_cpu(ctrl->wLength);
if (w_length == 0) {
- if (dfu_file_entry->flags & FILE_LIST_FLAG_SAFE) {
- dfu->dfu_state = DFU_STATE_dfuMANIFEST;
- } else {
- dfu->dfu_state = DFU_STATE_dfuIDLE;
- dfu_cleanup(dfu);
- }
+ handle_manifest(f, ctrl);
+ dfu->dfu_state = DFU_STATE_dfuMANIFEST;
return 0;
}
@@ -386,53 +579,6 @@ static int handle_dnload(struct usb_function *f, const struct usb_ctrlrequest *c
return 0;
}
-static int handle_manifest(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
-{
- struct f_dfu *dfu = func_to_dfu(f);
- int ret;
-
- dfu->dfu_state = DFU_STATE_dfuIDLE;
-
- if (dfu_file_entry->flags & FILE_LIST_FLAG_SAFE) {
- int fd;
- unsigned flags = O_WRONLY;
-
- if (dfu_file_entry->flags & FILE_LIST_FLAG_CREATE)
- flags |= O_CREAT | O_TRUNC;
-
- fd = open(dfu_file_entry->filename, flags);
- if (fd < 0) {
- perror("open");
- dfu->dfu_status = DFU_STATUS_errERASE;
- ret = -EINVAL;
- goto out;
- }
-
- ret = erase(fd, ERASE_SIZE_ALL, 0);
- close(fd);
- if (ret && ret != -ENOSYS) {
- dfu->dfu_status = DFU_STATUS_errERASE;
- perror("erase");
- goto out;
- }
-
- ret = copy_file(DFU_TEMPFILE, dfu_file_entry->filename, 0);
- if (ret) {
- printf("copy file failed\n");
- ret = -EINVAL;
- goto out;
- }
- }
-
- return 0;
-
-out:
- dfu->dfu_status = DFU_STATUS_errWRITE;
- dfu->dfu_state = DFU_STATE_dfuERROR;
- dfu_cleanup(dfu);
- return ret;
-}
-
static void up_complete(struct usb_ep *ep, struct usb_request *req)
{
}
@@ -440,28 +586,22 @@ static void up_complete(struct usb_ep *ep, struct usb_request *req)
static int handle_upload(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
{
struct f_dfu *dfu = func_to_dfu(f);
- struct usb_composite_dev *cdev = f->config->cdev;
+ struct dfu_work *dw;
u16 w_length = le16_to_cpu(ctrl->wLength);
- int len;
-
- len = read(dfufd, dfu->dnreq->buf, w_length);
- dfu->dnreq->length = len;
- if (len < w_length) {
- dfu_cleanup(dfu);
- dfu->dfu_state = DFU_STATE_dfuIDLE;
- }
-
- dfu->dnreq->complete = up_complete;
- usb_ep_queue(cdev->gadget->ep0, dfu->dnreq);
+ dw = xzalloc(sizeof(*dw));
+ dw->dfu = dfu;
+ dw->task = dfu_do_read;
+ dw->len = w_length;
+ dw->rbuf = dfu->dnreq->buf;
+ wq_queue_work(&dfu->wq, &dw->work);
return 0;
}
static void dfu_abort(struct f_dfu *dfu)
{
- dfu->dfu_state = DFU_STATE_dfuIDLE;
- dfu->dfu_status = DFU_STATUS_OK;
+ wq_cancel_work(&dfu->wq);
dfu_cleanup(dfu);
}
@@ -474,7 +614,7 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
int value = -EOPNOTSUPP;
int w_length = le16_to_cpu(ctrl->wLength);
int w_value = le16_to_cpu(ctrl->wValue);
- int ret;
+ struct dfu_work *dw;
if (ctrl->bRequestType == USB_DIR_IN && ctrl->bRequest == USB_REQ_GET_DESCRIPTOR
&& (w_value >> 8) == 0x21) {
@@ -500,46 +640,28 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
value = -EINVAL;
goto out;
}
- debug("dfu: starting download to %s\n", dfu_file_entry->filename);
- if (dfu_file_entry->flags & FILE_LIST_FLAG_SAFE) {
- dfufd = open(DFU_TEMPFILE, O_WRONLY | O_CREAT);
- } else {
- unsigned flags = O_WRONLY;
-
- if (dfu_file_entry->flags & FILE_LIST_FLAG_CREATE)
- flags |= O_CREAT | O_TRUNC;
-
- dfufd = open(dfu_file_entry->filename, flags);
- }
-
- if (dfufd < 0) {
- dfu->dfu_state = DFU_STATE_dfuERROR;
- perror("open");
- goto out;
- }
-
- if (!(dfu_file_entry->flags & FILE_LIST_FLAG_SAFE)) {
- ret = ioctl(dfufd, MEMGETINFO, &dfu_mtdinfo);
- if (!ret) /* file is on a mtd device */
- prog_erase = 1;
- }
+ pr_debug("starting download to %s\n", dfu_file_entry->filename);
+ dw = xzalloc(sizeof(*dw));
+ dw->dfu = dfu;
+ dw->task = dfu_do_open_dnload;
+ wq_queue_work(&dfu->wq, &dw->work);
value = handle_dnload(f, ctrl);
dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
return 0;
case USB_REQ_DFU_UPLOAD:
dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE;
- debug("dfu: starting upload from %s\n", dfu_file_entry->filename);
+ pr_debug("starting upload from %s\n", dfu_file_entry->filename);
if (!(dfu_file_entry->flags & FILE_LIST_FLAG_READBACK)) {
dfu->dfu_state = DFU_STATE_dfuERROR;
goto out;
}
- dfufd = open(dfu_file_entry->filename, O_RDONLY);
- if (dfufd < 0) {
- dfu->dfu_state = DFU_STATE_dfuERROR;
- perror("open");
- goto out;
- }
+
+ dw = xzalloc(sizeof(*dw));
+ dw->dfu = dfu;
+ dw->task = dfu_do_open_upload;
+ wq_queue_work(&dfu->wq, &dw->work);
+
handle_upload(f, ctrl);
return 0;
case USB_REQ_DFU_ABORT:
@@ -606,6 +728,7 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
}
break;
case DFU_STATE_dfuERROR:
+ wq_cancel_work(&dfu->wq);
switch (ctrl->bRequest) {
case USB_REQ_DFU_GETSTATUS:
value = dfu_status(f, ctrl);
@@ -647,10 +770,7 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
}
break;
case DFU_STATE_dfuMANIFEST:
- value = handle_manifest(f, ctrl);
- if (dfu->dfu_state != DFU_STATE_dfuIDLE) {
- return 0;
- }
+ dfu->dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
switch (ctrl->bRequest) {
case USB_REQ_DFU_GETSTATUS:
value = dfu_status(f, ctrl);
@@ -692,9 +812,7 @@ static void dfu_disable(struct usb_function *f)
{
struct f_dfu *dfu = func_to_dfu(f);
- dfu->dfu_state = DFU_STATE_dfuIDLE;
-
- dfu_cleanup(dfu);
+ dfu_abort(dfu);
}
#define STRING_MANUFACTURER_IDX 0
@@ -863,7 +981,7 @@ out:
static void dfu_free_func(struct usb_function *f)
{
- struct f_dfu *dfu = container_of(f, struct f_dfu, func);
+ struct f_dfu *dfu = func_to_dfu(f);
free(dfu);
}
diff --git a/drivers/usb/otg/otgdev.c b/drivers/usb/otg/otgdev.c
index 52f43b75d2..c233315d91 100644
--- a/drivers/usb/otg/otgdev.c
+++ b/drivers/usb/otg/otgdev.c
@@ -4,28 +4,33 @@
#include <driver.h>
#include <usb/usb.h>
-static int (*set_mode_callback)(void *ctx, enum usb_dr_mode mode);
-static unsigned int otg_mode;
+struct otg_mode {
+ struct device_d dev;
+ unsigned int var_mode;
+ unsigned int cur_mode;
+ int (*set_mode_callback)(void *ctx, enum usb_dr_mode mode);
+ void *ctx;
+};
static int otg_set_mode(struct param_d *param, void *ctx)
{
- static int cur_mode = USB_DR_MODE_OTG;
+ struct otg_mode *otg = ctx;
int ret;
- if (otg_mode == USB_DR_MODE_UNKNOWN)
+ if (otg->var_mode == USB_DR_MODE_UNKNOWN)
return -EINVAL;
- if (otg_mode == cur_mode)
+ if (otg->var_mode == otg->cur_mode)
return 0;
- if (cur_mode != USB_DR_MODE_OTG)
+ if (otg->cur_mode != USB_DR_MODE_OTG)
return -EBUSY;
- ret = set_mode_callback(ctx, otg_mode);
+ ret = otg->set_mode_callback(otg->ctx, otg->var_mode);
if (ret)
return ret;
- cur_mode = otg_mode;
+ otg->cur_mode = otg->var_mode;
return 0;
}
@@ -47,20 +52,38 @@ int usb_register_otg_device(struct device_d *parent,
{
int ret;
struct param_d *param_mode;
-
- if (otg_device.parent)
- return -EBUSY;
-
- otg_device.parent = parent;
- set_mode_callback = set_mode;
- otg_mode = USB_DR_MODE_OTG;
-
- ret = register_device(&otg_device);
+ struct otg_mode *otg;
+
+ otg = xzalloc(sizeof(*otg));
+ otg->dev.priv = otg;
+ otg->dev.parent = parent;
+ otg->dev.id = DEVICE_ID_DYNAMIC;
+ dev_set_name(&otg->dev, "otg");
+
+ otg->var_mode = USB_DR_MODE_OTG;
+ otg->cur_mode = USB_DR_MODE_OTG;
+ otg->set_mode_callback = set_mode;
+ otg->ctx = ctx;
+
+ /* register otg.mode as an alias of otg0.mode */
+ if (otg_device.parent == NULL) {
+ otg_device.parent = parent;
+ ret = register_device(&otg_device);
+ if (ret)
+ return ret;
+
+ param_mode = dev_add_param_enum(&otg_device, "mode",
+ otg_set_mode, NULL, &otg->var_mode,
+ otg_mode_names, ARRAY_SIZE(otg_mode_names), otg);
+ }
+
+ ret = register_device(&otg->dev);
if (ret)
return ret;
- param_mode = dev_add_param_enum(&otg_device, "mode",
- otg_set_mode, NULL, &otg_mode,
- otg_mode_names, ARRAY_SIZE(otg_mode_names), ctx);
+ param_mode = dev_add_param_enum(&otg->dev, "mode",
+ otg_set_mode, NULL, &otg->var_mode,
+ otg_mode_names, ARRAY_SIZE(otg_mode_names), otg);
+
return PTR_ERR_OR_ZERO(param_mode);
}
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index e0ef4f5ef3..c264dd4b71 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -185,7 +185,7 @@ exit:
}
static int usb_stor_io_10(struct us_blk_dev *usb_blkdev, u8 opcode,
- u32 start, u8 *data, u16 blocks)
+ sector_t start, u8 *data, u16 blocks)
{
u8 cmd[10];
@@ -206,7 +206,7 @@ static int usb_stor_io_10(struct us_blk_dev *usb_blkdev, u8 opcode,
/* Read / write a chunk of sectors on media */
static int usb_stor_blk_io(struct block_device *disk_dev,
- int sector_start, int sector_count, void *buffer,
+ sector_t sector_start, blkcnt_t sector_count, void *buffer,
bool read)
{
struct us_blk_dev *pblk_dev = container_of(disk_dev,
@@ -223,18 +223,18 @@ static int usb_stor_blk_io(struct block_device *disk_dev,
}
/* read / write the requested data */
- dev_dbg(dev, "%s %u block(s), starting from %d\n",
+ dev_dbg(dev, "%s %llu block(s), starting from %llu\n",
read ? "Read" : "Write",
sector_count, sector_start);
while (sector_count > 0) {
- unsigned n = min(sector_count, US_MAX_IO_BLK);
+ u16 n = min_t(blkcnt_t, sector_count, US_MAX_IO_BLK);
if (usb_stor_io_10(pblk_dev,
read ? SCSI_READ10 : SCSI_WRITE10,
sector_start,
buffer, n)) {
- dev_dbg(dev, "I/O error at sector %d\n", sector_start);
+ dev_dbg(dev, "I/O error at sector %llu\n", sector_start);
break;
}
sector_start += n;
@@ -247,14 +247,14 @@ static int usb_stor_blk_io(struct block_device *disk_dev,
/* Write a chunk of sectors to media */
static int __maybe_unused usb_stor_blk_write(struct block_device *blk,
- const void *buffer, int block, int num_blocks)
+ const void *buffer, sector_t block, blkcnt_t num_blocks)
{
return usb_stor_blk_io(blk, block, num_blocks, (void *)buffer, false);
}
/* Read a chunk of sectors from media */
-static int usb_stor_blk_read(struct block_device *blk, void *buffer, int block,
- int num_blocks)
+static int usb_stor_blk_read(struct block_device *blk, void *buffer, sector_t block,
+ blkcnt_t num_blocks)
{
return usb_stor_blk_io(blk, block, num_blocks, buffer, true);
}
@@ -305,17 +305,18 @@ static int usb_stor_init_blkdev(struct us_blk_dev *pblk_dev)
return result;
}
- if (last_lba > INT_MAX - 1) {
- last_lba = INT_MAX - 1;
+ if (last_lba == U32_MAX) {
+ last_lba = U32_MAX - 1;
dev_warn(dev,
- "Limiting device size due to 31 bit contraints\n");
+ "Limiting device size due to 32 bit constraints\n");
+ /* To support LBA >= U32_MAX, a READ CAPACITY (16) should be issued here */
}
pblk_dev->blk.num_blocks = last_lba + 1;
if (block_length != SECTOR_SIZE)
pr_warn("Support only %d bytes sectors\n", SECTOR_SIZE);
pblk_dev->blk.blockbits = SECTOR_SHIFT;
- dev_dbg(dev, "Capacity = 0x%x, blockshift = 0x%x\n",
+ dev_dbg(dev, "Capacity = 0x%llx, blockshift = 0x%x\n",
pblk_dev->blk.num_blocks, pblk_dev->blk.blockbits);
return 0;
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 9ec6ea4248..b6d468c63c 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -82,6 +82,7 @@ endif
config DRIVER_VIDEO_SDL
bool "SDL framebuffer driver"
depends on SANDBOX
+ select SDL
config DRIVER_VIDEO_PXA
bool "PXA27x framebuffer driver"
diff --git a/drivers/video/backlight-pwm.c b/drivers/video/backlight-pwm.c
index cae016be8f..4410c7d047 100644
--- a/drivers/video/backlight-pwm.c
+++ b/drivers/video/backlight-pwm.c
@@ -24,7 +24,7 @@
#include <regulator.h>
#include <gpio.h>
#include <of_gpio.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
struct pwm_backlight {
struct backlight_device backlight;
diff --git a/drivers/video/imx-ipu-fb.c b/drivers/video/imx-ipu-fb.c
index 18171bdd81..a3f195373b 100644
--- a/drivers/video/imx-ipu-fb.c
+++ b/drivers/video/imx-ipu-fb.c
@@ -23,7 +23,7 @@
#include <mach/imxfb.h>
#include <malloc.h>
#include <errno.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <mmu.h>
#include <mach/imx-ipu-fb.h>
#include <linux/clk.h>
diff --git a/drivers/video/imx-ipu-v3/imx-hdmi.c b/drivers/video/imx-ipu-v3/imx-hdmi.c
index 1e55c97d24..589ef5e32d 100644
--- a/drivers/video/imx-ipu-v3/imx-hdmi.c
+++ b/drivers/video/imx-ipu-v3/imx-hdmi.c
@@ -19,7 +19,7 @@
#include <init.h>
#include <linux/clk.h>
#include <linux/err.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <linux/clk.h>
#include <i2c/i2c.h>
#include <video/media-bus-format.h>
diff --git a/drivers/video/imx-ipu-v3/imx-ldb.c b/drivers/video/imx-ipu-v3/imx-ldb.c
index d7793bdc0e..1316237161 100644
--- a/drivers/video/imx-ipu-v3/imx-ldb.c
+++ b/drivers/video/imx-ipu-v3/imx-ldb.c
@@ -31,7 +31,7 @@
#include <mfd/imx6q-iomuxc-gpr.h>
#include <linux/clk.h>
#include <linux/err.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <linux/clk.h>
#include <mach/imx6-regs.h>
#include <mach/imx53-regs.h>
diff --git a/drivers/video/imx-ipu-v3/ipu-di.c b/drivers/video/imx-ipu-v3/ipu-di.c
index b4302412e0..97613207c9 100644
--- a/drivers/video/imx-ipu-v3/ipu-di.c
+++ b/drivers/video/imx-ipu-v3/ipu-di.c
@@ -15,7 +15,7 @@
#include <common.h>
#include <linux/err.h>
#include <linux/clk.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <malloc.h>
#include "imx-ipu-v3.h"
diff --git a/drivers/video/imx-ipu-v3/ipufb.c b/drivers/video/imx-ipu-v3/ipufb.c
index dd54d9df31..0b53916434 100644
--- a/drivers/video/imx-ipu-v3/ipufb.c
+++ b/drivers/video/imx-ipu-v3/ipufb.c
@@ -22,7 +22,7 @@
#include <of_graph.h>
#include <linux/clk.h>
#include <linux/err.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <video/media-bus-format.h>
#include "imx-ipu-v3.h"
diff --git a/drivers/video/imx.c b/drivers/video/imx.c
index d15c2d88fb..e93859775a 100644
--- a/drivers/video/imx.c
+++ b/drivers/video/imx.c
@@ -25,7 +25,7 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/sizes.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#define LCDC_SSA 0x00
diff --git a/drivers/video/pxa.c b/drivers/video/pxa.c
index d444e0981f..a2ff4bce2a 100644
--- a/drivers/video/pxa.c
+++ b/drivers/video/pxa.c
@@ -38,7 +38,7 @@
#include <mach/pxafb.h>
#include <asm/io.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
/* PXA LCD DMA descriptor */
struct pxafb_dma_descriptor {
diff --git a/drivers/video/sdl.c b/drivers/video/sdl.c
index 9811b2cf12..e9debc51b1 100644
--- a/drivers/video/sdl.c
+++ b/drivers/video/sdl.c
@@ -13,23 +13,25 @@
#include <errno.h>
#include <gui/graphic_utils.h>
+#define to_mask(color) GENMASK(color.length - 1, color.offset)
+
static void sdlfb_enable(struct fb_info *info)
{
- int ret;
-
- ret = sdl_open(info->xres, info->yres, info->bits_per_pixel,
- info->screen_base);
- if (ret)
- return;
- sdl_get_bitfield_rgba(&info->red, &info->green, &info->blue, &info->transp);
-
- sdl_start_timer();
+ struct sdl_fb_info sdl_info = {
+ .screen_base = info->screen_base,
+ .xres = info->xres, .yres = info->yres, .bpp = info->bits_per_pixel,
+ .rmask = to_mask(info->red),
+ .gmask = to_mask(info->green),
+ .bmask = to_mask(info->blue),
+ .amask = to_mask(info->transp),
+ };
+
+ sdl_video_open(&sdl_info);
}
static void sdlfb_disable(struct fb_info *info)
{
- sdl_stop_timer();
- sdl_close();
+ sdl_video_close();
}
static struct fb_ops sdlfb_ops = {
@@ -48,10 +50,19 @@ static int sdlfb_probe(struct device_d *dev)
fb = xzalloc(sizeof(*fb));
fb->modes.modes = fb->mode = dev->platform_data;
fb->modes.num_modes = 1;
- fb->bits_per_pixel = 4 << 3;
fb->xres = fb->mode->xres;
fb->yres = fb->mode->yres;
+ fb->bits_per_pixel = 32;
+ fb->transp.length = 8;
+ fb->red.length = 8;
+ fb->green.length = 8;
+ fb->blue.length = 8;
+ fb->transp.offset = 24;
+ fb->red.offset = 16;
+ fb->green.offset = 8;
+ fb->blue.offset = 0;
+
fb->priv = fb;
fb->fbops = &sdlfb_ops;
@@ -68,7 +79,6 @@ static int sdlfb_probe(struct device_d *dev)
kfree(fb->screen_base);
kfree(fb);
- sdl_close();
return ret;
}
@@ -78,7 +88,6 @@ static void sdlfb_remove(struct device_d *dev)
kfree(fb->screen_base);
kfree(fb);
- sdl_close();
}
static struct driver_d sdlfb_driver = {
diff --git a/drivers/video/tc358767.c b/drivers/video/tc358767.c
index e64dde1ddf..2a0fa8b368 100644
--- a/drivers/video/tc358767.c
+++ b/drivers/video/tc358767.c
@@ -31,7 +31,7 @@
#include <of_gpio.h>
#include <video/media-bus-format.h>
#include <video/vpl.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#define DP_LINK_BW_SET 0x100
#define DP_ENHANCED_FRAME_EN (1 << 7)
@@ -1191,8 +1191,7 @@ static int tc_read_edid(struct tc_data *tc)
#ifdef DEBUG
printk(KERN_DEBUG "eDP display EDID:\n");
- print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1, tc->edid,
- EDID_LENGTH, true);
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, tc->edid, EDID_LENGTH);
#endif
return 0;
diff --git a/drivers/watchdog/stpmic1_wdt.c b/drivers/watchdog/stpmic1_wdt.c
index 12280f1447..105ba39fb7 100644
--- a/drivers/watchdog/stpmic1_wdt.c
+++ b/drivers/watchdog/stpmic1_wdt.c
@@ -174,10 +174,6 @@ static int stpmic1_wdt_probe(struct device_d *dev)
wdd->set_timeout = stpmic1_wdt_set_timeout;
wdd->timeout_max = PMIC_WDT_MAX_TIMEOUT;
- /* have the watchdog reset, not power-off the system */
- regmap_write_bits(wdt->regmap, SWOFF_PWRCTRL_CR,
- RESTART_REQUEST_ENABLED, RESTART_REQUEST_ENABLED);
-
ret = watchdog_register(wdd);
if (ret) {
dev_err(dev, "Failed to register watchdog device\n");
diff --git a/drivers/watchdog/wd_core.c b/drivers/watchdog/wd_core.c
index 643c53268f..4b0ee31d5b 100644
--- a/drivers/watchdog/wd_core.c
+++ b/drivers/watchdog/wd_core.c
@@ -54,6 +54,9 @@ int watchdog_set_timeout(struct watchdog *wd, unsigned timeout)
if (ret)
return ret;
+ wd->last_ping = get_time_ns();
+ wd->timeout_cur = timeout;
+
wd->running = timeout ? WDOG_HW_RUNNING : WDOG_HW_NOT_RUNNING;
return 0;
@@ -155,6 +158,25 @@ static unsigned int dev_get_watchdog_priority(struct device_d *dev)
return priority;
}
+static int seconds_to_expire_get(struct param_d *p, void *priv)
+{
+ struct watchdog *wd = priv;
+ uint64_t diff;
+
+ if (!wd->timeout_cur) {
+ wd->seconds_to_expire = -1;
+ return 0;
+ }
+
+ diff = get_time_ns() - wd->last_ping;
+
+ do_div(diff, 1000000000);
+
+ wd->seconds_to_expire = wd->timeout_cur - diff;
+
+ return 0;
+}
+
int watchdog_register(struct watchdog *wd)
{
struct param_d *p;
@@ -218,6 +240,13 @@ int watchdog_register(struct watchdog *wd)
goto error_unregister;
}
+ p = dev_add_param_uint32(&wd->dev, "seconds_to_expire", param_set_readonly,
+ seconds_to_expire_get, &wd->seconds_to_expire, "%d", wd);
+ if (IS_ERR(p)) {
+ ret = PTR_ERR(p);
+ goto error_unregister;
+ }
+
list_add_tail(&wd->list, &watchdog_list);
pr_debug("registering watchdog %s with priority %d\n", watchdog_name(wd),