summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/adc/Kconfig16
-rw-r--r--drivers/adc/Makefile1
-rw-r--r--drivers/adc/adc-uclass.c35
-rw-r--r--drivers/adc/stm32-adc-core.c209
-rw-r--r--drivers/adc/stm32-adc-core.h51
-rw-r--r--drivers/adc/stm32-adc.c257
-rw-r--r--drivers/ata/sata_ceva.c87
-rw-r--r--drivers/bootcount/bootcount.c13
-rw-r--r--drivers/clk/clk-uclass.c8
-rw-r--r--drivers/clk/clk_sandbox_test.c13
-rw-r--r--drivers/core/device.c7
-rw-r--r--drivers/ddr/fsl/options.c14
-rw-r--r--drivers/gpio/hsdk-creg-gpio.c103
-rw-r--r--drivers/gpio/xilinx_gpio.c409
-rw-r--r--drivers/gpio/zynq_gpio.c77
-rw-r--r--drivers/i2c/imx_lpi2c.c47
-rw-r--r--drivers/i2c/muxes/pca954x.c9
-rw-r--r--drivers/mmc/arm_pl180_mmci.c73
-rw-r--r--drivers/mmc/arm_pl180_mmci.h1
-rw-r--r--drivers/mmc/sunxi_mmc.c13
-rw-r--r--drivers/mtd/nand/nand_base.c4
-rw-r--r--drivers/mtd/nand/sunxi_nand.c2
-rw-r--r--drivers/mtd/spi/Kconfig5
-rw-r--r--drivers/mtd/spi/spi_flash_ids.c1
-rw-r--r--drivers/net/Kconfig5
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/cpsw.c2
-rw-r--r--drivers/net/mvgbe.c416
-rw-r--r--drivers/net/mvgbe.h16
-rw-r--r--drivers/net/phy/atheros.c1
-rw-r--r--drivers/net/phy/broadcom.c1
-rw-r--r--drivers/net/phy/davicom.c1
-rw-r--r--drivers/net/phy/generic_10g.c2
-rw-r--r--drivers/net/phy/lxt.c1
-rw-r--r--drivers/net/phy/marvell.c1
-rw-r--r--drivers/net/phy/micrel_ksz8xxx.c1
-rw-r--r--drivers/net/phy/micrel_ksz90x1.c2
-rw-r--r--drivers/net/phy/natsemi.c1
-rw-r--r--drivers/net/phy/phy.c6
-rw-r--r--drivers/net/phy/realtek.c1
-rw-r--r--drivers/net/phy/smsc.c1
-rw-r--r--drivers/net/phy/teranetics.c1
-rw-r--r--drivers/net/phy/ti.c41
-rw-r--r--drivers/net/phy/vitesse.c1
-rw-r--r--drivers/net/phy/xilinx_phy.c10
-rw-r--r--drivers/net/sandbox-raw-bus.c66
-rw-r--r--drivers/net/sandbox-raw.c53
-rw-r--r--drivers/net/sandbox.c16
-rw-r--r--drivers/net/zynq_gem.c30
-rw-r--r--drivers/phy/allwinner/phy-sun4i-usb.c10
-rw-r--r--drivers/power/domain/Makefile2
-rw-r--r--drivers/power/pmic/Kconfig2
-rw-r--r--drivers/rtc/at91sam9_rtt.c4
-rw-r--r--drivers/rtc/davinci.c2
-rw-r--r--drivers/rtc/ds1302.c4
-rw-r--r--drivers/rtc/ds1306.c4
-rw-r--r--drivers/rtc/ds1307.c4
-rw-r--r--drivers/rtc/ds1337.c4
-rw-r--r--drivers/rtc/ds1374.c3
-rw-r--r--drivers/rtc/ds164x.c4
-rw-r--r--drivers/rtc/ds174x.c4
-rw-r--r--drivers/rtc/ds3231.c4
-rw-r--r--drivers/rtc/imxdi.c4
-rw-r--r--drivers/rtc/m41t11.c3
-rw-r--r--drivers/rtc/m41t60.c3
-rw-r--r--drivers/rtc/m41t62.c4
-rw-r--r--drivers/rtc/m48t35ax.c4
-rw-r--r--drivers/rtc/max6900.c4
-rw-r--r--drivers/rtc/mc146818.c6
-rw-r--r--drivers/rtc/mcfrtc.c4
-rw-r--r--drivers/rtc/mk48t59.c4
-rw-r--r--drivers/rtc/pcf8563.c4
-rw-r--r--drivers/rtc/rs5c372.c3
-rw-r--r--drivers/rtc/rx8025.c4
-rw-r--r--drivers/rtc/s3c24x0_rtc.c4
-rw-r--r--drivers/rtc/x1205.c4
-rw-r--r--drivers/serial/sandbox.c4
-rw-r--r--drivers/spi/Kconfig5
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/kirkwood_spi.c16
-rw-r--r--drivers/spi/sun4i_spi.c456
-rw-r--r--drivers/tpm/Kconfig13
-rw-r--r--drivers/tpm/tpm-uclass.c3
-rw-r--r--drivers/tpm/tpm2_tis_sandbox.c5
-rw-r--r--drivers/tpm/tpm2_tis_spi.c4
-rw-r--r--drivers/video/Kconfig1
-rw-r--r--drivers/video/panel-uclass.c11
-rw-r--r--drivers/video/sunxi/sunxi_de2.c3
89 files changed, 1990 insertions, 771 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 276e5ee4d7..d53208540e 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_ARMADA_XP) += ddr/marvell/axp/
obj-$(CONFIG_ALTERA_SDRAM) += ddr/altera/
obj-$(CONFIG_SPL_POWER_SUPPORT) += power/ power/pmic/
obj-$(CONFIG_SPL_POWER_SUPPORT) += power/regulator/
+obj-$(CONFIG_SPL_POWER_DOMAIN) += power/domain/
obj-$(CONFIG_SPL_DM_RESET) += reset/
obj-$(CONFIG_SPL_MTD_SUPPORT) += mtd/
obj-$(CONFIG_SPL_ONENAND_SUPPORT) += mtd/onenand/
diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig
index 93e27f131c..e719c38bb3 100644
--- a/drivers/adc/Kconfig
+++ b/drivers/adc/Kconfig
@@ -47,3 +47,19 @@ config SARADC_ROCKCHIP
- 2~6 analog input channels
- 1O or 12 bits resolution
- Up to 1MSPS of sample rate
+
+config STM32_ADC
+ bool "Enable STMicroelectronics STM32 ADC driver"
+ depends on ADC && (STM32H7 || ARCH_STM32MP)
+ help
+ This enables driver for STMicroelectronics STM32 analog-to-digital
+ converter (ADC).
+ A STM32 ADC block can be composed of several individual ADCs.
+ Each has its own private registers, but shares some resources:
+ - clock selection and prescaler
+ - voltage reference
+ - common registers area.
+ STM32 ADC driver is composed of:
+ - core driver to deal with common resources
+ - child driver to deal with individual ADC resources (declare ADC
+ device and associated channels, start/stop conversions)
diff --git a/drivers/adc/Makefile b/drivers/adc/Makefile
index 95c93d4c57..cca0fecd59 100644
--- a/drivers/adc/Makefile
+++ b/drivers/adc/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_ADC_EXYNOS) += exynos-adc.o
obj-$(CONFIG_ADC_SANDBOX) += sandbox.o
obj-$(CONFIG_SARADC_ROCKCHIP) += rockchip-saradc.o
obj-$(CONFIG_SARADC_MESON) += meson-saradc.o
+obj-$(CONFIG_STM32_ADC) += stm32-adc.o stm32-adc-core.o
diff --git a/drivers/adc/adc-uclass.c b/drivers/adc/adc-uclass.c
index 17c1a4e52a..738c1eabdc 100644
--- a/drivers/adc/adc-uclass.c
+++ b/drivers/adc/adc-uclass.c
@@ -264,10 +264,8 @@ static int adc_vdd_platdata_update(struct udevice *dev)
* will bind before its supply regulator device, then the below 'get'
* will return an error.
*/
- ret = device_get_supply_regulator(dev, "vdd-supply",
- &uc_pdata->vdd_supply);
- if (ret)
- return ret;
+ if (!uc_pdata->vdd_supply)
+ return 0;
ret = regulator_get_value(uc_pdata->vdd_supply);
if (ret < 0)
@@ -283,10 +281,8 @@ static int adc_vss_platdata_update(struct udevice *dev)
struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
int ret;
- ret = device_get_supply_regulator(dev, "vss-supply",
- &uc_pdata->vss_supply);
- if (ret)
- return ret;
+ if (!uc_pdata->vss_supply)
+ return 0;
ret = regulator_get_value(uc_pdata->vss_supply);
if (ret < 0)
@@ -302,14 +298,11 @@ int adc_vdd_value(struct udevice *dev, int *uV)
struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
int ret, value_sign = uc_pdata->vdd_polarity_negative ? -1 : 1;
- if (!uc_pdata->vdd_supply)
- goto nodev;
-
/* Update the regulator Value. */
ret = adc_vdd_platdata_update(dev);
if (ret)
return ret;
-nodev:
+
if (uc_pdata->vdd_microvolts == -ENODATA)
return -ENODATA;
@@ -323,14 +316,11 @@ int adc_vss_value(struct udevice *dev, int *uV)
struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
int ret, value_sign = uc_pdata->vss_polarity_negative ? -1 : 1;
- if (!uc_pdata->vss_supply)
- goto nodev;
-
/* Update the regulator Value. */
ret = adc_vss_platdata_update(dev);
if (ret)
return ret;
-nodev:
+
if (uc_pdata->vss_microvolts == -ENODATA)
return -ENODATA;
@@ -348,7 +338,12 @@ static int adc_vdd_platdata_set(struct udevice *dev)
prop = "vdd-polarity-negative";
uc_pdata->vdd_polarity_negative = dev_read_bool(dev, prop);
- ret = adc_vdd_platdata_update(dev);
+ /* Optionally get regulators */
+ ret = device_get_supply_regulator(dev, "vdd-supply",
+ &uc_pdata->vdd_supply);
+ if (!ret)
+ return adc_vdd_platdata_update(dev);
+
if (ret != -ENOENT)
return ret;
@@ -368,7 +363,11 @@ static int adc_vss_platdata_set(struct udevice *dev)
prop = "vss-polarity-negative";
uc_pdata->vss_polarity_negative = dev_read_bool(dev, prop);
- ret = adc_vss_platdata_update(dev);
+ ret = device_get_supply_regulator(dev, "vss-supply",
+ &uc_pdata->vss_supply);
+ if (!ret)
+ return adc_vss_platdata_update(dev);
+
if (ret != -ENOENT)
return ret;
diff --git a/drivers/adc/stm32-adc-core.c b/drivers/adc/stm32-adc-core.c
new file mode 100644
index 0000000000..a9aa143bfe
--- /dev/null
+++ b/drivers/adc/stm32-adc-core.c
@@ -0,0 +1,209 @@
+// 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 <asm/io.h>
+#include <power/regulator.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 udevice *dev,
+ struct stm32_adc_common *common)
+{
+ u32 ckmode, presc;
+ unsigned long rate;
+ int i, div;
+
+ /* stm32h7 bus clock is common for all ADC instances (mandatory) */
+ if (!clk_valid(&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 (clk_valid(&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 udevice *dev)
+{
+ struct stm32_adc_common *common = dev_get_priv(dev);
+ int ret;
+
+ common->base = dev_read_addr_ptr(dev);
+ if (!common->base) {
+ dev_err(dev, "can't get address\n");
+ return -ENOENT;
+ }
+
+ ret = device_get_supply_regulator(dev, "vref-supply", &common->vref);
+ if (ret) {
+ dev_err(dev, "can't get vref-supply: %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_get_value(common->vref);
+ if (ret < 0) {
+ dev_err(dev, "can't get vref-supply value: %d\n", ret);
+ return ret;
+ }
+ common->vref_uv = ret;
+
+ ret = clk_get_by_name(dev, "adc", &common->aclk);
+ if (!ret) {
+ ret = clk_enable(&common->aclk);
+ if (ret) {
+ dev_err(dev, "Can't enable aclk: %d\n", ret);
+ return ret;
+ }
+ }
+
+ ret = clk_get_by_name(dev, "bus", &common->bclk);
+ if (!ret) {
+ ret = clk_enable(&common->bclk);
+ if (ret) {
+ dev_err(dev, "Can't enable bclk: %d\n", ret);
+ goto err_aclk_disable;
+ }
+ }
+
+ ret = stm32h7_adc_clk_sel(dev, common);
+ if (ret)
+ goto err_bclk_disable;
+
+ return ret;
+
+err_bclk_disable:
+ if (clk_valid(&common->bclk))
+ clk_disable(&common->bclk);
+
+err_aclk_disable:
+ if (clk_valid(&common->aclk))
+ clk_disable(&common->aclk);
+
+ return ret;
+}
+
+static const struct udevice_id stm32_adc_core_ids[] = {
+ { .compatible = "st,stm32h7-adc-core" },
+ { .compatible = "st,stm32mp1-adc-core" },
+ {}
+};
+
+U_BOOT_DRIVER(stm32_adc_core) = {
+ .name = "stm32-adc-core",
+ .id = UCLASS_SIMPLE_BUS,
+ .of_match = stm32_adc_core_ids,
+ .probe = stm32_adc_core_probe,
+ .priv_auto_alloc_size = sizeof(struct stm32_adc_common),
+};
diff --git a/drivers/adc/stm32-adc-core.h b/drivers/adc/stm32-adc-core.h
new file mode 100644
index 0000000000..ba0e10e6cc
--- /dev/null
+++ b/drivers/adc/stm32-adc-core.h
@@ -0,0 +1,51 @@
+/* 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 <common.h>
+#include <clk.h>
+#include <dm.h>
+
+/**
+ * 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 udevice *vref;
+ int vref_uv;
+};
+
+#endif
diff --git a/drivers/adc/stm32-adc.c b/drivers/adc/stm32-adc.c
new file mode 100644
index 0000000000..e108062f2f
--- /dev/null
+++ b/drivers/adc/stm32-adc.c
@@ -0,0 +1,257 @@
+// 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 <adc.h>
+#include <asm/io.h>
+#include <linux/iopoll.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_TIMEOUT_US 100000
+
+struct stm32_adc_cfg {
+ unsigned int max_channels;
+ unsigned int num_bits;
+ bool has_vregready;
+};
+
+struct stm32_adc {
+ void __iomem *regs;
+ int active_channel;
+ const struct stm32_adc_cfg *cfg;
+};
+
+static int stm32_adc_stop(struct udevice *dev)
+{
+ struct stm32_adc *adc = dev_get_priv(dev);
+
+ 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);
+ adc->active_channel = -1;
+
+ return 0;
+}
+
+static int stm32_adc_start_channel(struct udevice *dev, int channel)
+{
+ struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+ struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev));
+ struct stm32_adc *adc = dev_get_priv(dev);
+ int ret;
+ u32 val;
+
+ /* 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(dev);
+ 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(dev);
+ dev_err(dev, "Failed to enable ADC: %d\n", ret);
+ return ret;
+ }
+
+ /* Preselect channels */
+ writel(uc_pdata->channel_mask, adc->regs + STM32H7_ADC_PCSEL);
+
+ /* Set sampling time to max value by default */
+ writel(0xffffffff, adc->regs + STM32H7_ADC_SMPR1);
+ writel(0xffffffff, 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);
+ adc->active_channel = channel;
+
+ return 0;
+}
+
+static int stm32_adc_channel_data(struct udevice *dev, int channel,
+ unsigned int *data)
+{
+ struct stm32_adc *adc = dev_get_priv(dev);
+ int ret;
+ u32 val;
+
+ if (channel != adc->active_channel) {
+ dev_err(dev, "Requested channel is not active!\n");
+ return -EINVAL;
+ }
+
+ 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_chan_of_init(struct udevice *dev)
+{
+ struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+ struct stm32_adc *adc = dev_get_priv(dev);
+ u32 chans[STM32_ADC_CH_MAX];
+ int i, num_channels, ret;
+
+ /* Retrieve single ended channels listed in device tree */
+ num_channels = dev_read_size(dev, "st,adc-channels");
+ if (num_channels < 0) {
+ dev_err(dev, "can't get st,adc-channels: %d\n", num_channels);
+ return num_channels;
+ }
+ num_channels /= sizeof(u32);
+
+ if (num_channels > adc->cfg->max_channels) {
+ dev_err(dev, "too many st,adc-channels: %d\n", num_channels);
+ return -EINVAL;
+ }
+
+ ret = dev_read_u32_array(dev, "st,adc-channels", chans, num_channels);
+ if (ret < 0) {
+ dev_err(dev, "can't read st,adc-channels: %d\n", ret);
+ return ret;
+ }
+
+ for (i = 0; i < num_channels; i++) {
+ if (chans[i] >= adc->cfg->max_channels) {
+ dev_err(dev, "bad channel %u\n", chans[i]);
+ return -EINVAL;
+ }
+ uc_pdata->channel_mask |= 1 << chans[i];
+ }
+
+ uc_pdata->data_mask = (1 << adc->cfg->num_bits) - 1;
+ uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
+ uc_pdata->data_timeout_us = 100000;
+
+ return 0;
+}
+
+static int stm32_adc_probe(struct udevice *dev)
+{
+ struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+ struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev));
+ struct stm32_adc *adc = dev_get_priv(dev);
+ int offset;
+
+ offset = dev_read_u32_default(dev, "reg", -ENODATA);
+ if (offset < 0) {
+ dev_err(dev, "Can't read reg property\n");
+ return offset;
+ }
+ adc->regs = common->base + offset;
+ adc->cfg = (const struct stm32_adc_cfg *)dev_get_driver_data(dev);
+
+ /* VDD supplied by common vref pin */
+ uc_pdata->vdd_supply = common->vref;
+ uc_pdata->vdd_microvolts = common->vref_uv;
+ uc_pdata->vss_microvolts = 0;
+
+ return stm32_adc_chan_of_init(dev);
+}
+
+static const struct adc_ops stm32_adc_ops = {
+ .start_channel = stm32_adc_start_channel,
+ .channel_data = stm32_adc_channel_data,
+ .stop = stm32_adc_stop,
+};
+
+static const struct stm32_adc_cfg stm32h7_adc_cfg = {
+ .num_bits = 16,
+ .max_channels = STM32_ADC_CH_MAX,
+};
+
+static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
+ .num_bits = 16,
+ .max_channels = STM32_ADC_CH_MAX,
+ .has_vregready = true,
+};
+
+static const struct udevice_id stm32_adc_ids[] = {
+ { .compatible = "st,stm32h7-adc",
+ .data = (ulong)&stm32h7_adc_cfg },
+ { .compatible = "st,stm32mp1-adc",
+ .data = (ulong)&stm32mp1_adc_cfg },
+ {}
+};
+
+U_BOOT_DRIVER(stm32_adc) = {
+ .name = "stm32-adc",
+ .id = UCLASS_ADC,
+ .of_match = stm32_adc_ids,
+ .probe = stm32_adc_probe,
+ .ops = &stm32_adc_ops,
+ .priv_auto_alloc_size = sizeof(struct stm32_adc),
+};
diff --git a/drivers/ata/sata_ceva.c b/drivers/ata/sata_ceva.c
index a7d45e81cf..047cff7f83 100644
--- a/drivers/ata/sata_ceva.c
+++ b/drivers/ata/sata_ceva.c
@@ -7,8 +7,6 @@
#include <dm.h>
#include <ahci.h>
#include <scsi.h>
-#include <asm/arch/hardware.h>
-
#include <asm/io.h>
/* Vendor Specific Register Offsets */
@@ -18,6 +16,7 @@
#define AHCI_VEND_PP3C 0xB0
#define AHCI_VEND_PP4C 0xB4
#define AHCI_VEND_PP5C 0xB8
+#define AHCI_VEND_AXICC 0xBc
#define AHCI_VEND_PAXIC 0xC0
#define AHCI_VEND_PTC 0xC8
@@ -72,45 +71,57 @@
#define DRV_NAME "ahci-ceva"
#define CEVA_FLAG_BROKEN_GEN2 1
+/* flag bit definition */
+#define FLAG_COHERENT 1
+
+/* register config value */
+#define CEVA_PHY1_CFG 0xa003fffe
+#define CEVA_PHY2_CFG 0x28184d1f
+#define CEVA_PHY3_CFG 0x0e081509
+#define CEVA_TRANS_CFG 0x08000029
+#define CEVA_AXICC_CFG 0x3fffffff
+
+/* ecc addr-val pair */
+#define ECC_DIS_ADDR_CH2 0x80000000
+#define ECC_DIS_VAL_CH2 0x20140520
+
+enum ceva_soc {
+ CEVA_1V84,
+ CEVA_LS1012A,
+};
+
struct ceva_sata_priv {
ulong base;
+ enum ceva_soc soc;
+ ulong flag;
};
-static int ceva_init_sata(ulong mmio)
+static int ceva_init_sata(struct ceva_sata_priv *priv)
{
+ ulong base = priv->base;
ulong tmp;
- int i;
-
- /*
- * AXI Data bus width to 64
- * Set Mem Addr Read, Write ID for data transfers
- * Transfer limit to 72 DWord
- */
- tmp = PAXIC_ADBW_BW64 | PAXIC_MAWIDD | PAXIC_MARIDD | PAXIC_OTL;
- writel(tmp, mmio + AHCI_VEND_PAXIC);
-
- /* Set AHCI Enable */
- tmp = readl(mmio + HOST_CTL);
- tmp |= HOST_AHCI_EN;
- writel(tmp, mmio + HOST_CTL);
-
- for (i = 0; i < NR_PORTS; i++) {
- /* TPSS TPRS scalars, CISE and Port Addr */
- tmp = PCFG_TPSS_VAL | PCFG_TPRS_VAL | (PCFG_PAD_VAL + i);
- writel(tmp, mmio + AHCI_VEND_PCFG);
-
- /* Port Phy Cfg register enables */
- tmp = PPCFG_TTA | PPCFG_PSS_EN | PPCFG_ESDF_EN;
- writel(tmp, mmio + AHCI_VEND_PPCFG);
- /* Rx Watermark setting */
+ switch (priv->soc) {
+ case CEVA_1V84:
+ tmp = PAXIC_ADBW_BW64 | PAXIC_MAWIDD | PAXIC_MARIDD | PAXIC_OTL;
+ writel(tmp, base + AHCI_VEND_PAXIC);
+ tmp = PCFG_TPSS_VAL | PCFG_TPRS_VAL | PCFG_PAD_VAL;
+ writel(tmp, base + AHCI_VEND_PCFG);
+ tmp = PPCFG_TTA | PPCFG_PSS_EN | PPCFG_ESDF_EN;
+ writel(tmp, base + AHCI_VEND_PPCFG);
tmp = PTC_RX_WM_VAL | PTC_RSVD;
- writel(tmp, mmio + AHCI_VEND_PTC);
-
- /* Default to Gen 2 Speed and Gen 1 if Gen2 is broken */
- tmp = PORT_SCTL_SPD_GEN3 | PORT_SCTL_IPM;
- writel(tmp, mmio + PORT_SCR_CTL + PORT_BASE + PORT_OFFSET * i);
+ writel(tmp, base + AHCI_VEND_PTC);
+ break;
+
+ case CEVA_LS1012A:
+ writel(ECC_DIS_ADDR_CH2, ECC_DIS_VAL_CH2);
+ writel(CEVA_PHY1_CFG, base + AHCI_VEND_PPCFG);
+ writel(CEVA_TRANS_CFG, base + AHCI_VEND_PTC);
+ if (priv->flag & FLAG_COHERENT)
+ writel(CEVA_AXICC_CFG, base + AHCI_VEND_AXICC);
+ break;
}
+
return 0;
}
@@ -125,13 +136,14 @@ static int sata_ceva_probe(struct udevice *dev)
{
struct ceva_sata_priv *priv = dev_get_priv(dev);
- ceva_init_sata(priv->base);
+ ceva_init_sata(priv);
return ahci_probe_scsi(dev, priv->base);
}
static const struct udevice_id sata_ceva_ids[] = {
- { .compatible = "ceva,ahci-1v84" },
+ { .compatible = "ceva,ahci-1v84", .data = CEVA_1V84 },
+ { .compatible = "fsl,ls1012a-ahci", .data = CEVA_LS1012A },
{ }
};
@@ -139,10 +151,15 @@ static int sata_ceva_ofdata_to_platdata(struct udevice *dev)
{
struct ceva_sata_priv *priv = dev_get_priv(dev);
- priv->base = devfdt_get_addr(dev);
+ if (dev_read_bool(dev, "dma-coherent"))
+ priv->flag |= FLAG_COHERENT;
+
+ priv->base = dev_read_addr(dev);
if (priv->base == FDT_ADDR_T_NONE)
return -EINVAL;
+ priv->soc = dev_get_driver_data(dev);
+
return 0;
}
diff --git a/drivers/bootcount/bootcount.c b/drivers/bootcount/bootcount.c
index a3162c97ed..646c563f8a 100644
--- a/drivers/bootcount/bootcount.c
+++ b/drivers/bootcount/bootcount.c
@@ -11,16 +11,23 @@
__weak void bootcount_store(ulong a)
{
void *reg = (void *)CONFIG_SYS_BOOTCOUNT_ADDR;
+ uintptr_t flush_start = rounddown(CONFIG_SYS_BOOTCOUNT_ADDR,
+ CONFIG_SYS_CACHELINE_SIZE);
+ uintptr_t flush_end;
#if defined(CONFIG_SYS_BOOTCOUNT_SINGLEWORD)
raw_bootcount_store(reg, (BOOTCOUNT_MAGIC & 0xffff0000) | a);
+
+ flush_end = roundup(CONFIG_SYS_BOOTCOUNT_ADDR + 4,
+ CONFIG_SYS_CACHELINE_SIZE);
#else
raw_bootcount_store(reg, a);
raw_bootcount_store(reg + 4, BOOTCOUNT_MAGIC);
+
+ flush_end = roundup(CONFIG_SYS_BOOTCOUNT_ADDR + 8,
+ CONFIG_SYS_CACHELINE_SIZE);
#endif /* defined(CONFIG_SYS_BOOTCOUNT_SINGLEWORD */
- flush_dcache_range(CONFIG_SYS_BOOTCOUNT_ADDR,
- CONFIG_SYS_BOOTCOUNT_ADDR +
- CONFIG_SYS_CACHELINE_SIZE);
+ flush_dcache_range(flush_start, flush_end);
}
__weak ulong bootcount_load(void)
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 419d4515ac..2b15978e14 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -154,6 +154,10 @@ static int clk_set_default_parents(struct udevice *dev)
for (index = 0; index < num_parents; index++) {
ret = clk_get_by_indexed_prop(dev, "assigned-clock-parents",
index, &parent_clk);
+ /* If -ENOENT, this is a no-op entry */
+ if (ret == -ENOENT)
+ continue;
+
if (ret) {
debug("%s: could not get parent clock %d for %s\n",
__func__, index, dev_read_name(dev));
@@ -210,6 +214,10 @@ static int clk_set_default_rates(struct udevice *dev)
goto fail;
for (index = 0; index < num_rates; index++) {
+ /* If 0 is passed, this is a no-op */
+ if (!rates[index])
+ continue;
+
ret = clk_get_by_indexed_prop(dev, "assigned-clocks",
index, &clk);
if (ret) {
diff --git a/drivers/clk/clk_sandbox_test.c b/drivers/clk/clk_sandbox_test.c
index 8cd4abb84f..e8465dbfad 100644
--- a/drivers/clk/clk_sandbox_test.c
+++ b/drivers/clk/clk_sandbox_test.c
@@ -116,6 +116,19 @@ int sandbox_clk_test_release_bulk(struct udevice *dev)
return clk_release_bulk(&sbct->bulk);
}
+int sandbox_clk_test_valid(struct udevice *dev)
+{
+ struct sandbox_clk_test *sbct = dev_get_priv(dev);
+ int i;
+
+ for (i = 0; i < SANDBOX_CLK_TEST_ID_COUNT; i++) {
+ if (!clk_valid(&sbct->clks[i]))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static const struct udevice_id sandbox_clk_test_ids[] = {
{ .compatible = "sandbox,clk-test" },
{ }
diff --git a/drivers/core/device.c b/drivers/core/device.c
index d5f5fc31b0..207d566b71 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -26,6 +26,7 @@
#include <dm/util.h>
#include <linux/err.h>
#include <linux/list.h>
+#include <power-domain.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -304,6 +305,7 @@ static void *alloc_priv(int size, uint flags)
int device_probe(struct udevice *dev)
{
+ struct power_domain pd;
const struct driver *drv;
int size = 0;
int ret;
@@ -383,6 +385,11 @@ int device_probe(struct udevice *dev)
if (dev->parent && device_get_uclass_id(dev) != UCLASS_PINCTRL)
pinctrl_select_state(dev, "default");
+ if (dev->parent && device_get_uclass_id(dev) != UCLASS_POWER_DOMAIN) {
+ if (!power_domain_get(dev, &pd))
+ power_domain_on(&pd);
+ }
+
ret = uclass_pre_probe_device(dev);
if (ret)
goto fail;
diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c
index 5f2acb1c9d..7639a8b3dd 100644
--- a/drivers/ddr/fsl/options.c
+++ b/drivers/ddr/fsl/options.c
@@ -742,8 +742,7 @@ unsigned int populate_memctl_options(const common_timing_params_t *common_dimm,
unsigned int ctrl_num)
{
unsigned int i;
- char buffer[HWCONFIG_BUFFER_SIZE];
- char *buf = NULL;
+ char buf[HWCONFIG_BUFFER_SIZE];
#if defined(CONFIG_SYS_FSL_DDR3) || \
defined(CONFIG_SYS_FSL_DDR2) || \
defined(CONFIG_SYS_FSL_DDR4)
@@ -757,8 +756,8 @@ unsigned int populate_memctl_options(const common_timing_params_t *common_dimm,
* Extract hwconfig from environment since we have not properly setup
* the environment but need it for ddr config params
*/
- if (env_get_f("hwconfig", buffer, sizeof(buffer)) > 0)
- buf = buffer;
+ if (env_get_f("hwconfig", buf, sizeof(buf)) < 0)
+ buf[0] = '\0';
#if defined(CONFIG_SYS_FSL_DDR3) || \
defined(CONFIG_SYS_FSL_DDR2) || \
@@ -1398,15 +1397,14 @@ int fsl_use_spd(void)
int use_spd = 0;
#ifdef CONFIG_DDR_SPD
- char buffer[HWCONFIG_BUFFER_SIZE];
- char *buf = NULL;
+ char buf[HWCONFIG_BUFFER_SIZE];
/*
* Extract hwconfig from environment since we have not properly setup
* the environment but need it for ddr config params
*/
- if (env_get_f("hwconfig", buffer, sizeof(buffer)) > 0)
- buf = buffer;
+ if (env_get_f("hwconfig", buf, sizeof(buf)) < 0)
+ buf[0] = '\0';
/* if hwconfig is not enabled, or "sdram" is not defined, use spd */
if (hwconfig_sub_f("fsl_ddr", "sdram", buf)) {
diff --git a/drivers/gpio/hsdk-creg-gpio.c b/drivers/gpio/hsdk-creg-gpio.c
index 084a2da652..800027f18e 100644
--- a/drivers/gpio/hsdk-creg-gpio.c
+++ b/drivers/gpio/hsdk-creg-gpio.c
@@ -16,25 +16,24 @@
#include <errno.h>
#include <linux/printk.h>
-#define HSDK_CREG_MAX_GPIO 8
-
-#define GPIO_ACTIVATE 0x2
-#define GPIO_DEACTIVATE 0x3
-#define GPIO_PIN_MASK 0x3
-#define BIT_PER_GPIO 2
+#define DRV_NAME "gpio_creg"
struct hsdk_creg_gpio {
- uint32_t *regs;
+ u32 *regs;
+ u8 shift;
+ u8 activate;
+ u8 deactivate;
+ u8 bit_per_gpio;
};
static int hsdk_creg_gpio_set_value(struct udevice *dev, unsigned oft, int val)
{
struct hsdk_creg_gpio *hcg = dev_get_priv(dev);
- uint32_t reg = readl(hcg->regs);
- uint32_t cmd = val ? GPIO_DEACTIVATE : GPIO_ACTIVATE;
+ u8 reg_shift = oft * hcg->bit_per_gpio + hcg->shift;
+ u32 reg = readl(hcg->regs);
- reg &= ~(GPIO_PIN_MASK << (oft * BIT_PER_GPIO));
- reg |= (cmd << (oft * BIT_PER_GPIO));
+ reg &= ~(GENMASK(hcg->bit_per_gpio - 1, 0) << reg_shift);
+ reg |= ((val ? hcg->deactivate : hcg->activate) << reg_shift);
writel(reg, hcg->regs);
@@ -51,7 +50,9 @@ static int hsdk_creg_gpio_direction_output(struct udevice *dev, unsigned oft,
static int hsdk_creg_gpio_direction_input(struct udevice *dev, unsigned oft)
{
- pr_err("hsdk-creg-gpio can't be used as input!\n");
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+ pr_err("%s can't be used as input!\n", uc_priv->bank_name);
return -ENOTSUPP;
}
@@ -59,10 +60,11 @@ static int hsdk_creg_gpio_direction_input(struct udevice *dev, unsigned oft)
static int hsdk_creg_gpio_get_value(struct udevice *dev, unsigned int oft)
{
struct hsdk_creg_gpio *hcg = dev_get_priv(dev);
- uint32_t val = readl(hcg->regs);
+ u32 val = readl(hcg->regs);
- val = (val >> (oft * BIT_PER_GPIO)) & GPIO_PIN_MASK;
- return (val == GPIO_DEACTIVATE) ? 1 : 0;
+ val >>= oft * hcg->bit_per_gpio + hcg->shift;
+ val &= GENMASK(hcg->bit_per_gpio - 1, 0);
+ return (val == hcg->deactivate) ? 1 : 0;
}
static const struct dm_gpio_ops hsdk_creg_gpio_ops = {
@@ -76,17 +78,74 @@ static int hsdk_creg_gpio_probe(struct udevice *dev)
{
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
struct hsdk_creg_gpio *hcg = dev_get_priv(dev);
+ u32 shift, bit_per_gpio, activate, deactivate, gpio_count;
+ const u8 *defaults;
- hcg->regs = (uint32_t *)devfdt_get_addr_ptr(dev);
-
- uc_priv->gpio_count = dev_read_u32_default(dev, "gpio-count", 1);
- if (uc_priv->gpio_count > HSDK_CREG_MAX_GPIO)
- uc_priv->gpio_count = HSDK_CREG_MAX_GPIO;
+ hcg->regs = (u32 *)devfdt_get_addr_ptr(dev);
+ gpio_count = dev_read_u32_default(dev, "gpio-count", 1);
+ shift = dev_read_u32_default(dev, "gpio-first-shift", 0);
+ bit_per_gpio = dev_read_u32_default(dev, "gpio-bit-per-line", 1);
+ activate = dev_read_u32_default(dev, "gpio-activate-val", 1);
+ deactivate = dev_read_u32_default(dev, "gpio-deactivate-val", 0);
+ defaults = dev_read_u8_array_ptr(dev, "gpio-default-val", gpio_count);
uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name");
if (!uc_priv->bank_name)
uc_priv->bank_name = dev_read_name(dev);
+ if (!bit_per_gpio) {
+ pr_err("%s: 'gpio-bit-per-line' can't be 0\n",
+ uc_priv->bank_name);
+
+ return -EINVAL;
+ }
+
+ if (!gpio_count) {
+ pr_err("%s: 'gpio-count' can't be 0\n",
+ uc_priv->bank_name);
+
+ return -EINVAL;
+ }
+
+ if ((gpio_count * bit_per_gpio + shift) > 32) {
+ pr_err("%s: u32 io register overflow: try to use %u bits\n",
+ uc_priv->bank_name, gpio_count * bit_per_gpio + shift);
+
+ return -EINVAL;
+ }
+
+ if (GENMASK(31, bit_per_gpio) & activate) {
+ pr_err("%s: 'gpio-activate-val' can't be more than %lu\n",
+ uc_priv->bank_name, GENMASK(bit_per_gpio - 1, 0));
+
+ return -EINVAL;
+ }
+
+ if (GENMASK(31, bit_per_gpio) & deactivate) {
+ pr_err("%s: 'gpio-deactivate-val' can't be more than %lu\n",
+ uc_priv->bank_name, GENMASK(bit_per_gpio - 1, 0));
+
+ return -EINVAL;
+ }
+
+ if (activate == deactivate) {
+ pr_err("%s: 'gpio-deactivate-val' and 'gpio-activate-val' can't be equal\n",
+ uc_priv->bank_name);
+
+ return -EINVAL;
+ }
+
+ hcg->shift = (u8)shift;
+ hcg->bit_per_gpio = (u8)bit_per_gpio;
+ hcg->activate = (u8)activate;
+ hcg->deactivate = (u8)deactivate;
+ uc_priv->gpio_count = gpio_count;
+
+ /* Setup default GPIO value if we have "gpio-default-val" array */
+ if (defaults)
+ for (u8 i = 0; i < gpio_count; i++)
+ hsdk_creg_gpio_set_value(dev, i, defaults[i]);
+
pr_debug("%s GPIO [0x%p] controller with %d gpios probed\n",
uc_priv->bank_name, hcg->regs, uc_priv->gpio_count);
@@ -94,12 +153,12 @@ static int hsdk_creg_gpio_probe(struct udevice *dev)
}
static const struct udevice_id hsdk_creg_gpio_ids[] = {
- { .compatible = "snps,hsdk-creg-gpio" },
+ { .compatible = "snps,creg-gpio" },
{ }
};
U_BOOT_DRIVER(gpio_hsdk_creg) = {
- .name = "gpio_hsdk_creg",
+ .name = DRV_NAME,
.id = UCLASS_GPIO,
.ops = &hsdk_creg_gpio_ops,
.probe = hsdk_creg_gpio_probe,
diff --git a/drivers/gpio/xilinx_gpio.c b/drivers/gpio/xilinx_gpio.c
index 48b52c985a..2389abee37 100644
--- a/drivers/gpio/xilinx_gpio.c
+++ b/drivers/gpio/xilinx_gpio.c
@@ -10,13 +10,9 @@
#include <asm/io.h>
#include <asm/gpio.h>
#include <dm.h>
+#include <dt-bindings/gpio/gpio.h>
-static LIST_HEAD(gpio_list);
-
-enum gpio_direction {
- GPIO_DIRECTION_OUT = 0,
- GPIO_DIRECTION_IN = 1,
-};
+#define XILINX_GPIO_MAX_BANK 2
/* Gpio simple map */
struct gpio_regs {
@@ -24,340 +20,16 @@ struct gpio_regs {
u32 gpiodir;
};
-#if !defined(CONFIG_DM_GPIO)
-
-#define GPIO_NAME_SIZE 10
-
-struct gpio_names {
- char name[GPIO_NAME_SIZE];
-};
-
-/* Initialized, rxbd_current, rx_first_buf must be 0 after init */
-struct xilinx_gpio_priv {
- struct gpio_regs *regs;
- u32 gpio_min;
- u32 gpio_max;
- u32 gpiodata_store;
- char name[GPIO_NAME_SIZE];
- struct list_head list;
- struct gpio_names *gpio_name;
-};
-
-/* Store number of allocated gpio pins */
-static u32 xilinx_gpio_max;
-
-/* Get associated gpio controller */
-static struct xilinx_gpio_priv *gpio_get_controller(unsigned gpio)
-{
- struct list_head *entry;
- struct xilinx_gpio_priv *priv = NULL;
-
- list_for_each(entry, &gpio_list) {
- priv = list_entry(entry, struct xilinx_gpio_priv, list);
- if (gpio >= priv->gpio_min && gpio <= priv->gpio_max) {
- debug("%s: reg: %x, min-max: %d-%d\n", __func__,
- (u32)priv->regs, priv->gpio_min, priv->gpio_max);
- return priv;
- }
- }
- puts("!!!Can't get gpio controller!!!\n");
- return NULL;
-}
-
-/* Get gpio pin name if used/setup */
-static char *get_name(unsigned gpio)
-{
- u32 gpio_priv;
- struct xilinx_gpio_priv *priv;
-
- debug("%s\n", __func__);
-
- priv = gpio_get_controller(gpio);
- if (priv) {
- gpio_priv = gpio - priv->gpio_min;
-
- return *priv->gpio_name[gpio_priv].name ?
- priv->gpio_name[gpio_priv].name : "UNKNOWN";
- }
- return "UNKNOWN";
-}
-
-/* Get output value */
-static int gpio_get_output_value(unsigned gpio)
-{
- u32 val, gpio_priv;
- struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
-
- if (priv) {
- gpio_priv = gpio - priv->gpio_min;
- val = !!(priv->gpiodata_store & (1 << gpio_priv));
- debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
- (u32)priv->regs, gpio_priv, val);
-
- return val;
- }
- return -1;
-}
-
-/* Get input value */
-static int gpio_get_input_value(unsigned gpio)
-{
- u32 val, gpio_priv;
- struct gpio_regs *regs;
- struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
-
- if (priv) {
- regs = priv->regs;
- gpio_priv = gpio - priv->gpio_min;
- val = readl(&regs->gpiodata);
- val = !!(val & (1 << gpio_priv));
- debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
- (u32)priv->regs, gpio_priv, val);
-
- return val;
- }
- return -1;
-}
-
-/* Set gpio direction */
-static int gpio_set_direction(unsigned gpio, enum gpio_direction direction)
-{
- u32 val, gpio_priv;
- struct gpio_regs *regs;
- struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
-
- if (priv) {
- regs = priv->regs;
- val = readl(&regs->gpiodir);
-
- gpio_priv = gpio - priv->gpio_min;
- if (direction == GPIO_DIRECTION_OUT)
- val &= ~(1 << gpio_priv);
- else
- val |= 1 << gpio_priv;
-
- writel(val, &regs->gpiodir);
- debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
- (u32)priv->regs, gpio_priv, val);
-
- return 0;
- }
-
- return -1;
-}
-
-/* Get gpio direction */
-static int gpio_get_direction(unsigned gpio)
-{
- u32 val, gpio_priv;
- struct gpio_regs *regs;
- struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
-
- if (priv) {
- regs = priv->regs;
- gpio_priv = gpio - priv->gpio_min;
- val = readl(&regs->gpiodir);
- val = !!(val & (1 << gpio_priv));
- debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
- (u32)priv->regs, gpio_priv, val);
-
- return val;
- }
-
- return -1;
-}
-
-/*
- * Get input value
- * for example gpio setup to output only can't get input value
- * which is breaking gpio toggle command
- */
-int gpio_get_value(unsigned gpio)
-{
- u32 val;
-
- if (gpio_get_direction(gpio) == GPIO_DIRECTION_OUT)
- val = gpio_get_output_value(gpio);
- else
- val = gpio_get_input_value(gpio);
-
- return val;
-}
-
-/* Set output value */
-static int gpio_set_output_value(unsigned gpio, int value)
-{
- u32 val, gpio_priv;
- struct gpio_regs *regs;
- struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
-
- if (priv) {
- regs = priv->regs;
- gpio_priv = gpio - priv->gpio_min;
- val = priv->gpiodata_store;
- if (value)
- val |= 1 << gpio_priv;
- else
- val &= ~(1 << gpio_priv);
-
- writel(val, &regs->gpiodata);
- debug("%s: reg: %x, gpio_no: %d, output_val: %d\n", __func__,
- (u32)priv->regs, gpio_priv, val);
- priv->gpiodata_store = val;
-
- return 0;
- }
-
- return -1;
-}
-
-int gpio_set_value(unsigned gpio, int value)
-{
- if (gpio_get_direction(gpio) == GPIO_DIRECTION_OUT)
- return gpio_set_output_value(gpio, value);
-
- return -1;
-}
-
-/* Set GPIO as input */
-int gpio_direction_input(unsigned gpio)
-{
- debug("%s\n", __func__);
- return gpio_set_direction(gpio, GPIO_DIRECTION_IN);
-}
-
-/* Setup GPIO as output and set output value */
-int gpio_direction_output(unsigned gpio, int value)
-{
- int ret = gpio_set_direction(gpio, GPIO_DIRECTION_OUT);
-
- debug("%s\n", __func__);
-
- if (ret < 0)
- return ret;
-
- return gpio_set_output_value(gpio, value);
-}
-
-/* Show gpio status */
-void gpio_info(void)
-{
- unsigned gpio;
-
- struct list_head *entry;
- struct xilinx_gpio_priv *priv = NULL;
-
- list_for_each(entry, &gpio_list) {
- priv = list_entry(entry, struct xilinx_gpio_priv, list);
- printf("\n%s: %s/%x (%d-%d)\n", __func__, priv->name,
- (u32)priv->regs, priv->gpio_min, priv->gpio_max);
-
- for (gpio = priv->gpio_min; gpio <= priv->gpio_max; gpio++) {
- printf("GPIO_%d:\t%s is an ", gpio, get_name(gpio));
- if (gpio_get_direction(gpio) == GPIO_DIRECTION_OUT)
- printf("OUTPUT value = %d\n",
- gpio_get_output_value(gpio));
- else
- printf("INPUT value = %d\n",
- gpio_get_input_value(gpio));
- }
- }
-}
-
-int gpio_request(unsigned gpio, const char *label)
-{
- u32 gpio_priv;
- struct xilinx_gpio_priv *priv;
-
- if (gpio >= xilinx_gpio_max)
- return -EINVAL;
-
- priv = gpio_get_controller(gpio);
- if (priv) {
- gpio_priv = gpio - priv->gpio_min;
-
- if (label != NULL) {
- strncpy(priv->gpio_name[gpio_priv].name, label,
- GPIO_NAME_SIZE);
- priv->gpio_name[gpio_priv].name[GPIO_NAME_SIZE - 1] =
- '\0';
- }
- return 0;
- }
-
- return -1;
-}
-
-int gpio_free(unsigned gpio)
-{
- u32 gpio_priv;
- struct xilinx_gpio_priv *priv;
-
- if (gpio >= xilinx_gpio_max)
- return -EINVAL;
-
- priv = gpio_get_controller(gpio);
- if (priv) {
- gpio_priv = gpio - priv->gpio_min;
- priv->gpio_name[gpio_priv].name[0] = '\0';
-
- /* Do nothing here */
- return 0;
- }
-
- return -1;
-}
-
-int gpio_alloc(u32 baseaddr, const char *name, u32 gpio_no)
-{
- struct xilinx_gpio_priv *priv;
-
- priv = calloc(1, sizeof(struct xilinx_gpio_priv));
-
- /* Setup gpio name */
- if (name != NULL) {
- strncpy(priv->name, name, GPIO_NAME_SIZE);
- priv->name[GPIO_NAME_SIZE - 1] = '\0';
- }
- priv->regs = (struct gpio_regs *)baseaddr;
-
- priv->gpio_min = xilinx_gpio_max;
- xilinx_gpio_max = priv->gpio_min + gpio_no;
- priv->gpio_max = xilinx_gpio_max - 1;
-
- priv->gpio_name = calloc(gpio_no, sizeof(struct gpio_names));
-
- INIT_LIST_HEAD(&priv->list);
- list_add_tail(&priv->list, &gpio_list);
-
- printf("%s: Add %s (%d-%d)\n", __func__, name,
- priv->gpio_min, priv->gpio_max);
-
- /* Return the first gpio allocated for this device */
- return priv->gpio_min;
-}
-
-/* Dual channel gpio is one IP with two independent channels */
-int gpio_alloc_dual(u32 baseaddr, const char *name, u32 gpio_no0, u32 gpio_no1)
-{
- int ret;
-
- ret = gpio_alloc(baseaddr, name, gpio_no0);
- gpio_alloc(baseaddr + 8, strcat((char *)name, "_1"), gpio_no1);
-
- /* Return the first gpio allocated for this device */
- return ret;
-}
-#else
-#include <dt-bindings/gpio/gpio.h>
-
-#define XILINX_GPIO_MAX_BANK 2
-
struct xilinx_gpio_platdata {
struct gpio_regs *regs;
int bank_max[XILINX_GPIO_MAX_BANK];
int bank_input[XILINX_GPIO_MAX_BANK];
int bank_output[XILINX_GPIO_MAX_BANK];
+ u32 dout_default[XILINX_GPIO_MAX_BANK];
+};
+
+struct xilinx_gpio_privdata {
+ u32 output_val[XILINX_GPIO_MAX_BANK];
};
static int xilinx_gpio_get_bank_pin(unsigned offset, u32 *bank_num,
@@ -387,6 +59,7 @@ static int xilinx_gpio_set_value(struct udevice *dev, unsigned offset,
int value)
{
struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev);
+ struct xilinx_gpio_privdata *priv = dev_get_priv(dev);
int val, ret;
u32 bank, pin;
@@ -394,25 +67,27 @@ static int xilinx_gpio_set_value(struct udevice *dev, unsigned offset,
if (ret)
return ret;
- debug("%s: regs: %lx, value: %x, gpio: %x, bank %x, pin %x\n",
- __func__, (ulong)platdata->regs, value, offset, bank, pin);
+ val = priv->output_val[bank];
- if (value) {
- val = readl(&platdata->regs->gpiodata + bank * 2);
+ debug("%s: regs: %lx, value: %x, gpio: %x, bank %x, pin %x, out %x\n",
+ __func__, (ulong)platdata->regs, value, offset, bank, pin, val);
+
+ if (value)
val = val | (1 << pin);
- writel(val, &platdata->regs->gpiodata + bank * 2);
- } else {
- val = readl(&platdata->regs->gpiodata + bank * 2);
+ else
val = val & ~(1 << pin);
- writel(val, &platdata->regs->gpiodata + bank * 2);
- }
- return val;
+ writel(val, &platdata->regs->gpiodata + bank * 2);
+
+ priv->output_val[bank] = val;
+
+ return 0;
};
static int xilinx_gpio_get_value(struct udevice *dev, unsigned offset)
{
struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev);
+ struct xilinx_gpio_privdata *priv = dev_get_priv(dev);
int val, ret;
u32 bank, pin;
@@ -423,7 +98,14 @@ static int xilinx_gpio_get_value(struct udevice *dev, unsigned offset)
debug("%s: regs: %lx, gpio: %x, bank %x, pin %x\n", __func__,
(ulong)platdata->regs, offset, bank, pin);
- val = readl(&platdata->regs->gpiodata + bank * 2);
+ if (platdata->bank_output[bank]) {
+ debug("%s: Read saved output value\n", __func__);
+ val = priv->output_val[bank];
+ } else {
+ debug("%s: Read input value from reg\n", __func__);
+ val = readl(&platdata->regs->gpiodata + bank * 2);
+ }
+
val = !!(val & (1 << pin));
return val;
@@ -435,6 +117,10 @@ static int xilinx_gpio_get_function(struct udevice *dev, unsigned offset)
int val, ret;
u32 bank, pin;
+ ret = xilinx_gpio_get_bank_pin(offset, &bank, &pin, dev);
+ if (ret)
+ return ret;
+
/* Check if all pins are inputs */
if (platdata->bank_input[bank])
return GPIOF_INPUT;
@@ -443,10 +129,6 @@ static int xilinx_gpio_get_function(struct udevice *dev, unsigned offset)
if (platdata->bank_output[bank])
return GPIOF_OUTPUT;
- ret = xilinx_gpio_get_bank_pin(offset, &bank, &pin, dev);
- if (ret)
- return ret;
-
/* FIXME test on dual */
val = readl(&platdata->regs->gpiodir + bank * 2);
val = !(val & (1 << pin));
@@ -472,14 +154,14 @@ static int xilinx_gpio_direction_output(struct udevice *dev, unsigned offset,
if (platdata->bank_input[bank])
return -EINVAL;
+ xilinx_gpio_set_value(dev, offset, value);
+
if (!platdata->bank_output[bank]) {
val = readl(&platdata->regs->gpiodir + bank * 2);
val = val & ~(1 << pin);
writel(val, &platdata->regs->gpiodir + bank * 2);
}
- xilinx_gpio_set_value(dev, offset, value);
-
return 0;
}
@@ -557,12 +239,26 @@ static const struct dm_gpio_ops xilinx_gpio_ops = {
static int xilinx_gpio_probe(struct udevice *dev)
{
struct xilinx_gpio_platdata *platdata = dev_get_platdata(dev);
+ struct xilinx_gpio_privdata *priv = dev_get_priv(dev);
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ const void *label_ptr;
- uc_priv->bank_name = dev->name;
+ label_ptr = dev_read_prop(dev, "label", NULL);
+ if (label_ptr) {
+ uc_priv->bank_name = strdup(label_ptr);
+ if (!uc_priv->bank_name)
+ return -ENOMEM;
+ } else {
+ uc_priv->bank_name = dev->name;
+ }
uc_priv->gpio_count = platdata->bank_max[0] + platdata->bank_max[1];
+ priv->output_val[0] = platdata->dout_default[0];
+
+ if (platdata->bank_max[1])
+ priv->output_val[1] = platdata->dout_default[1];
+
return 0;
}
@@ -579,6 +275,9 @@ static int xilinx_gpio_ofdata_to_platdata(struct udevice *dev)
"xlnx,all-inputs", 0);
platdata->bank_output[0] = dev_read_u32_default(dev,
"xlnx,all-outputs", 0);
+ platdata->dout_default[0] = dev_read_u32_default(dev,
+ "xlnx,dout-default",
+ 0);
is_dual = dev_read_u32_default(dev, "xlnx,is-dual", 0);
if (is_dual) {
@@ -588,6 +287,8 @@ static int xilinx_gpio_ofdata_to_platdata(struct udevice *dev)
"xlnx,all-inputs-2", 0);
platdata->bank_output[1] = dev_read_u32_default(dev,
"xlnx,all-outputs-2", 0);
+ platdata->dout_default[1] = dev_read_u32_default(dev,
+ "xlnx,dout-default-2", 0);
}
return 0;
@@ -606,5 +307,5 @@ U_BOOT_DRIVER(xilinx_gpio) = {
.ofdata_to_platdata = xilinx_gpio_ofdata_to_platdata,
.probe = xilinx_gpio_probe,
.platdata_auto_alloc_size = sizeof(struct xilinx_gpio_platdata),
+ .priv_auto_alloc_size = sizeof(struct xilinx_gpio_privdata),
};
-#endif
diff --git a/drivers/gpio/zynq_gpio.c b/drivers/gpio/zynq_gpio.c
index f793ee5754..55a5cba068 100644
--- a/drivers/gpio/zynq_gpio.c
+++ b/drivers/gpio/zynq_gpio.c
@@ -93,7 +93,7 @@
/* GPIO upper 16 bit mask */
#define ZYNQ_GPIO_UPPER_MASK 0xFFFF0000
-struct zynq_gpio_privdata {
+struct zynq_gpio_platdata {
phys_addr_t base;
const struct zynq_platform_data *p_data;
};
@@ -162,20 +162,20 @@ static inline void zynq_gpio_get_bank_pin(unsigned int pin_num,
unsigned int *bank_pin_num,
struct udevice *dev)
{
- struct zynq_gpio_privdata *priv = dev_get_priv(dev);
+ struct zynq_gpio_platdata *platdata = dev_get_platdata(dev);
u32 bank;
- for (bank = 0; bank < priv->p_data->max_bank; bank++) {
- if ((pin_num >= priv->p_data->bank_min[bank]) &&
- (pin_num <= priv->p_data->bank_max[bank])) {
- *bank_num = bank;
- *bank_pin_num = pin_num -
- priv->p_data->bank_min[bank];
- return;
+ for (bank = 0; bank < platdata->p_data->max_bank; bank++) {
+ if (pin_num >= platdata->p_data->bank_min[bank] &&
+ pin_num <= platdata->p_data->bank_max[bank]) {
+ *bank_num = bank;
+ *bank_pin_num = pin_num -
+ platdata->p_data->bank_min[bank];
+ return;
}
}
- if (bank >= priv->p_data->max_bank) {
+ if (bank >= platdata->p_data->max_bank) {
printf("Invalid bank and pin num\n");
*bank_num = 0;
*bank_pin_num = 0;
@@ -184,9 +184,9 @@ static inline void zynq_gpio_get_bank_pin(unsigned int pin_num,
static int gpio_is_valid(unsigned gpio, struct udevice *dev)
{
- struct zynq_gpio_privdata *priv = dev_get_priv(dev);
+ struct zynq_gpio_platdata *platdata = dev_get_platdata(dev);
- return gpio < priv->p_data->ngpio;
+ return gpio < platdata->p_data->ngpio;
}
static int check_gpio(unsigned gpio, struct udevice *dev)
@@ -202,14 +202,14 @@ static int zynq_gpio_get_value(struct udevice *dev, unsigned gpio)
{
u32 data;
unsigned int bank_num, bank_pin_num;
- struct zynq_gpio_privdata *priv = dev_get_priv(dev);
+ struct zynq_gpio_platdata *platdata = dev_get_platdata(dev);
if (check_gpio(gpio, dev) < 0)
return -1;
zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num, dev);
- data = readl(priv->base +
+ data = readl(platdata->base +
ZYNQ_GPIO_DATA_RO_OFFSET(bank_num));
return (data >> bank_pin_num) & 1;
@@ -218,7 +218,7 @@ static int zynq_gpio_get_value(struct udevice *dev, unsigned gpio)
static int zynq_gpio_set_value(struct udevice *dev, unsigned gpio, int value)
{
unsigned int reg_offset, bank_num, bank_pin_num;
- struct zynq_gpio_privdata *priv = dev_get_priv(dev);
+ struct zynq_gpio_platdata *platdata = dev_get_platdata(dev);
if (check_gpio(gpio, dev) < 0)
return -1;
@@ -241,7 +241,7 @@ static int zynq_gpio_set_value(struct udevice *dev, unsigned gpio, int value)
value = ~(1 << (bank_pin_num + ZYNQ_GPIO_MID_PIN_NUM)) &
((value << bank_pin_num) | ZYNQ_GPIO_UPPER_MASK);
- writel(value, priv->base + reg_offset);
+ writel(value, platdata->base + reg_offset);
return 0;
}
@@ -250,7 +250,7 @@ static int zynq_gpio_direction_input(struct udevice *dev, unsigned gpio)
{
u32 reg;
unsigned int bank_num, bank_pin_num;
- struct zynq_gpio_privdata *priv = dev_get_priv(dev);
+ struct zynq_gpio_platdata *platdata = dev_get_platdata(dev);
if (check_gpio(gpio, dev) < 0)
return -1;
@@ -262,9 +262,9 @@ static int zynq_gpio_direction_input(struct udevice *dev, unsigned gpio)
return -1;
/* clear the bit in direction mode reg to set the pin as input */
- reg = readl(priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+ reg = readl(platdata->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
reg &= ~BIT(bank_pin_num);
- writel(reg, priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+ writel(reg, platdata->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
return 0;
}
@@ -274,7 +274,7 @@ static int zynq_gpio_direction_output(struct udevice *dev, unsigned gpio,
{
u32 reg;
unsigned int bank_num, bank_pin_num;
- struct zynq_gpio_privdata *priv = dev_get_priv(dev);
+ struct zynq_gpio_platdata *platdata = dev_get_platdata(dev);
if (check_gpio(gpio, dev) < 0)
return -1;
@@ -282,14 +282,14 @@ static int zynq_gpio_direction_output(struct udevice *dev, unsigned gpio,
zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num, dev);
/* set the GPIO pin as output */
- reg = readl(priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+ reg = readl(platdata->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
reg |= BIT(bank_pin_num);
- writel(reg, priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+ writel(reg, platdata->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
/* configure the output enable reg for the pin */
- reg = readl(priv->base + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
+ reg = readl(platdata->base + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
reg |= BIT(bank_pin_num);
- writel(reg, priv->base + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
+ writel(reg, platdata->base + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
/* set the state of the pin */
gpio_set_value(gpio, value);
@@ -300,7 +300,7 @@ static int zynq_gpio_get_function(struct udevice *dev, unsigned offset)
{
u32 reg;
unsigned int bank_num, bank_pin_num;
- struct zynq_gpio_privdata *priv = dev_get_priv(dev);
+ struct zynq_gpio_platdata *platdata = dev_get_platdata(dev);
if (check_gpio(offset, dev) < 0)
return -1;
@@ -308,7 +308,7 @@ static int zynq_gpio_get_function(struct udevice *dev, unsigned offset)
zynq_gpio_get_bank_pin(offset, &bank_num, &bank_pin_num, dev);
/* set the GPIO pin as output */
- reg = readl(priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+ reg = readl(platdata->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
reg &= BIT(bank_pin_num);
if (reg)
return GPIOF_OUTPUT;
@@ -334,24 +334,33 @@ static const struct udevice_id zynq_gpio_ids[] = {
static int zynq_gpio_probe(struct udevice *dev)
{
- struct zynq_gpio_privdata *priv = dev_get_priv(dev);
+ struct zynq_gpio_platdata *platdata = dev_get_platdata(dev);
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ const void *label_ptr;
- uc_priv->bank_name = dev->name;
+ label_ptr = dev_read_prop(dev, "label", NULL);
+ if (label_ptr) {
+ uc_priv->bank_name = strdup(label_ptr);
+ if (!uc_priv->bank_name)
+ return -ENOMEM;
+ } else {
+ uc_priv->bank_name = dev->name;
+ }
- if (priv->p_data)
- uc_priv->gpio_count = priv->p_data->ngpio;
+ if (platdata->p_data)
+ uc_priv->gpio_count = platdata->p_data->ngpio;
return 0;
}
static int zynq_gpio_ofdata_to_platdata(struct udevice *dev)
{
- struct zynq_gpio_privdata *priv = dev_get_priv(dev);
+ struct zynq_gpio_platdata *platdata = dev_get_platdata(dev);
- priv->base = (phys_addr_t)dev_read_addr(dev);
+ platdata->base = (phys_addr_t)dev_read_addr(dev);
- priv->p_data = (struct zynq_platform_data *)dev_get_driver_data(dev);
+ platdata->p_data =
+ (struct zynq_platform_data *)dev_get_driver_data(dev);
return 0;
}
@@ -363,5 +372,5 @@ U_BOOT_DRIVER(gpio_zynq) = {
.of_match = zynq_gpio_ids,
.ofdata_to_platdata = zynq_gpio_ofdata_to_platdata,
.probe = zynq_gpio_probe,
- .priv_auto_alloc_size = sizeof(struct zynq_gpio_privdata),
+ .platdata_auto_alloc_size = sizeof(struct zynq_gpio_platdata),
};
diff --git a/drivers/i2c/imx_lpi2c.c b/drivers/i2c/imx_lpi2c.c
index ff07ca34aa..6c343072fb 100644
--- a/drivers/i2c/imx_lpi2c.c
+++ b/drivers/i2c/imx_lpi2c.c
@@ -261,8 +261,14 @@ static int bus_i2c_write(struct udevice *bus, u32 chip, u8 *buf, int len)
}
+u32 __weak imx_get_i2cclk(u32 i2c_num)
+{
+ return 0;
+}
+
static int bus_i2c_set_bus_speed(struct udevice *bus, int speed)
{
+ struct imx_lpi2c_bus *i2c_bus = dev_get_priv(bus);
struct imx_lpi2c_reg *regs;
u32 val;
u32 preescale = 0, best_pre = 0, clkhi = 0;
@@ -273,9 +279,18 @@ static int bus_i2c_set_bus_speed(struct udevice *bus, int speed)
int i;
regs = (struct imx_lpi2c_reg *)devfdt_get_addr(bus);
- clock_rate = imx_get_i2cclk(bus->seq);
- if (!clock_rate)
- return -EPERM;
+
+ if (IS_ENABLED(CONFIG_CLK)) {
+ clock_rate = clk_get_rate(&i2c_bus->per_clk);
+ if (clock_rate <= 0) {
+ dev_err(bus, "Failed to get i2c clk: %d\n", clock_rate);
+ return clock_rate;
+ }
+ } else {
+ clock_rate = imx_get_i2cclk(bus->seq);
+ if (!clock_rate)
+ return -EPERM;
+ }
mode = (readl(&regs->mcr) & LPI2C_MCR_MEN_MASK) >> LPI2C_MCR_MEN_SHIFT;
/* disable master mode */
@@ -417,6 +432,11 @@ static int imx_lpi2c_set_bus_speed(struct udevice *bus, unsigned int speed)
return bus_i2c_set_bus_speed(bus, speed);
}
+__weak int enable_i2c_clk(unsigned char enable, unsigned int i2c_num)
+{
+ return 0;
+}
+
static int imx_lpi2c_probe(struct udevice *bus)
{
struct imx_lpi2c_bus *i2c_bus = dev_get_priv(bus);
@@ -440,10 +460,23 @@ static int imx_lpi2c_probe(struct udevice *bus)
return ret;
}
- /* To i.MX7ULP, only i2c4-7 can be handled by A7 core */
- ret = enable_i2c_clk(1, bus->seq);
- if (ret < 0)
- return ret;
+ if (IS_ENABLED(CONFIG_CLK)) {
+ ret = clk_get_by_name(bus, "per", &i2c_bus->per_clk);
+ if (ret) {
+ dev_err(bus, "Failed to get per clk\n");
+ return ret;
+ }
+ ret = clk_enable(&i2c_bus->per_clk);
+ if (ret) {
+ dev_err(bus, "Failed to enable per clk\n");
+ return ret;
+ }
+ } else {
+ /* To i.MX7ULP, only i2c4-7 can be handled by A7 core */
+ ret = enable_i2c_clk(1, bus->seq);
+ if (ret < 0)
+ return ret;
+ }
ret = bus_i2c_init(bus, 100000);
if (ret < 0)
diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c
index 4debc03957..ab8b4000af 100644
--- a/drivers/i2c/muxes/pca954x.c
+++ b/drivers/i2c/muxes/pca954x.c
@@ -17,7 +17,8 @@ DECLARE_GLOBAL_DATA_PTR;
enum pca_type {
PCA9544,
PCA9547,
- PCA9548
+ PCA9548,
+ PCA9646
};
struct chip_desc {
@@ -51,6 +52,11 @@ static const struct chip_desc chips[] = {
.muxtype = pca954x_isswi,
.width = 8,
},
+ [PCA9646] = {
+ .enable = 0x0,
+ .muxtype = pca954x_isswi,
+ .width = 4,
+ },
};
static int pca954x_deselect(struct udevice *mux, struct udevice *bus,
@@ -86,6 +92,7 @@ static const struct udevice_id pca954x_ids[] = {
{ .compatible = "nxp,pca9544", .data = PCA9544 },
{ .compatible = "nxp,pca9547", .data = PCA9547 },
{ .compatible = "nxp,pca9548", .data = PCA9548 },
+ { .compatible = "nxp,pca9646", .data = PCA9646 },
{ }
};
diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c
index e267cd782e..f71d79ecd6 100644
--- a/drivers/mmc/arm_pl180_mmci.c
+++ b/drivers/mmc/arm_pl180_mmci.c
@@ -357,13 +357,13 @@ static const struct mmc_ops arm_pl180_mmci_ops = {
.set_ios = host_set_ios,
.init = mmc_host_reset,
};
-#endif
/*
* mmc_host_init - initialize the mmc controller.
* Set initial clock and power for mmc slot.
* Initialize mmc struct and register with mmc framework.
*/
+
int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc)
{
u32 sdi_u32;
@@ -377,9 +377,8 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc)
writel(sdi_u32, &host->base->mask0);
host->cfg.name = host->name;
-#ifndef CONFIG_DM_MMC
host->cfg.ops = &arm_pl180_mmci_ops;
-#endif
+
/* TODO remove the duplicates */
host->cfg.host_caps = host->caps;
host->cfg.voltages = host->voltages;
@@ -393,20 +392,34 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc)
*mmc = mmc_create(&host->cfg, host);
if (!*mmc)
return -1;
-
debug("registered mmc interface number is:%d\n",
(*mmc)->block_dev.devnum);
return 0;
}
+#endif
#ifdef CONFIG_DM_MMC
+static void arm_pl180_mmc_init(struct pl180_mmc_host *host)
+{
+ u32 sdi_u32;
+
+ writel(host->pwr_init, &host->base->power);
+ writel(host->clkdiv_init, &host->base->clock);
+ udelay(CLK_CHANGE_DELAY);
+
+ /* Disable mmc interrupts */
+ sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK;
+ writel(sdi_u32, &host->base->mask0);
+}
+
static int arm_pl180_mmc_probe(struct udevice *dev)
{
struct arm_pl180_mmc_plat *pdata = dev_get_platdata(dev);
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct mmc *mmc = &pdata->mmc;
- struct pl180_mmc_host *host = mmc->priv;
+ struct pl180_mmc_host *host = dev->priv;
+ struct mmc_config *cfg = &pdata->cfg;
struct clk clk;
u32 bus_width;
int ret;
@@ -417,31 +430,33 @@ static int arm_pl180_mmc_probe(struct udevice *dev)
ret = clk_enable(&clk);
if (ret) {
+ clk_free(&clk);
dev_err(dev, "failed to enable clock\n");
return ret;
}
- strcpy(host->name, "MMC");
host->pwr_init = INIT_PWR;
host->clkdiv_init = SDI_CLKCR_CLKDIV_INIT_V1 | SDI_CLKCR_CLKEN |
SDI_CLKCR_HWFC_EN;
- host->voltages = VOLTAGE_WINDOW_SD;
- host->caps = 0;
host->clock_in = clk_get_rate(&clk);
- host->clock_min = host->clock_in / (2 * (SDI_CLKCR_CLKDIV_INIT_V1 + 1));
- host->clock_max = dev_read_u32_default(dev, "max-frequency",
- MMC_CLOCK_MAX);
host->version2 = dev_get_driver_data(dev);
+ cfg->name = dev->name;
+ cfg->voltages = VOLTAGE_WINDOW_SD;
+ cfg->host_caps = 0;
+ cfg->f_min = host->clock_in / (2 * (SDI_CLKCR_CLKDIV_INIT_V1 + 1));
+ cfg->f_max = dev_read_u32_default(dev, "max-frequency", MMC_CLOCK_MAX);
+ cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
gpio_request_by_name(dev, "cd-gpios", 0, &host->cd_gpio, GPIOD_IS_IN);
bus_width = dev_read_u32_default(dev, "bus-width", 1);
switch (bus_width) {
case 8:
- host->caps |= MMC_MODE_8BIT;
+ cfg->host_caps |= MMC_MODE_8BIT;
/* Hosts capable of 8-bit transfers can also do 4 bits */
case 4:
- host->caps |= MMC_MODE_4BIT;
+ cfg->host_caps |= MMC_MODE_4BIT;
break;
case 1:
break;
@@ -449,19 +464,21 @@ static int arm_pl180_mmc_probe(struct udevice *dev)
dev_err(dev, "Invalid bus-width value %u\n", bus_width);
}
- ret = arm_pl180_mmci_init(host, &mmc);
- if (ret) {
- dev_err(dev, "arm_pl180_mmci init failed\n");
- return ret;
- }
-
+ arm_pl180_mmc_init(host);
+ mmc->priv = host;
mmc->dev = dev;
- dev->priv = host;
upriv->mmc = mmc;
return 0;
}
+int arm_pl180_mmc_bind(struct udevice *dev)
+{
+ struct arm_pl180_mmc_plat *plat = dev_get_platdata(dev);
+
+ return mmc_bind(dev, &plat->mmc, &plat->cfg);
+}
+
static int dm_host_request(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data)
{
@@ -479,16 +496,11 @@ static int dm_host_set_ios(struct udevice *dev)
static int dm_mmc_getcd(struct udevice *dev)
{
- struct arm_pl180_mmc_plat *pdata = dev_get_platdata(dev);
- struct mmc *mmc = &pdata->mmc;
- struct pl180_mmc_host *host = mmc->priv;
+ struct pl180_mmc_host *host = dev->priv;
int value = 1;
- if (dm_gpio_is_valid(&host->cd_gpio)) {
+ if (dm_gpio_is_valid(&host->cd_gpio))
value = dm_gpio_get_value(&host->cd_gpio);
- if (host->cd_inverted)
- return !value;
- }
return value;
}
@@ -501,12 +513,10 @@ static const struct dm_mmc_ops arm_pl180_dm_mmc_ops = {
static int arm_pl180_mmc_ofdata_to_platdata(struct udevice *dev)
{
- struct arm_pl180_mmc_plat *pdata = dev_get_platdata(dev);
- struct mmc *mmc = &pdata->mmc;
- struct pl180_mmc_host *host = mmc->priv;
+ struct pl180_mmc_host *host = dev->priv;
fdt_addr_t addr;
- addr = devfdt_get_addr(dev);
+ addr = dev_read_addr(dev);
if (addr == FDT_ADDR_T_NONE)
return -EINVAL;
@@ -527,6 +537,7 @@ U_BOOT_DRIVER(arm_pl180_mmc) = {
.ops = &arm_pl180_dm_mmc_ops,
.probe = arm_pl180_mmc_probe,
.ofdata_to_platdata = arm_pl180_mmc_ofdata_to_platdata,
+ .bind = arm_pl180_mmc_bind,
.priv_auto_alloc_size = sizeof(struct pl180_mmc_host),
.platdata_auto_alloc_size = sizeof(struct arm_pl180_mmc_plat),
};
diff --git a/drivers/mmc/arm_pl180_mmci.h b/drivers/mmc/arm_pl180_mmci.h
index 6b98db6cd9..36487be288 100644
--- a/drivers/mmc/arm_pl180_mmci.h
+++ b/drivers/mmc/arm_pl180_mmci.h
@@ -192,7 +192,6 @@ struct pl180_mmc_host {
struct mmc_config cfg;
#ifdef CONFIG_DM_MMC
struct gpio_desc cd_gpio;
- bool cd_inverted;
#endif
};
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 7fa1ae8b16..39f15eb423 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -70,10 +70,12 @@ static int mmc_resource_init(int sdc_no)
priv->reg = (struct sunxi_mmc *)SUNXI_MMC2_BASE;
priv->mclkreg = &ccm->sd2_clk_cfg;
break;
+#ifdef SUNXI_MMC3_BASE
case 3:
priv->reg = (struct sunxi_mmc *)SUNXI_MMC3_BASE;
priv->mclkreg = &ccm->sd3_clk_cfg;
break;
+#endif
default:
printf("Wrong mmc number %d\n", sdc_no);
return -1;
@@ -116,6 +118,9 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz)
#ifdef CONFIG_MACH_SUN9I
pll = CCM_MMC_CTRL_PLL_PERIPH0;
pll_hz = clock_get_pll4_periph0();
+#elif defined(CONFIG_MACH_SUN50I_H6)
+ pll = CCM_MMC_CTRL_PLL6X2;
+ pll_hz = clock_get_pll6() * 2;
#else
pll = CCM_MMC_CTRL_PLL6;
pll_hz = clock_get_pll6();
@@ -494,7 +499,7 @@ struct mmc *sunxi_mmc_init(int sdc_no)
cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
cfg->host_caps = MMC_MODE_4BIT;
-#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN8I)
+#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN8I) || defined(CONFIG_MACH_SUN50I_H6)
if (sdc_no == 2)
cfg->host_caps = MMC_MODE_8BIT;
#endif
@@ -509,6 +514,7 @@ struct mmc *sunxi_mmc_init(int sdc_no)
/* config ahb clock */
debug("init mmc %d clock and io\n", sdc_no);
+#if !defined(CONFIG_MACH_SUN50I_H6)
setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no));
#ifdef CONFIG_SUNXI_GEN_SUN6I
@@ -520,6 +526,11 @@ struct mmc *sunxi_mmc_init(int sdc_no)
writel(SUNXI_MMC_COMMON_CLK_GATE | SUNXI_MMC_COMMON_RESET,
SUNXI_MMC_COMMON_BASE + 4 * sdc_no);
#endif
+#else /* CONFIG_MACH_SUN50I_H6 */
+ setbits_le32(&ccm->sd_gate_reset, 1 << sdc_no);
+ /* unassert reset */
+ setbits_le32(&ccm->sd_gate_reset, 1 << (RESET_SHIFT + sdc_no));
+#endif
ret = mmc_set_mod_clk(priv, 24000000);
if (ret)
return NULL;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 64e4621aaa..9094f857c1 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -3041,7 +3041,7 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
if (!chip->onfi_version ||
!(le16_to_cpu(chip->onfi_params.opt_cmd)
& ONFI_OPT_CMD_SET_GET_FEATURES))
- return -EINVAL;
+ return -ENOTSUPP;
#endif
chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1);
@@ -3070,7 +3070,7 @@ static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
if (!chip->onfi_version ||
!(le16_to_cpu(chip->onfi_params.opt_cmd)
& ONFI_OPT_CMD_SET_GET_FEATURES))
- return -EINVAL;
+ return -ENOTSUPP;
#endif
chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1);
diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c
index bb87aca698..3ccb168d13 100644
--- a/drivers/mtd/nand/sunxi_nand.c
+++ b/drivers/mtd/nand/sunxi_nand.c
@@ -1369,7 +1369,7 @@ static int sunxi_nand_chip_init_timings(struct sunxi_nand_chip *chip)
ONFI_FEATURE_ADDR_TIMING_MODE,
feature);
chip->nand.select_chip(mtd, -1);
- if (ret)
+ if (ret && ret != -ENOTSUPP)
return ret;
}
}
diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig
index 4484cf8195..98485b1236 100644
--- a/drivers/mtd/spi/Kconfig
+++ b/drivers/mtd/spi/Kconfig
@@ -66,6 +66,11 @@ config SPI_FLASH_GIGADEVICE
help
Add support for various GigaDevice SPI flash chips (GD25xxx)
+config SPI_FLASH_ISSI
+ bool "ISSI SPI flash support"
+ help
+ Add support for various ISSI SPI flash chips (ISxxx)
+
config SPI_FLASH_MACRONIX
bool "Macronix SPI flash support"
help
diff --git a/drivers/mtd/spi/spi_flash_ids.c b/drivers/mtd/spi/spi_flash_ids.c
index 3cdee508c8..e662e4b42e 100644
--- a/drivers/mtd/spi/spi_flash_ids.c
+++ b/drivers/mtd/spi/spi_flash_ids.c
@@ -109,6 +109,7 @@ const struct spi_flash_info spi_flash_ids[] = {
{"s25fl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, RD_FULL | WR_QPP) },
{"s25fl128s_256k", INFO(0x012018, 0x4d00, 256 * 1024, 64, RD_FULL | WR_QPP) },
{"s25fl128s_64k", INFO(0x012018, 0x4d01, 64 * 1024, 256, RD_FULL | WR_QPP) },
+ {"s25fl128l", INFO(0x016018, 0, 64 * 1024, 256, RD_FULL | WR_QPP) },
{"s25fl256s_256k", INFO(0x010219, 0x4d00, 256 * 1024, 128, RD_FULL | WR_QPP) },
{"s25fs256s_64k", INFO6(0x010219, 0x4d0181, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) },
{"s25fl256s_64k", INFO(0x010219, 0x4d01, 64 * 1024, 512, RD_FULL | WR_QPP) },
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index e88f056d84..f762b0898d 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -7,8 +7,8 @@ config DM_ETH
help
Enable driver model for Ethernet.
- The eth_*() interface will be implemented by the UC_ETH class
- This is currently implemented in net/eth.c
+ The eth_*() interface will be implemented by the UCLASS_ETH class
+ This is currently implemented in net/eth-uclass.c
Look in include/net.h for details.
config DRIVER_TI_CPSW
@@ -181,6 +181,7 @@ config FTMAC100
config MVGBE
bool "Marvell Orion5x/Kirkwood network interface support"
depends on KIRKWOOD || ORION5X
+ select PHYLIB if DM_ETH
help
This driver supports the network interface units in the
Marvell Orion5x and Kirkwood SoCs
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 058dd00768..c1ed44e21f 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_RTL8139) += rtl8139.o
obj-$(CONFIG_RTL8169) += rtl8169.o
obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw.o
+obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw-bus.o
obj-$(CONFIG_SH_ETHER) += sh_eth.o
obj-$(CONFIG_RENESAS_RAVB) += ravb.o
obj-$(CONFIG_SMC91111) += smc91111.o
diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c
index 9919d3919f..c31695eba9 100644
--- a/drivers/net/cpsw.c
+++ b/drivers/net/cpsw.c
@@ -999,7 +999,7 @@ static int cpsw_phy_init(struct cpsw_priv *priv, struct cpsw_slave *slave)
#ifdef CONFIG_DM_ETH
if (slave->data->phy_of_handle)
- dev_set_of_offset(phydev->dev, slave->data->phy_of_handle);
+ phydev->node = offset_to_ofnode(slave->data->phy_of_handle);
#endif
priv->phydev = phydev;
diff --git a/drivers/net/mvgbe.c b/drivers/net/mvgbe.c
index e6585ef8b3..74fed7abd8 100644
--- a/drivers/net/mvgbe.c
+++ b/drivers/net/mvgbe.c
@@ -12,6 +12,7 @@
*/
#include <common.h>
+#include <dm.h>
#include <net.h>
#include <malloc.h>
#include <miiphy.h>
@@ -55,20 +56,13 @@ static int smi_wait_ready(struct mvgbe_device *dmvgbe)
return 0;
}
-/*
- * smi_reg_read - miiphy_read callback function.
- *
- * Returns 16bit phy register value, or -EFAULT on error
- */
-static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad,
- int reg_ofs)
+static int __mvgbe_mdio_read(struct mvgbe_device *dmvgbe, int phy_adr,
+ int devad, int reg_ofs)
{
- u16 data = 0;
- struct eth_device *dev = eth_get_dev_by_name(bus->name);
- struct mvgbe_device *dmvgbe = to_mvgbe(dev);
struct mvgbe_registers *regs = dmvgbe->regs;
u32 smi_reg;
u32 timeout;
+ u16 data = 0;
/* Phyadr read request */
if (phy_adr == MV_PHY_ADR_REQUEST &&
@@ -127,15 +121,26 @@ static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad,
}
/*
- * smi_reg_write - miiphy_write callback function.
+ * smi_reg_read - miiphy_read callback function.
*
- * Returns 0 if write succeed, -EFAULT on error
+ * Returns 16bit phy register value, or -EFAULT on error
*/
-static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad,
- int reg_ofs, u16 data)
+static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad,
+ int reg_ofs)
{
+#ifdef CONFIG_DM_ETH
+ struct mvgbe_device *dmvgbe = bus->priv;
+#else
struct eth_device *dev = eth_get_dev_by_name(bus->name);
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
+#endif
+
+ return __mvgbe_mdio_read(dmvgbe, phy_adr, devad, reg_ofs);
+}
+
+static int __mvgbe_mdio_write(struct mvgbe_device *dmvgbe, int phy_adr,
+ int devad, int reg_ofs, u16 data)
+{
struct mvgbe_registers *regs = dmvgbe->regs;
u32 smi_reg;
@@ -171,6 +176,24 @@ static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad,
return 0;
}
+
+/*
+ * smi_reg_write - miiphy_write callback function.
+ *
+ * Returns 0 if write succeed, -EFAULT on error
+ */
+static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad,
+ int reg_ofs, u16 data)
+{
+#ifdef CONFIG_DM_ETH
+ struct mvgbe_device *dmvgbe = bus->priv;
+#else
+ struct eth_device *dev = eth_get_dev_by_name(bus->name);
+ struct mvgbe_device *dmvgbe = to_mvgbe(dev);
+#endif
+
+ return __mvgbe_mdio_write(dmvgbe, phy_adr, devad, reg_ofs, data);
+}
#endif
/* Stop and checks all queues */
@@ -357,8 +380,9 @@ static int port_uc_addr(struct mvgbe_registers *regs, u8 uc_nibble,
/*
* port_uc_addr_set - This function Set the port Unicast address.
*/
-static void port_uc_addr_set(struct mvgbe_registers *regs, u8 * p_addr)
+static void port_uc_addr_set(struct mvgbe_device *dmvgbe, u8 *p_addr)
{
+ struct mvgbe_registers *regs = dmvgbe->regs;
u32 mac_h;
u32 mac_l;
@@ -400,12 +424,13 @@ static void mvgbe_init_rx_desc_ring(struct mvgbe_device *dmvgbe)
dmvgbe->p_rxdesc_curr = dmvgbe->p_rxdesc;
}
-static int mvgbe_init(struct eth_device *dev)
+static int __mvgbe_init(struct mvgbe_device *dmvgbe, u8 *enetaddr,
+ const char *name)
{
- struct mvgbe_device *dmvgbe = to_mvgbe(dev);
struct mvgbe_registers *regs = dmvgbe->regs;
#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
!defined(CONFIG_PHYLIB) && \
+ !defined(CONFIG_DM_ETH) && \
defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
int i;
#endif
@@ -422,7 +447,7 @@ static int mvgbe_init(struct eth_device *dev)
set_dram_access(regs);
port_init_mac_tables(regs);
- port_uc_addr_set(regs, dmvgbe->dev.enetaddr);
+ port_uc_addr_set(dmvgbe, enetaddr);
/* Assign port configuration and command. */
MVGBE_REG_WR(regs->pxc, PRT_CFG_VAL);
@@ -459,28 +484,37 @@ static int mvgbe_init(struct eth_device *dev)
#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
!defined(CONFIG_PHYLIB) && \
+ !defined(CONFIG_DM_ETH) && \
defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
/* Wait up to 5s for the link status */
for (i = 0; i < 5; i++) {
u16 phyadr;
- miiphy_read(dev->name, MV_PHY_ADR_REQUEST,
+ miiphy_read(name, MV_PHY_ADR_REQUEST,
MV_PHY_ADR_REQUEST, &phyadr);
/* Return if we get link up */
- if (miiphy_link(dev->name, phyadr))
+ if (miiphy_link(name, phyadr))
return 0;
udelay(1000000);
}
- printf("No link on %s\n", dev->name);
+ printf("No link on %s\n", name);
return -1;
#endif
return 0;
}
-static int mvgbe_halt(struct eth_device *dev)
+#ifndef CONFIG_DM_ETH
+static int mvgbe_init(struct eth_device *dev)
{
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
+
+ return __mvgbe_init(dmvgbe, dmvgbe->dev.enetaddr, dmvgbe->dev.name);
+}
+#endif
+
+static void __mvgbe_halt(struct mvgbe_device *dmvgbe)
+{
struct mvgbe_registers *regs = dmvgbe->regs;
/* Disable all gigE address decoder */
@@ -502,23 +536,42 @@ static int mvgbe_halt(struct eth_device *dev)
MVGBE_REG_WR(regs->ice, 0);
MVGBE_REG_WR(regs->pim, 0);
MVGBE_REG_WR(regs->peim, 0);
+}
+
+#ifndef CONFIG_DM_ETH
+static int mvgbe_halt(struct eth_device *dev)
+{
+ struct mvgbe_device *dmvgbe = to_mvgbe(dev);
+
+ __mvgbe_halt(dmvgbe);
return 0;
}
+#endif
+
+#ifdef CONFIG_DM_ETH
+static int mvgbe_write_hwaddr(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ port_uc_addr_set(dev_get_priv(dev), pdata->enetaddr);
+
+ return 0;
+}
+#else
static int mvgbe_write_hwaddr(struct eth_device *dev)
{
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
- struct mvgbe_registers *regs = dmvgbe->regs;
/* Programs net device MAC address after initialization */
- port_uc_addr_set(regs, dmvgbe->dev.enetaddr);
+ port_uc_addr_set(dmvgbe, dmvgbe->dev.enetaddr);
return 0;
}
+#endif
-static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize)
+static int __mvgbe_send(struct mvgbe_device *dmvgbe, void *dataptr,
+ int datasize)
{
- struct mvgbe_device *dmvgbe = to_mvgbe(dev);
struct mvgbe_registers *regs = dmvgbe->regs;
struct mvgbe_txdesc *p_txdesc = dmvgbe->p_txdesc;
void *p = (void *)dataptr;
@@ -571,13 +624,25 @@ static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize)
return 0;
}
-static int mvgbe_recv(struct eth_device *dev)
+#ifndef CONFIG_DM_ETH
+static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize)
{
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
+
+ return __mvgbe_send(dmvgbe, dataptr, datasize);
+}
+#endif
+
+static int __mvgbe_recv(struct mvgbe_device *dmvgbe, uchar **packetp)
+{
struct mvgbe_rxdesc *p_rxdesc_curr = dmvgbe->p_rxdesc_curr;
u32 cmd_sts;
u32 timeout = 0;
u32 rxdesc_curr_addr;
+ unsigned char *data;
+ int rx_bytes = 0;
+
+ *packetp = NULL;
/* wait untill rx packet available or timeout */
do {
@@ -621,11 +686,11 @@ static int mvgbe_recv(struct eth_device *dev)
" upper layer (net_process_received_packet)\n",
__func__);
- /* let the upper layer handle the packet */
- net_process_received_packet((p_rxdesc_curr->buf_ptr +
- RX_BUF_OFFSET),
- (int)(p_rxdesc_curr->byte_cnt -
- RX_BUF_OFFSET));
+ data = (p_rxdesc_curr->buf_ptr + RX_BUF_OFFSET);
+ rx_bytes = (int)(p_rxdesc_curr->byte_cnt -
+ RX_BUF_OFFSET);
+
+ *packetp = data;
}
/*
* free these descriptors and point next in the ring
@@ -638,10 +703,59 @@ static int mvgbe_recv(struct eth_device *dev)
rxdesc_curr_addr = (u32)&dmvgbe->p_rxdesc_curr;
writel((unsigned)p_rxdesc_curr->nxtdesc_p, rxdesc_curr_addr);
+ return rx_bytes;
+}
+
+#ifndef CONFIG_DM_ETH
+static int mvgbe_recv(struct eth_device *dev)
+{
+ struct mvgbe_device *dmvgbe = to_mvgbe(dev);
+ uchar *packet;
+ int ret;
+
+ ret = __mvgbe_recv(dmvgbe, &packet);
+ if (ret < 0)
+ return ret;
+
+ net_process_received_packet(packet, ret);
+
return 0;
}
+#endif
-#if defined(CONFIG_PHYLIB)
+#if defined(CONFIG_PHYLIB) || defined(CONFIG_DM_ETH)
+#if defined(CONFIG_DM_ETH)
+static struct phy_device *__mvgbe_phy_init(struct udevice *dev,
+ struct mii_dev *bus,
+ phy_interface_t phy_interface,
+ int phyid)
+#else
+static struct phy_device *__mvgbe_phy_init(struct eth_device *dev,
+ struct mii_dev *bus,
+ phy_interface_t phy_interface,
+ int phyid)
+#endif
+{
+ struct phy_device *phydev;
+
+ /* Set phy address of the port */
+ miiphy_write(dev->name, MV_PHY_ADR_REQUEST, MV_PHY_ADR_REQUEST,
+ phyid);
+
+ phydev = phy_connect(bus, phyid, dev, phy_interface);
+ if (!phydev) {
+ printf("phy_connect failed\n");
+ return NULL;
+ }
+
+ phy_config(phydev);
+ phy_startup(phydev);
+
+ return phydev;
+}
+#endif /* CONFIG_PHYLIB || CONFIG_DM_ETH */
+
+#if defined(CONFIG_PHYLIB) && !defined(CONFIG_DM_ETH)
int mvgbe_phylib_init(struct eth_device *dev, int phyid)
{
struct mii_dev *bus;
@@ -664,27 +778,53 @@ int mvgbe_phylib_init(struct eth_device *dev, int phyid)
return -ENOMEM;
}
- /* Set phy address of the port */
- smi_reg_write(bus, MV_PHY_ADR_REQUEST, 0, MV_PHY_ADR_REQUEST, phyid);
-
- phydev = phy_connect(bus, phyid, dev, PHY_INTERFACE_MODE_RGMII);
- if (!phydev) {
- printf("phy_connect failed\n");
+ phydev = __mvgbe_phy_init(dev, bus, PHY_INTERFACE_MODE_RGMII, phyid);
+ if (!phydev)
return -ENODEV;
- }
-
- phy_config(phydev);
- phy_startup(phydev);
return 0;
}
#endif
+static int mvgbe_alloc_buffers(struct mvgbe_device *dmvgbe)
+{
+ dmvgbe->p_rxdesc = memalign(PKTALIGN,
+ MV_RXQ_DESC_ALIGNED_SIZE * RINGSZ + 1);
+ if (!dmvgbe->p_rxdesc)
+ goto error1;
+
+ dmvgbe->p_rxbuf = memalign(PKTALIGN,
+ RINGSZ * PKTSIZE_ALIGN + 1);
+ if (!dmvgbe->p_rxbuf)
+ goto error2;
+
+ dmvgbe->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN);
+ if (!dmvgbe->p_aligned_txbuf)
+ goto error3;
+
+ dmvgbe->p_txdesc = memalign(PKTALIGN, sizeof(struct mvgbe_txdesc) + 1);
+ if (!dmvgbe->p_txdesc)
+ goto error4;
+
+ return 0;
+
+error4:
+ free(dmvgbe->p_aligned_txbuf);
+error3:
+ free(dmvgbe->p_rxbuf);
+error2:
+ free(dmvgbe->p_rxdesc);
+error1:
+ return -ENOMEM;
+}
+
+#ifndef CONFIG_DM_ETH
int mvgbe_initialize(bd_t *bis)
{
struct mvgbe_device *dmvgbe;
struct eth_device *dev;
int devnum;
+ int ret;
u8 used_ports[MAX_MVGBE_DEVS] = CONFIG_MVGBE_PORTS;
for (devnum = 0; devnum < MAX_MVGBE_DEVS; devnum++) {
@@ -693,45 +833,16 @@ int mvgbe_initialize(bd_t *bis)
continue;
dmvgbe = malloc(sizeof(struct mvgbe_device));
-
if (!dmvgbe)
- goto error1;
+ return -ENOMEM;
memset(dmvgbe, 0, sizeof(struct mvgbe_device));
-
- dmvgbe->p_rxdesc =
- (struct mvgbe_rxdesc *)memalign(PKTALIGN,
- MV_RXQ_DESC_ALIGNED_SIZE*RINGSZ + 1);
-
- if (!dmvgbe->p_rxdesc)
- goto error2;
-
- dmvgbe->p_rxbuf = (u8 *) memalign(PKTALIGN,
- RINGSZ*PKTSIZE_ALIGN + 1);
-
- if (!dmvgbe->p_rxbuf)
- goto error3;
-
- dmvgbe->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN);
-
- if (!dmvgbe->p_aligned_txbuf)
- goto error4;
-
- dmvgbe->p_txdesc = (struct mvgbe_txdesc *) memalign(
- PKTALIGN, sizeof(struct mvgbe_txdesc) + 1);
-
- if (!dmvgbe->p_txdesc) {
- free(dmvgbe->p_aligned_txbuf);
-error4:
- free(dmvgbe->p_rxbuf);
-error3:
- free(dmvgbe->p_rxdesc);
-error2:
- free(dmvgbe);
-error1:
+ ret = mvgbe_alloc_buffers(dmvgbe);
+ if (ret) {
printf("Err.. %s Failed to allocate memory\n",
__func__);
- return -1;
+ free(dmvgbe);
+ return ret;
}
dev = &dmvgbe->dev;
@@ -783,3 +894,154 @@ error1:
}
return 0;
}
+#endif
+
+#ifdef CONFIG_DM_ETH
+static int mvgbe_port_is_fixed_link(struct mvgbe_device *dmvgbe)
+{
+ return dmvgbe->phyaddr > PHY_MAX_ADDR;
+}
+
+static int mvgbe_start(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct mvgbe_device *dmvgbe = dev_get_priv(dev);
+ int ret;
+
+ ret = __mvgbe_init(dmvgbe, pdata->enetaddr, dev->name);
+ if (ret)
+ return ret;
+
+ if (!mvgbe_port_is_fixed_link(dmvgbe)) {
+ dmvgbe->phydev = __mvgbe_phy_init(dev, dmvgbe->bus,
+ dmvgbe->phy_interface,
+ dmvgbe->phyaddr);
+ if (!dmvgbe->phydev)
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int mvgbe_send(struct udevice *dev, void *packet, int length)
+{
+ struct mvgbe_device *dmvgbe = dev_get_priv(dev);
+
+ return __mvgbe_send(dmvgbe, packet, length);
+}
+
+static int mvgbe_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+ struct mvgbe_device *dmvgbe = dev_get_priv(dev);
+
+ return __mvgbe_recv(dmvgbe, packetp);
+}
+
+static void mvgbe_stop(struct udevice *dev)
+{
+ struct mvgbe_device *dmvgbe = dev_get_priv(dev);
+
+ __mvgbe_halt(dmvgbe);
+}
+
+static int mvgbe_probe(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct mvgbe_device *dmvgbe = dev_get_priv(dev);
+ struct mii_dev *bus;
+ int ret;
+
+ ret = mvgbe_alloc_buffers(dmvgbe);
+ if (ret)
+ return ret;
+
+ dmvgbe->regs = (void __iomem *)pdata->iobase;
+
+ bus = mdio_alloc();
+ if (!bus) {
+ printf("Failed to allocate MDIO bus\n");
+ return -ENOMEM;
+ }
+
+ bus->read = smi_reg_read;
+ bus->write = smi_reg_write;
+ snprintf(bus->name, sizeof(bus->name), dev->name);
+ bus->priv = dmvgbe;
+ dmvgbe->bus = bus;
+
+ ret = mdio_register(bus);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static const struct eth_ops mvgbe_ops = {
+ .start = mvgbe_start,
+ .send = mvgbe_send,
+ .recv = mvgbe_recv,
+ .stop = mvgbe_stop,
+ .write_hwaddr = mvgbe_write_hwaddr,
+};
+
+static int mvgbe_ofdata_to_platdata(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct mvgbe_device *dmvgbe = dev_get_priv(dev);
+ void *blob = (void *)gd->fdt_blob;
+ int node = dev_of_offset(dev);
+ const char *phy_mode;
+ int fl_node;
+ int pnode;
+ unsigned long addr;
+
+ pdata->iobase = devfdt_get_addr(dev);
+ pdata->phy_interface = -1;
+
+ pnode = fdt_node_offset_by_compatible(blob, node,
+ "marvell,kirkwood-eth-port");
+
+ /* Get phy-mode / phy_interface from DT */
+ phy_mode = fdt_getprop(gd->fdt_blob, pnode, "phy-mode", NULL);
+ if (phy_mode)
+ pdata->phy_interface = phy_get_interface_by_name(phy_mode);
+ if (pdata->phy_interface == -1) {
+ debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
+ return -EINVAL;
+ }
+
+ dmvgbe->phy_interface = pdata->phy_interface;
+
+ /* fetch 'fixed-link' property */
+ fl_node = fdt_subnode_offset(blob, pnode, "fixed-link");
+ if (fl_node != -FDT_ERR_NOTFOUND) {
+ /* set phy_addr to invalid value for fixed link */
+ dmvgbe->phyaddr = PHY_MAX_ADDR + 1;
+ dmvgbe->duplex = fdtdec_get_bool(blob, fl_node, "full-duplex");
+ dmvgbe->speed = fdtdec_get_int(blob, fl_node, "speed", 0);
+ } else {
+ /* Now read phyaddr from DT */
+ addr = fdtdec_lookup_phandle(blob, pnode, "phy-handle");
+ if (addr > 0)
+ dmvgbe->phyaddr = fdtdec_get_int(blob, addr, "reg", 0);
+ }
+
+ return 0;
+}
+
+static const struct udevice_id mvgbe_ids[] = {
+ { .compatible = "marvell,kirkwood-eth" },
+ { }
+};
+
+U_BOOT_DRIVER(mvgbe) = {
+ .name = "mvgbe",
+ .id = UCLASS_ETH,
+ .of_match = mvgbe_ids,
+ .ofdata_to_platdata = mvgbe_ofdata_to_platdata,
+ .probe = mvgbe_probe,
+ .ops = &mvgbe_ops,
+ .priv_auto_alloc_size = sizeof(struct mvgbe_device),
+ .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
+#endif /* CONFIG_DM_ETH */
diff --git a/drivers/net/mvgbe.h b/drivers/net/mvgbe.h
index 1dc9bbea2f..44541c0a85 100644
--- a/drivers/net/mvgbe.h
+++ b/drivers/net/mvgbe.h
@@ -30,7 +30,9 @@
#define RXUQ 0 /* Used Rx queue */
#define TXUQ 0 /* Used Rx queue */
+#ifndef CONFIG_DM_ETH
#define to_mvgbe(_d) container_of(_d, struct mvgbe_device, dev)
+#endif
#define MVGBE_REG_WR(adr, val) writel(val, &adr)
#define MVGBE_REG_RD(adr) readl(&adr)
#define MVGBE_REG_BITS_RESET(adr, val) writel(readl(&adr) & ~(val), &adr)
@@ -479,13 +481,27 @@ struct mvgbe_txdesc {
/* port device data struct */
struct mvgbe_device {
+#ifndef CONFIG_DM_ETH
struct eth_device dev;
+#endif
struct mvgbe_registers *regs;
struct mvgbe_txdesc *p_txdesc;
struct mvgbe_rxdesc *p_rxdesc;
struct mvgbe_rxdesc *p_rxdesc_curr;
u8 *p_rxbuf;
u8 *p_aligned_txbuf;
+
+#ifdef CONFIG_DM_ETH
+ phy_interface_t phy_interface;
+ unsigned int link;
+ unsigned int duplex;
+ unsigned int speed;
+
+ int init;
+ int phyaddr;
+ struct phy_device *phydev;
+ struct mii_dev *bus;
+#endif
};
#endif /* __MVGBE_H__ */
diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c
index 79f68af14c..3783d155e7 100644
--- a/drivers/net/phy/atheros.c
+++ b/drivers/net/phy/atheros.c
@@ -5,6 +5,7 @@
* Copyright 2011, 2013 Freescale Semiconductor, Inc.
* author Andy Fleming
*/
+#include <common.h>
#include <phy.h>
#define AR803x_PHY_DEBUG_ADDR_REG 0x1d
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 202e3dd487..3399fd2366 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -5,7 +5,6 @@
* Copyright 2010-2011 Freescale Semiconductor, Inc.
* author Andy Fleming
*/
-#include <config.h>
#include <common.h>
#include <phy.h>
diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c
index 27c7788493..4666497d44 100644
--- a/drivers/net/phy/davicom.c
+++ b/drivers/net/phy/davicom.c
@@ -5,6 +5,7 @@
* Copyright 2010-2011 Freescale Semiconductor, Inc.
* author Andy Fleming
*/
+#include <common.h>
#include <phy.h>
#define MIIM_DM9161_SCR 0x10
diff --git a/drivers/net/phy/generic_10g.c b/drivers/net/phy/generic_10g.c
index 1024d7db7b..b4384e1f78 100644
--- a/drivers/net/phy/generic_10g.c
+++ b/drivers/net/phy/generic_10g.c
@@ -7,8 +7,6 @@
*
* Based loosely off of Linux's PHY Lib
*/
-
-#include <config.h>
#include <common.h>
#include <miiphy.h>
#include <phy.h>
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
index 5942664f1c..2618deb009 100644
--- a/drivers/net/phy/lxt.c
+++ b/drivers/net/phy/lxt.c
@@ -5,6 +5,7 @@
* Copyright 2010-2011 Freescale Semiconductor, Inc.
* author Andy Fleming
*/
+#include <common.h>
#include <phy.h>
/* LXT971 Status 2 registers */
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 436ff572fe..efbbd31ff7 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -5,7 +5,6 @@
* Copyright 2010-2011 Freescale Semiconductor, Inc.
* author Andy Fleming
*/
-#include <config.h>
#include <common.h>
#include <errno.h>
#include <phy.h>
diff --git a/drivers/net/phy/micrel_ksz8xxx.c b/drivers/net/phy/micrel_ksz8xxx.c
index c70c0364b8..3411150ab9 100644
--- a/drivers/net/phy/micrel_ksz8xxx.c
+++ b/drivers/net/phy/micrel_ksz8xxx.c
@@ -6,7 +6,6 @@
* author Andy Fleming
* (C) 2012 NetModule AG, David Andrey, added KSZ9031
*/
-#include <config.h>
#include <common.h>
#include <dm.h>
#include <errno.h>
diff --git a/drivers/net/phy/micrel_ksz90x1.c b/drivers/net/phy/micrel_ksz90x1.c
index 5462532be6..3951535bf1 100644
--- a/drivers/net/phy/micrel_ksz90x1.c
+++ b/drivers/net/phy/micrel_ksz90x1.c
@@ -8,8 +8,6 @@
* (C) Copyright 2017 Adaptrum, Inc.
* Written by Alexandru Gagniuc <alex.g@adaptrum.com> for Adaptrum, Inc.
*/
-
-#include <config.h>
#include <common.h>
#include <dm.h>
#include <errno.h>
diff --git a/drivers/net/phy/natsemi.c b/drivers/net/phy/natsemi.c
index 05c7e7c089..efde4574de 100644
--- a/drivers/net/phy/natsemi.c
+++ b/drivers/net/phy/natsemi.c
@@ -5,6 +5,7 @@
* Copyright 2010-2011 Freescale Semiconductor, Inc.
* author Andy Fleming
*/
+#include <common.h>
#include <phy.h>
/* NatSemi DP83630 */
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 4e610bf054..e837eb7688 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -7,8 +7,6 @@
*
* Based loosely off of Linux's PHY Lib
*/
-
-#include <config.h>
#include <common.h>
#include <console.h>
#include <dm.h>
@@ -644,6 +642,10 @@ static struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
dev->link = 0;
dev->interface = interface;
+#ifdef CONFIG_DM_ETH
+ dev->node = ofnode_null();
+#endif
+
dev->autoneg = AUTONEG_ENABLE;
dev->addr = addr;
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index b0867af220..b3e6578df9 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -6,7 +6,6 @@
* author Andy Fleming
* Copyright 2016 Karsten Merker <merker@debian.org>
*/
-#include <config.h>
#include <common.h>
#include <linux/bitops.h>
#include <phy.h>
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 2f92957a5a..7740a2510d 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -9,6 +9,7 @@
* Some code copied from linux kernel
* Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.org>
*/
+#include <common.h>
#include <miiphy.h>
/* This code does not check the partner abilities. */
diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c
index d674e8f857..49d6a1ad90 100644
--- a/drivers/net/phy/teranetics.c
+++ b/drivers/net/phy/teranetics.c
@@ -5,7 +5,6 @@
* Copyright 2010-2011 Freescale Semiconductor, Inc.
* author Andy Fleming
*/
-#include <config.h>
#include <common.h>
#include <phy.h>
diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c
index 8f3ed8a983..f870e6d662 100644
--- a/drivers/net/phy/ti.c
+++ b/drivers/net/phy/ti.c
@@ -8,11 +8,9 @@
#include <linux/compat.h>
#include <malloc.h>
-#include <fdtdec.h>
#include <dm.h>
#include <dt-bindings/net/ti-dp83867.h>
-DECLARE_GLOBAL_DATA_PTR;
/* TI DP83867 */
#define DP83867_DEVADDR 0x1f
@@ -24,6 +22,7 @@ DECLARE_GLOBAL_DATA_PTR;
#define DP83867_CTRL 0x1f
/* Extended Registers */
+#define DP83867_CFG4 0x0031
#define DP83867_RGMIICTL 0x0032
#define DP83867_RGMIIDCTL 0x0086
#define DP83867_IO_MUX_CFG 0x0170
@@ -95,6 +94,7 @@ struct dp83867_private {
int tx_id_delay;
int fifo_depth;
int io_impedance;
+ bool rxctrl_strap_quirk;
};
/**
@@ -172,25 +172,31 @@ void phy_write_mmd_indirect(struct phy_device *phydev, int prtad,
static int dp83867_of_init(struct phy_device *phydev)
{
struct dp83867_private *dp83867 = phydev->priv;
- struct udevice *dev = phydev->dev;
- int node = dev_of_offset(dev);
- const void *fdt = gd->fdt_blob;
+ ofnode node;
- if (fdtdec_get_bool(fdt, node, "ti,max-output-impedance"))
+ node = phy_get_ofnode(phydev);
+ if (!ofnode_valid(node))
+ return -EINVAL;
+
+ if (ofnode_read_bool(node, "ti,max-output-impedance"))
dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX;
- else if (fdtdec_get_bool(fdt, node, "ti,min-output-impedance"))
+ else if (ofnode_read_bool(node, "ti,min-output-impedance"))
dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN;
else
dp83867->io_impedance = -EINVAL;
- dp83867->rx_id_delay = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
- "ti,rx-internal-delay", -1);
+ if (ofnode_read_bool(node, "ti,dp83867-rxctrl-strap-quirk"))
+ dp83867->rxctrl_strap_quirk = true;
+ dp83867->rx_id_delay = ofnode_read_u32_default(node,
+ "ti,rx-internal-delay",
+ -1);
- dp83867->tx_id_delay = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
- "ti,tx-internal-delay", -1);
+ dp83867->tx_id_delay = ofnode_read_u32_default(node,
+ "ti,tx-internal-delay",
+ -1);
- dp83867->fifo_depth = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
- "ti,fifo-depth", -1);
+ dp83867->fifo_depth = ofnode_read_u32_default(node, "ti,fifo-depth",
+ -1);
return 0;
}
@@ -232,6 +238,15 @@ static int dp83867_config(struct phy_device *phydev)
phy_write(phydev, MDIO_DEVAD_NONE, DP83867_CTRL,
val | DP83867_SW_RESTART);
+ /* Mode 1 or 2 workaround */
+ if (dp83867->rxctrl_strap_quirk) {
+ val = phy_read_mmd_indirect(phydev, DP83867_CFG4,
+ DP83867_DEVADDR, phydev->addr);
+ val &= ~BIT(7);
+ phy_write_mmd_indirect(phydev, DP83867_CFG4,
+ DP83867_DEVADDR, phydev->addr, val);
+ }
+
if (phy_interface_is_rgmii(phydev)) {
ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL,
(DP83867_MDI_CROSSOVER_AUTO << DP83867_MDI_CROSSOVER) |
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 9df4a3fae5..eca26c9893 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -6,6 +6,7 @@
* Original Author: Andy Fleming
* Add vsc8662 phy support - Priyanka Jain
*/
+#include <common.h>
#include <miiphy.h>
/* Cicada Auxiliary Control/Status Register */
diff --git a/drivers/net/phy/xilinx_phy.c b/drivers/net/phy/xilinx_phy.c
index 004cfcf647..3aa8891efe 100644
--- a/drivers/net/phy/xilinx_phy.c
+++ b/drivers/net/phy/xilinx_phy.c
@@ -10,8 +10,6 @@
#include <phy.h>
#include <dm.h>
-DECLARE_GLOBAL_DATA_PTR;
-
#define MII_PHY_STATUS_SPD_MASK 0x0C00
#define MII_PHY_STATUS_FULLDUPLEX 0x1000
#define MII_PHY_STATUS_1000 0x0800
@@ -101,10 +99,14 @@ static int xilinxphy_startup(struct phy_device *phydev)
static int xilinxphy_of_init(struct phy_device *phydev)
{
u32 phytype;
+ ofnode node;
debug("%s\n", __func__);
- phytype = fdtdec_get_int(gd->fdt_blob, dev_of_offset(phydev->dev),
- "xlnx,phy-type", -1);
+ node = phy_get_ofnode(phydev);
+ if (!ofnode_valid(node))
+ return -EINVAL;
+
+ phytype = ofnode_read_u32_default(node, "xlnx,phy-type", -1);
if (phytype == XAE_PHY_TYPE_1000BASE_X)
phydev->flags |= XAE_PHY_TYPE_1000BASE_X;
diff --git a/drivers/net/sandbox-raw-bus.c b/drivers/net/sandbox-raw-bus.c
new file mode 100644
index 0000000000..76d65afe6c
--- /dev/null
+++ b/drivers/net/sandbox-raw-bus.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2018 National Instruments
+ * Copyright (c) 2018 Joe Hershberger <joe.hershberger@ni.com>
+ */
+
+#include <common.h>
+#include <asm/eth-raw-os.h>
+#include <dm.h>
+#include <errno.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+
+static int eth_raw_bus_post_bind(struct udevice *dev)
+{
+ struct sandbox_eth_raw_if_nameindex *ni, *i;
+ struct udevice *child;
+ struct eth_sandbox_raw_priv *priv;
+ char *ub_ifname;
+ static const char ub_ifname_pfx[] = "host_";
+ u32 skip_localhost = 0;
+
+ ni = sandbox_eth_raw_if_nameindex();
+ if (!ni)
+ return -EINVAL;
+
+ dev_read_u32(dev, "skip-localhost", &skip_localhost);
+ for (i = ni; !(i->if_index == 0 && !i->if_name); i++) {
+ int local = sandbox_eth_raw_os_is_local(i->if_name);
+
+ if (local < 0)
+ continue;
+ if (skip_localhost && local)
+ continue;
+
+ ub_ifname = calloc(IFNAMSIZ + sizeof(ub_ifname_pfx), 1);
+ strcpy(ub_ifname, ub_ifname_pfx);
+ strncat(ub_ifname, i->if_name, IFNAMSIZ);
+ device_bind_driver(dev, "eth_sandbox_raw", ub_ifname, &child);
+
+ device_set_name_alloced(child);
+ device_probe(child);
+ priv = dev_get_priv(child);
+ if (priv) {
+ memcpy(priv->host_ifname, i->if_name, IFNAMSIZ);
+ priv->host_ifindex = i->if_index;
+ priv->local = local;
+ }
+ }
+
+ sandbox_eth_raw_if_freenameindex(ni);
+
+ return 0;
+}
+
+static const struct udevice_id sandbox_eth_raw_bus_ids[] = {
+ { .compatible = "sandbox,eth-raw-bus" },
+ { }
+};
+
+U_BOOT_DRIVER(sandbox_eth_raw_bus) = {
+ .name = "sb_eth_raw_bus",
+ .id = UCLASS_SIMPLE_BUS,
+ .of_match = sandbox_eth_raw_bus_ids,
+ .bind = eth_raw_bus_post_bind,
+};
diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
index 3f8020f629..09cc678ebd 100644
--- a/drivers/net/sandbox-raw.c
+++ b/drivers/net/sandbox-raw.c
@@ -21,21 +21,18 @@ static int sb_eth_raw_start(struct udevice *dev)
{
struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
struct eth_pdata *pdata = dev_get_platdata(dev);
- const char *interface;
+ int ret;
debug("eth_sandbox_raw: Start\n");
- interface = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
- "host-raw-interface", NULL);
- if (interface == NULL)
- return -EINVAL;
-
- if (strcmp(interface, "lo") == 0) {
- priv->local = 1;
+ ret = sandbox_eth_raw_os_start(priv, pdata->enetaddr);
+ if (priv->local) {
env_set("ipaddr", "127.0.0.1");
env_set("serverip", "127.0.0.1");
+ net_ip = string_to_ip("127.0.0.1");
+ net_server_ip = net_ip;
}
- return sandbox_eth_raw_os_start(interface, pdata->enetaddr, priv);
+ return ret;
}
static int sb_eth_raw_send(struct udevice *dev, void *packet, int length)
@@ -133,18 +130,54 @@ static void sb_eth_raw_stop(struct udevice *dev)
sandbox_eth_raw_os_stop(priv);
}
+static int sb_eth_raw_read_rom_hwaddr(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+
+ net_random_ethaddr(pdata->enetaddr);
+
+ return 0;
+}
+
static const struct eth_ops sb_eth_raw_ops = {
.start = sb_eth_raw_start,
.send = sb_eth_raw_send,
.recv = sb_eth_raw_recv,
.stop = sb_eth_raw_stop,
+ .read_rom_hwaddr = sb_eth_raw_read_rom_hwaddr,
};
static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+ const char *ifname;
+ u32 local;
+ int ret;
+
+ pdata->iobase = dev_read_addr(dev);
+
+ ifname = dev_read_string(dev, "host-raw-interface");
+ if (ifname) {
+ strncpy(priv->host_ifname, ifname, IFNAMSIZ);
+ printf(": Using %s from DT\n", priv->host_ifname);
+ }
+ if (dev_read_u32(dev, "host-raw-interface-idx",
+ &priv->host_ifindex) < 0) {
+ priv->host_ifindex = 0;
+ } else {
+ ret = sandbox_eth_raw_os_idx_to_name(priv);
+ if (ret < 0)
+ return ret;
+ printf(": Using interface index %d from DT (%s)\n",
+ priv->host_ifindex, priv->host_ifname);
+ }
+
+ local = sandbox_eth_raw_os_is_local(priv->host_ifname);
+ if (local < 0)
+ return local;
+ priv->local = local;
- pdata->iobase = devfdt_get_addr(dev);
return 0;
}
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
index b34712bd06..b71c8f88d9 100644
--- a/drivers/net/sandbox.c
+++ b/drivers/net/sandbox.c
@@ -59,10 +59,8 @@ static int sb_eth_start(struct udevice *dev)
debug("eth_sandbox: Start\n");
- fdtdec_get_byte_array(gd->fdt_blob, dev_of_offset(dev),
- "fake-host-hwaddr", priv->fake_host_hwaddr,
- ARP_HLEN);
priv->recv_packet_buffer = net_rx_packets[0];
+
return 0;
}
@@ -203,8 +201,18 @@ static int sb_eth_remove(struct udevice *dev)
static int sb_eth_ofdata_to_platdata(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct eth_sandbox_priv *priv = dev_get_priv(dev);
+ const u8 *mac;
+
+ pdata->iobase = dev_read_addr(dev);
+
+ mac = dev_read_u8_array_ptr(dev, "fake-host-hwaddr", ARP_HLEN);
+ if (!mac) {
+ printf("'fake-host-hwaddr' is missing from the DT\n");
+ return -EINVAL;
+ }
+ memcpy(priv->fake_host_hwaddr, mac, ARP_HLEN);
- pdata->iobase = devfdt_get_addr(dev);
return 0;
}
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index d1138fe090..68d1c2fcea 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -178,7 +178,7 @@ struct zynq_gem_priv {
struct zynq_gem_regs *iobase;
phy_interface_t interface;
struct phy_device *phydev;
- int phy_of_handle;
+ ofnode phy_of_node;
struct mii_dev *bus;
struct clk clk;
u32 max_speed;
@@ -348,9 +348,7 @@ static int zynq_phy_init(struct udevice *dev)
}
priv->phydev->advertising = priv->phydev->supported;
-
- if (priv->phy_of_handle > 0)
- dev_set_of_offset(priv->phydev->dev, priv->phy_of_handle);
+ priv->phydev->node = priv->phy_of_node;
return phy_config(priv->phydev);
}
@@ -693,21 +691,23 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_platdata(dev);
struct zynq_gem_priv *priv = dev_get_priv(dev);
- int node = dev_of_offset(dev);
+ struct ofnode_phandle_args phandle_args;
const char *phy_mode;
- pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
+ pdata->iobase = (phys_addr_t)dev_read_addr(dev);
priv->iobase = (struct zynq_gem_regs *)pdata->iobase;
/* Hardcode for now */
priv->phyaddr = -1;
- priv->phy_of_handle = fdtdec_lookup_phandle(gd->fdt_blob, node,
- "phy-handle");
- if (priv->phy_of_handle > 0)
- priv->phyaddr = fdtdec_get_int(gd->fdt_blob,
- priv->phy_of_handle, "reg", -1);
+ if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
+ &phandle_args)) {
+ debug("phy-handle does not exist %s\n", dev->name);
+ return -ENOENT;
+ }
- phy_mode = fdt_getprop(gd->fdt_blob, node, "phy-mode", NULL);
+ priv->phyaddr = ofnode_read_u32_default(phandle_args.node, "reg", -1);
+ priv->phy_of_node = phandle_args.node;
+ phy_mode = dev_read_prop(dev, "phy-mode", NULL);
if (phy_mode)
pdata->phy_interface = phy_get_interface_by_name(phy_mode);
if (pdata->phy_interface == -1) {
@@ -716,10 +716,8 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev)
}
priv->interface = pdata->phy_interface;
- priv->max_speed = fdtdec_get_uint(gd->fdt_blob, priv->phy_of_handle,
- "max-speed", SPEED_1000);
- priv->int_pcs = fdtdec_get_bool(gd->fdt_blob, node,
- "is-internal-pcspma");
+ priv->max_speed = dev_read_u32_default(dev, "max-speed", SPEED_1000);
+ priv->int_pcs = dev_read_bool(dev, "is-internal-pcspma");
printf("ZYNQ GEM: %lx, phyaddr %x, interface %s\n", (ulong)priv->iobase,
priv->phyaddr, phy_string_for_interface(priv->interface));
diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index 2b3cf48025..a7d7e3f044 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -117,9 +117,6 @@ struct sun4i_usb_phy_info {
.gpio_vbus = CONFIG_USB3_VBUS_PIN,
.gpio_vbus_det = NULL,
.gpio_id_det = NULL,
-#ifdef CONFIG_MACH_SUN6I
- .rst_mask = (CCM_USB_CTRL_PHY3_RST | CCM_USB_CTRL_PHY3_CLK),
-#endif
},
};
@@ -300,8 +297,7 @@ static int sun4i_usb_phy_init(struct phy *phy)
data->cfg->disc_thresh, PHY_DISCON_TH_LEN);
}
- if (usb_phy->id != 0)
- sun4i_usb_phy_passby(phy, true);
+ sun4i_usb_phy_passby(phy, true);
sun4i_usb_phy0_reroute(data, true);
@@ -461,10 +457,10 @@ static int sun4i_usb_phy_probe(struct udevice *dev)
phy->id = i;
phy->rst_mask = info->rst_mask;
+ if ((data->cfg->type == sun8i_h3_phy) && (phy->id == 3))
+ phy->rst_mask = (BIT(3) | BIT(11));
};
- setbits_le32(&data->ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE);
-
debug("Allwinner Sun4I USB PHY driver loaded\n");
return 0;
}
diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
index c7d7644402..020eee2378 100644
--- a/drivers/power/domain/Makefile
+++ b/drivers/power/domain/Makefile
@@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_POWER_DOMAIN) += power-domain-uclass.o
+obj-$(CONFIG_$(SPL_)POWER_DOMAIN) += power-domain-uclass.o
obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o
obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain.o
obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain-test.o
diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
index d504c28b77..cba48e12da 100644
--- a/drivers/power/pmic/Kconfig
+++ b/drivers/power/pmic/Kconfig
@@ -131,7 +131,7 @@ config PMIC_S2MPS11
Binding info: doc/device-tree-bindings/pmic/s2mps11.txt
config DM_PMIC_SANDBOX
- bool "Enable Driver Model for emulated Sandbox PMIC "
+ bool "Enable Driver Model for emulated Sandbox PMIC"
depends on DM_PMIC
---help---
Enable the driver for Sandbox PMIC emulation. The emulated PMIC device
diff --git a/drivers/rtc/at91sam9_rtt.c b/drivers/rtc/at91sam9_rtt.c
index da5bb3e2f7..6f92660ef1 100644
--- a/drivers/rtc/at91sam9_rtt.c
+++ b/drivers/rtc/at91sam9_rtt.c
@@ -27,8 +27,6 @@
#include <asm/arch/at91_rtt.h>
#include <asm/arch/at91_gpbr.h>
-#if defined(CONFIG_CMD_DATE)
-
int rtc_get (struct rtc_time *tmp)
{
at91_rtt_t *rtt = (at91_rtt_t *) ATMEL_BASE_RTT;
@@ -78,5 +76,3 @@ void rtc_reset (void)
while (readl(&rtt->vr) != 0)
;
}
-
-#endif
diff --git a/drivers/rtc/davinci.c b/drivers/rtc/davinci.c
index f03dc56069..b6930bd839 100644
--- a/drivers/rtc/davinci.c
+++ b/drivers/rtc/davinci.c
@@ -9,7 +9,6 @@
#include <asm/io.h>
#include <asm/davinci_rtc.h>
-#if defined(CONFIG_CMD_DATE)
int rtc_get(struct rtc_time *tmp)
{
struct davinci_rtc *rtc = (struct davinci_rtc *)DAVINCI_RTC_BASE;
@@ -79,4 +78,3 @@ void rtc_reset(void)
/* run RTC counter */
writel(0x01, &rtc->ctrl);
}
-#endif
diff --git a/drivers/rtc/ds1302.c b/drivers/rtc/ds1302.c
index 87ddd01916..b94163f748 100644
--- a/drivers/rtc/ds1302.c
+++ b/drivers/rtc/ds1302.c
@@ -9,8 +9,6 @@
#include <command.h>
#include <rtc.h>
-#if defined(CONFIG_CMD_DATE)
-
/* GPP Pins */
#define DATA 0x200
#define SCLK 0x400
@@ -328,5 +326,3 @@ int rtc_set(struct rtc_time *tmp)
return 0;
}
-
-#endif
diff --git a/drivers/rtc/ds1306.c b/drivers/rtc/ds1306.c
index bd1e0845aa..02d617e09c 100644
--- a/drivers/rtc/ds1306.c
+++ b/drivers/rtc/ds1306.c
@@ -19,8 +19,6 @@
#include <rtc.h>
#include <spi.h>
-#if defined(CONFIG_CMD_DATE)
-
#define RTC_SECONDS 0x00
#define RTC_MINUTES 0x01
#define RTC_HOURS 0x02
@@ -437,5 +435,3 @@ static void rtc_write (unsigned char reg, unsigned char val)
}
#endif /* end of code exclusion (see #ifdef CONFIG_SXNI855T above) */
-
-#endif
diff --git a/drivers/rtc/ds1307.c b/drivers/rtc/ds1307.c
index cdb088c9b1..48220b45db 100644
--- a/drivers/rtc/ds1307.c
+++ b/drivers/rtc/ds1307.c
@@ -51,8 +51,6 @@ enum ds_type {
#ifndef CONFIG_DM_RTC
-#if defined(CONFIG_CMD_DATE)
-
/*---------------------------------------------------------------------*/
#undef DEBUG_RTC
@@ -204,8 +202,6 @@ static void rtc_write (uchar reg, uchar val)
i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
}
-#endif /* CONFIG_CMD_DATE*/
-
#endif /* !CONFIG_DM_RTC */
#ifdef CONFIG_DM_RTC
diff --git a/drivers/rtc/ds1337.c b/drivers/rtc/ds1337.c
index 9a0a214386..9b31048e97 100644
--- a/drivers/rtc/ds1337.c
+++ b/drivers/rtc/ds1337.c
@@ -15,8 +15,6 @@
#include <rtc.h>
#include <i2c.h>
-#if defined(CONFIG_CMD_DATE)
-
/*
* RTC register addresses
*/
@@ -190,5 +188,3 @@ static void rtc_write (uchar reg, uchar val)
{
i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
}
-
-#endif
diff --git a/drivers/rtc/ds1374.c b/drivers/rtc/ds1374.c
index bc27f61c72..5a2060fe75 100644
--- a/drivers/rtc/ds1374.c
+++ b/drivers/rtc/ds1374.c
@@ -18,8 +18,6 @@
#include <rtc.h>
#include <i2c.h>
-#if defined(CONFIG_CMD_DATE)
-
/*---------------------------------------------------------------------*/
#undef DEBUG_RTC
#define DEBUG_RTC
@@ -214,4 +212,3 @@ static void rtc_write_raw (uchar reg, uchar val)
{
i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
}
-#endif
diff --git a/drivers/rtc/ds164x.c b/drivers/rtc/ds164x.c
index 7ee6214b2b..f8707892e7 100644
--- a/drivers/rtc/ds164x.c
+++ b/drivers/rtc/ds164x.c
@@ -20,8 +20,6 @@
#include <rtc.h>
-#if defined(CONFIG_CMD_DATE)
-
static uchar rtc_read(unsigned int addr );
static void rtc_write(unsigned int addr, uchar val);
@@ -171,5 +169,3 @@ static void rtc_write( unsigned int addr, uchar val )
#endif
*(volatile unsigned char*)(addr) = val;
}
-
-#endif
diff --git a/drivers/rtc/ds174x.c b/drivers/rtc/ds174x.c
index b6daf59e80..94f943d97a 100644
--- a/drivers/rtc/ds174x.c
+++ b/drivers/rtc/ds174x.c
@@ -16,8 +16,6 @@
#include <command.h>
#include <rtc.h>
-#if defined(CONFIG_CMD_DATE)
-
static uchar rtc_read( unsigned int addr );
static void rtc_write( unsigned int addr, uchar val);
@@ -172,5 +170,3 @@ static void rtc_write( unsigned int addr, uchar val )
#endif
out8( addr, val );
}
-
-#endif
diff --git a/drivers/rtc/ds3231.c b/drivers/rtc/ds3231.c
index 0e66f6ea0f..9352ff87a2 100644
--- a/drivers/rtc/ds3231.c
+++ b/drivers/rtc/ds3231.c
@@ -16,8 +16,6 @@
#include <rtc.h>
#include <i2c.h>
-#if defined(CONFIG_CMD_DATE)
-
/*
* RTC register addresses
*/
@@ -166,5 +164,3 @@ static void rtc_write (uchar reg, uchar val)
{
i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
}
-
-#endif
diff --git a/drivers/rtc/imxdi.c b/drivers/rtc/imxdi.c
index 3c4797f4c5..39920f1a7a 100644
--- a/drivers/rtc/imxdi.c
+++ b/drivers/rtc/imxdi.c
@@ -17,8 +17,6 @@
#include <linux/compat.h>
#include <rtc.h>
-#if defined(CONFIG_CMD_DATE)
-
#include <asm/io.h>
#include <asm/arch/imx-regs.h>
@@ -222,5 +220,3 @@ void rtc_reset(void)
{
di_init();
}
-
-#endif
diff --git a/drivers/rtc/m41t11.c b/drivers/rtc/m41t11.c
index e997152098..960348bb3e 100644
--- a/drivers/rtc/m41t11.c
+++ b/drivers/rtc/m41t11.c
@@ -29,8 +29,6 @@
#endif
*/
-#if defined(CONFIG_SYS_I2C_RTC_ADDR) && defined(CONFIG_CMD_DATE)
-
/* ------------------------------------------------------------------------- */
/*
these are simple defines for the chip local to here so they aren't too
@@ -167,4 +165,3 @@ void rtc_reset (void)
val = val & 0x3F;/*turn off freq test keep calibration*/
i2c_write(CONFIG_SYS_I2C_RTC_ADDR, RTC_CONTROL_ADDR, 1, &val, 1);
}
-#endif
diff --git a/drivers/rtc/m41t60.c b/drivers/rtc/m41t60.c
index 7846193e26..c84c8e11b3 100644
--- a/drivers/rtc/m41t60.c
+++ b/drivers/rtc/m41t60.c
@@ -20,8 +20,6 @@
#include <rtc.h>
#include <i2c.h>
-#if defined(CONFIG_SYS_I2C_RTC_ADDR) && defined(CONFIG_CMD_DATE)
-
/*
* Convert between century and "century bits" (CB1 and CB0). These routines
* assume years are in the range 1900 - 2299.
@@ -237,4 +235,3 @@ void rtc_reset(void)
}
rtc_dump("end reset");
}
-#endif /* CONFIG_RTC_M41T60 && CONFIG_SYS_I2C_RTC_ADDR && CONFIG_CMD_DATE */
diff --git a/drivers/rtc/m41t62.c b/drivers/rtc/m41t62.c
index d53ef7d862..137438389d 100644
--- a/drivers/rtc/m41t62.c
+++ b/drivers/rtc/m41t62.c
@@ -18,8 +18,6 @@
#include <rtc.h>
#include <i2c.h>
-#if defined(CONFIG_CMD_DATE)
-
#define M41T62_REG_SSEC 0
#define M41T62_REG_SEC 1
#define M41T62_REG_MIN 2
@@ -130,5 +128,3 @@ void rtc_reset(void)
val &= ~M41T80_ALHOUR_HT;
i2c_write(CONFIG_SYS_I2C_RTC_ADDR, M41T62_REG_ALARM_HOUR, 1, &val, 1);
}
-
-#endif
diff --git a/drivers/rtc/m48t35ax.c b/drivers/rtc/m48t35ax.c
index 0b035ced26..1cc24cccae 100644
--- a/drivers/rtc/m48t35ax.c
+++ b/drivers/rtc/m48t35ax.c
@@ -16,8 +16,6 @@
#include <rtc.h>
#include <config.h>
-#if defined(CONFIG_CMD_DATE)
-
static uchar rtc_read (uchar reg);
static void rtc_write (uchar reg, uchar val);
@@ -135,5 +133,3 @@ static void rtc_write (uchar reg, uchar val)
*(unsigned char *)
((CONFIG_SYS_NVRAM_BASE_ADDR + CONFIG_SYS_NVRAM_SIZE - 8) + reg) = val;
}
-
-#endif
diff --git a/drivers/rtc/max6900.c b/drivers/rtc/max6900.c
index f5c651bad0..b35186579a 100644
--- a/drivers/rtc/max6900.c
+++ b/drivers/rtc/max6900.c
@@ -15,8 +15,6 @@
#include <rtc.h>
#include <i2c.h>
-#if defined(CONFIG_CMD_DATE)
-
#ifndef CONFIG_SYS_I2C_RTC_ADDR
#define CONFIG_SYS_I2C_RTC_ADDR 0x50
#endif
@@ -104,5 +102,3 @@ int rtc_set (struct rtc_time *tmp)
void rtc_reset (void)
{
}
-
-#endif
diff --git a/drivers/rtc/mc146818.c b/drivers/rtc/mc146818.c
index ee29c711aa..b98c39d821 100644
--- a/drivers/rtc/mc146818.c
+++ b/drivers/rtc/mc146818.c
@@ -19,8 +19,6 @@
#define out8(p, v) outb(v, p)
#endif
-#if defined(CONFIG_CMD_DATE)
-
/* Set this to 1 to clear the CMOS RAM */
#define CLEAR_CMOS 0
@@ -145,7 +143,8 @@ static int mc146818_set(struct rtc_time *tmp)
mc146818_write8(RTC_YEAR, bin2bcd(tmp->tm_year % 100));
mc146818_write8(RTC_MONTH, bin2bcd(tmp->tm_mon));
- mc146818_write8(RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday));
+ /* Sunday = 1, Saturday = 7 */
+ mc146818_write8(RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday + 1));
mc146818_write8(RTC_DATE_OF_MONTH, bin2bcd(tmp->tm_mday));
mc146818_write8(RTC_HOURS, bin2bcd(tmp->tm_hour));
mc146818_write8(RTC_MINUTES, bin2bcd(tmp->tm_min));
@@ -195,7 +194,6 @@ static void mc146818_init(void)
/* Clear any pending interrupts */
mc146818_read8(RTC_CONFIG_C);
}
-#endif /* CONFIG_CMD_DATE */
#ifdef CONFIG_DM_RTC
diff --git a/drivers/rtc/mcfrtc.c b/drivers/rtc/mcfrtc.c
index 0ac8e4dbc5..e10638ec7d 100644
--- a/drivers/rtc/mcfrtc.c
+++ b/drivers/rtc/mcfrtc.c
@@ -6,8 +6,6 @@
#include <common.h>
-#if defined(CONFIG_CMD_DATE)
-
#include <command.h>
#include <rtc.h>
#include <asm/immap.h>
@@ -104,5 +102,3 @@ void rtc_reset(void)
rtc->cr |= RTC_CR_SWR;
}
-
-#endif /* CONFIG_MCFRTC && CONFIG_CMD_DATE */
diff --git a/drivers/rtc/mk48t59.c b/drivers/rtc/mk48t59.c
index d29d5ce600..8c90a70407 100644
--- a/drivers/rtc/mk48t59.c
+++ b/drivers/rtc/mk48t59.c
@@ -70,8 +70,6 @@ void nvram_write(short dest, const void *src, size_t count)
rtc_write(d++, *s++);
}
-#if defined(CONFIG_CMD_DATE)
-
/* ------------------------------------------------------------------------- */
int rtc_get (struct rtc_time *tmp)
@@ -175,5 +173,3 @@ void rtc_set_watchdog(short multi, short res)
wd_value = RTC_WDS | ((multi & 0x1F) << 2) | (res & 0x3);
rtc_write(RTC_WATCHDOG, wd_value);
}
-
-#endif
diff --git a/drivers/rtc/pcf8563.c b/drivers/rtc/pcf8563.c
index e2fa6b6aab..a839d6cc98 100644
--- a/drivers/rtc/pcf8563.c
+++ b/drivers/rtc/pcf8563.c
@@ -15,8 +15,6 @@
#include <rtc.h>
#include <i2c.h>
-#if defined(CONFIG_CMD_DATE)
-
static uchar rtc_read (uchar reg);
static void rtc_write (uchar reg, uchar val);
@@ -117,5 +115,3 @@ static void rtc_write (uchar reg, uchar val)
{
i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
}
-
-#endif
diff --git a/drivers/rtc/rs5c372.c b/drivers/rtc/rs5c372.c
index c815c915d5..97ec001aef 100644
--- a/drivers/rtc/rs5c372.c
+++ b/drivers/rtc/rs5c372.c
@@ -24,7 +24,6 @@
#include <rtc.h>
#include <i2c.h>
-#if defined(CONFIG_CMD_DATE)
/*
* Reads are always done starting with register 15, which requires some
* jumping-through-hoops to access the data correctly.
@@ -255,5 +254,3 @@ rtc_reset (void)
if (!setup_done)
rs5c372_enable();
}
-
-#endif
diff --git a/drivers/rtc/rx8025.c b/drivers/rtc/rx8025.c
index 1c2b92fe00..7bd9f8b42a 100644
--- a/drivers/rtc/rx8025.c
+++ b/drivers/rtc/rx8025.c
@@ -13,8 +13,6 @@
#include <rtc.h>
#include <i2c.h>
-#if defined(CONFIG_CMD_DATE)
-
/*---------------------------------------------------------------------*/
#undef DEBUG_RTC
@@ -190,5 +188,3 @@ static void rtc_write (uchar reg, uchar val)
printf("Error writing to RTC\n");
}
-
-#endif /* CONFIG_RTC_RX8025 && CONFIG_CMD_DATE */
diff --git a/drivers/rtc/s3c24x0_rtc.c b/drivers/rtc/s3c24x0_rtc.c
index 1253085f53..96ea3cf878 100644
--- a/drivers/rtc/s3c24x0_rtc.c
+++ b/drivers/rtc/s3c24x0_rtc.c
@@ -11,8 +11,6 @@
#include <common.h>
#include <command.h>
-#if (defined(CONFIG_CMD_DATE))
-
#include <asm/arch/s3c24x0_cpu.h>
#include <rtc.h>
@@ -149,5 +147,3 @@ void rtc_reset(void)
writeb((readb(&rtc->rtccon) & ~0x06) | 0x08, &rtc->rtccon);
writeb(readb(&rtc->rtccon) & ~(0x08 | 0x01), &rtc->rtccon);
}
-
-#endif
diff --git a/drivers/rtc/x1205.c b/drivers/rtc/x1205.c
index e9d8390f39..ed6aaa5237 100644
--- a/drivers/rtc/x1205.c
+++ b/drivers/rtc/x1205.c
@@ -22,8 +22,6 @@
#include <rtc.h>
#include <i2c.h>
-#if defined(CONFIG_CMD_DATE)
-
#define CCR_SEC 0
#define CCR_MIN 1
#define CCR_HOUR 2
@@ -160,5 +158,3 @@ void rtc_reset(void)
* Nothing to do
*/
}
-
-#endif
diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c
index d2e007284c..a60dabe588 100644
--- a/drivers/serial/sandbox.c
+++ b/drivers/serial/sandbox.c
@@ -10,6 +10,7 @@
*/
#include <common.h>
+#include <console.h>
#include <dm.h>
#include <fdtdec.h>
#include <lcd.h>
@@ -69,6 +70,9 @@ static int sandbox_serial_probe(struct udevice *dev)
os_tty_raw(0, state->term_raw == STATE_TERM_RAW_WITH_SIGS);
priv->start_of_line = 0;
+ if (state->term_raw != STATE_TERM_RAW)
+ disable_ctrlc(1);
+
return 0;
}
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index b85fca5628..dcd719ff0a 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -174,6 +174,11 @@ config STM32_QSPI
used to access the SPI NOR flash chips on platforms embedding
this ST IP core.
+config SUN4I_SPI
+ bool "Allwinner A10 SoCs SPI controller"
+ help
+ SPI driver for Allwinner sun4i, sun5i and sun7i SoCs
+
config TEGRA114_SPI
bool "nVidia Tegra114 SPI driver"
help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 95b03a29dc..728e30c538 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o
obj-$(CONFIG_SH_SPI) += sh_spi.o
obj-$(CONFIG_SH_QSPI) += sh_qspi.o
obj-$(CONFIG_STM32_QSPI) += stm32_qspi.o
+obj-$(CONFIG_SUN4I_SPI) += sun4i_spi.o
obj-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o
obj-$(CONFIG_TEGRA20_SFLASH) += tegra20_sflash.o
obj-$(CONFIG_TEGRA20_SLINK) += tegra20_slink.o
diff --git a/drivers/spi/kirkwood_spi.c b/drivers/spi/kirkwood_spi.c
index d6944af7e7..5dd1ad67cf 100644
--- a/drivers/spi/kirkwood_spi.c
+++ b/drivers/spi/kirkwood_spi.c
@@ -248,6 +248,7 @@ struct mvebu_spi_dev {
struct mvebu_spi_platdata {
struct kwspi_registers *spireg;
+ bool is_errata_50mhz_ac;
};
struct mvebu_spi_priv {
@@ -309,7 +310,6 @@ static int mvebu_spi_set_mode(struct udevice *bus, uint mode)
{
struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
struct kwspi_registers *reg = plat->spireg;
- const struct mvebu_spi_dev *drvdata;
u32 data = readl(&reg->cfg);
data &= ~(KWSPI_CPHA | KWSPI_CPOL | KWSPI_RXLSBF | KWSPI_TXLSBF);
@@ -323,8 +323,7 @@ static int mvebu_spi_set_mode(struct udevice *bus, uint mode)
writel(data, &reg->cfg);
- drvdata = (struct mvebu_spi_dev *)dev_get_driver_data(bus);
- if (drvdata->is_errata_50mhz_ac)
+ if (plat->is_errata_50mhz_ac)
mvebu_spi_50mhz_ac_timing_erratum(bus, mode);
return 0;
@@ -367,8 +366,11 @@ static int mvebu_spi_probe(struct udevice *bus)
static int mvebu_spi_ofdata_to_platdata(struct udevice *bus)
{
struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+ const struct mvebu_spi_dev *drvdata =
+ (struct mvebu_spi_dev *)dev_get_driver_data(bus);
plat->spireg = (struct kwspi_registers *)devfdt_get_addr(bus);
+ plat->is_errata_50mhz_ac = drvdata->is_errata_50mhz_ac;
return 0;
}
@@ -384,6 +386,10 @@ static const struct dm_spi_ops mvebu_spi_ops = {
*/
};
+static const struct mvebu_spi_dev armada_spi_dev_data = {
+ .is_errata_50mhz_ac = false,
+};
+
static const struct mvebu_spi_dev armada_xp_spi_dev_data = {
.is_errata_50mhz_ac = false,
};
@@ -398,6 +404,10 @@ static const struct mvebu_spi_dev armada_380_spi_dev_data = {
static const struct udevice_id mvebu_spi_ids[] = {
{
+ .compatible = "marvell,orion-spi",
+ .data = (ulong)&armada_spi_dev_data,
+ },
+ {
.compatible = "marvell,armada-375-spi",
.data = (ulong)&armada_375_spi_dev_data
},
diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
new file mode 100644
index 0000000000..b86b5a00ad
--- /dev/null
+++ b/drivers/spi/sun4i_spi.c
@@ -0,0 +1,456 @@
+/*
+ * (C) Copyright 2017 Whitebox Systems / Northend Systems B.V.
+ * S.J.R. van Schaik <stephan@whiteboxsystems.nl>
+ * M.B.W. Wajer <merlijn@whiteboxsystems.nl>
+ *
+ * (C) Copyright 2017 Olimex Ltd..
+ * Stefan Mavrodiev <stefan@olimex.com>
+ *
+ * Based on linux spi driver. Original copyright follows:
+ * linux/drivers/spi/spi-sun4i.c
+ *
+ * Copyright (C) 2012 - 2014 Allwinner Tech
+ * Pan Nan <pannan@allwinnertech.com>
+ *
+ * Copyright (C) 2014 Maxime Ripard
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <spi.h>
+#include <errno.h>
+#include <fdt_support.h>
+#include <wait_bit.h>
+
+#include <asm/bitops.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+
+#include <asm/arch/clock.h>
+
+#define SUN4I_FIFO_DEPTH 64
+
+#define SUN4I_RXDATA_REG 0x00
+
+#define SUN4I_TXDATA_REG 0x04
+
+#define SUN4I_CTL_REG 0x08
+#define SUN4I_CTL_ENABLE BIT(0)
+#define SUN4I_CTL_MASTER BIT(1)
+#define SUN4I_CTL_CPHA BIT(2)
+#define SUN4I_CTL_CPOL BIT(3)
+#define SUN4I_CTL_CS_ACTIVE_LOW BIT(4)
+#define SUN4I_CTL_LMTF BIT(6)
+#define SUN4I_CTL_TF_RST BIT(8)
+#define SUN4I_CTL_RF_RST BIT(9)
+#define SUN4I_CTL_XCH_MASK 0x0400
+#define SUN4I_CTL_XCH BIT(10)
+#define SUN4I_CTL_CS_MASK 0x3000
+#define SUN4I_CTL_CS(cs) (((cs) << 12) & SUN4I_CTL_CS_MASK)
+#define SUN4I_CTL_DHB BIT(15)
+#define SUN4I_CTL_CS_MANUAL BIT(16)
+#define SUN4I_CTL_CS_LEVEL BIT(17)
+#define SUN4I_CTL_TP BIT(18)
+
+#define SUN4I_INT_CTL_REG 0x0c
+#define SUN4I_INT_CTL_RF_F34 BIT(4)
+#define SUN4I_INT_CTL_TF_E34 BIT(12)
+#define SUN4I_INT_CTL_TC BIT(16)
+
+#define SUN4I_INT_STA_REG 0x10
+
+#define SUN4I_DMA_CTL_REG 0x14
+
+#define SUN4I_WAIT_REG 0x18
+
+#define SUN4I_CLK_CTL_REG 0x1c
+#define SUN4I_CLK_CTL_CDR2_MASK 0xff
+#define SUN4I_CLK_CTL_CDR2(div) ((div) & SUN4I_CLK_CTL_CDR2_MASK)
+#define SUN4I_CLK_CTL_CDR1_MASK 0xf
+#define SUN4I_CLK_CTL_CDR1(div) (((div) & SUN4I_CLK_CTL_CDR1_MASK) << 8)
+#define SUN4I_CLK_CTL_DRS BIT(12)
+
+#define SUN4I_MAX_XFER_SIZE 0xffffff
+
+#define SUN4I_BURST_CNT_REG 0x20
+#define SUN4I_BURST_CNT(cnt) ((cnt) & SUN4I_MAX_XFER_SIZE)
+
+#define SUN4I_XMIT_CNT_REG 0x24
+#define SUN4I_XMIT_CNT(cnt) ((cnt) & SUN4I_MAX_XFER_SIZE)
+
+#define SUN4I_FIFO_STA_REG 0x28
+#define SUN4I_FIFO_STA_RF_CNT_MASK 0x7f
+#define SUN4I_FIFO_STA_RF_CNT_BITS 0
+#define SUN4I_FIFO_STA_TF_CNT_MASK 0x7f
+#define SUN4I_FIFO_STA_TF_CNT_BITS 16
+
+#define SUN4I_SPI_MAX_RATE 24000000
+#define SUN4I_SPI_MIN_RATE 3000
+#define SUN4I_SPI_DEFAULT_RATE 1000000
+#define SUN4I_SPI_TIMEOUT_US 1000000
+
+/* sun4i spi register set */
+struct sun4i_spi_regs {
+ u32 rxdata;
+ u32 txdata;
+ u32 ctl;
+ u32 intctl;
+ u32 st;
+ u32 dmactl;
+ u32 wait;
+ u32 cctl;
+ u32 bc;
+ u32 tc;
+ u32 fifo_sta;
+};
+
+struct sun4i_spi_platdata {
+ u32 base_addr;
+ u32 max_hz;
+};
+
+struct sun4i_spi_priv {
+ struct sun4i_spi_regs *regs;
+ u32 freq;
+ u32 mode;
+
+ const u8 *tx_buf;
+ u8 *rx_buf;
+};
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
+{
+ u8 byte;
+
+ while (len--) {
+ byte = readb(&priv->regs->rxdata);
+ *priv->rx_buf++ = byte;
+ }
+}
+
+static inline void sun4i_spi_fill_fifo(struct sun4i_spi_priv *priv, int len)
+{
+ u8 byte;
+
+ while (len--) {
+ byte = priv->tx_buf ? *priv->tx_buf++ : 0;
+ writeb(byte, &priv->regs->txdata);
+ }
+}
+
+static void sun4i_spi_set_cs(struct udevice *bus, u8 cs, bool enable)
+{
+ struct sun4i_spi_priv *priv = dev_get_priv(bus);
+ u32 reg;
+
+ reg = readl(&priv->regs->ctl);
+
+ reg &= ~SUN4I_CTL_CS_MASK;
+ reg |= SUN4I_CTL_CS(cs);
+
+ if (enable)
+ reg &= ~SUN4I_CTL_CS_LEVEL;
+ else
+ reg |= SUN4I_CTL_CS_LEVEL;
+
+ writel(reg, &priv->regs->ctl);
+}
+
+static int sun4i_spi_parse_pins(struct udevice *dev)
+{
+ const void *fdt = gd->fdt_blob;
+ const char *pin_name;
+ const fdt32_t *list;
+ u32 phandle;
+ int drive, pull = 0, pin, i;
+ int offset;
+ int size;
+
+ list = fdt_getprop(fdt, dev_of_offset(dev), "pinctrl-0", &size);
+ if (!list) {
+ printf("WARNING: sun4i_spi: cannot find pinctrl-0 node\n");
+ return -EINVAL;
+ }
+
+ while (size) {
+ phandle = fdt32_to_cpu(*list++);
+ size -= sizeof(*list);
+
+ offset = fdt_node_offset_by_phandle(fdt, phandle);
+ if (offset < 0)
+ return offset;
+
+ drive = fdt_getprop_u32_default_node(fdt, offset, 0,
+ "drive-strength", 0);
+ if (drive) {
+ if (drive <= 10)
+ drive = 0;
+ else if (drive <= 20)
+ drive = 1;
+ else if (drive <= 30)
+ drive = 2;
+ else
+ drive = 3;
+ } else {
+ drive = fdt_getprop_u32_default_node(fdt, offset, 0,
+ "allwinner,drive",
+ 0);
+ drive = min(drive, 3);
+ }
+
+ if (fdt_get_property(fdt, offset, "bias-disable", NULL))
+ pull = 0;
+ else if (fdt_get_property(fdt, offset, "bias-pull-up", NULL))
+ pull = 1;
+ else if (fdt_get_property(fdt, offset, "bias-pull-down", NULL))
+ pull = 2;
+ else
+ pull = fdt_getprop_u32_default_node(fdt, offset, 0,
+ "allwinner,pull",
+ 0);
+ pull = min(pull, 2);
+
+ for (i = 0; ; i++) {
+ pin_name = fdt_stringlist_get(fdt, offset,
+ "pins", i, NULL);
+ if (!pin_name) {
+ pin_name = fdt_stringlist_get(fdt, offset,
+ "allwinner,pins",
+ i, NULL);
+ if (!pin_name)
+ break;
+ }
+
+ pin = name_to_gpio(pin_name);
+ if (pin < 0)
+ break;
+
+ sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
+ sunxi_gpio_set_drv(pin, drive);
+ sunxi_gpio_set_pull(pin, pull);
+ }
+ }
+ return 0;
+}
+
+static inline void sun4i_spi_enable_clock(void)
+{
+ struct sunxi_ccm_reg *const ccm =
+ (struct sunxi_ccm_reg *const)SUNXI_CCM_BASE;
+
+ setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_SPI0));
+ writel((1 << 31), &ccm->spi0_clk_cfg);
+}
+
+static int sun4i_spi_ofdata_to_platdata(struct udevice *bus)
+{
+ struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
+ int node = dev_of_offset(bus);
+
+ plat->base_addr = devfdt_get_addr(bus);
+ plat->max_hz = fdtdec_get_int(gd->fdt_blob, node,
+ "spi-max-frequency",
+ SUN4I_SPI_DEFAULT_RATE);
+
+ if (plat->max_hz > SUN4I_SPI_MAX_RATE)
+ plat->max_hz = SUN4I_SPI_MAX_RATE;
+
+ return 0;
+}
+
+static int sun4i_spi_probe(struct udevice *bus)
+{
+ struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
+ struct sun4i_spi_priv *priv = dev_get_priv(bus);
+
+ sun4i_spi_enable_clock();
+ sun4i_spi_parse_pins(bus);
+
+ priv->regs = (struct sun4i_spi_regs *)(uintptr_t)plat->base_addr;
+ priv->freq = plat->max_hz;
+
+ return 0;
+}
+
+static int sun4i_spi_claim_bus(struct udevice *dev)
+{
+ struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
+
+ writel(SUN4I_CTL_ENABLE | SUN4I_CTL_MASTER | SUN4I_CTL_TP |
+ SUN4I_CTL_CS_MANUAL | SUN4I_CTL_CS_ACTIVE_LOW,
+ &priv->regs->ctl);
+ return 0;
+}
+
+static int sun4i_spi_release_bus(struct udevice *dev)
+{
+ struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
+ u32 reg;
+
+ reg = readl(&priv->regs->ctl);
+ reg &= ~SUN4I_CTL_ENABLE;
+ writel(reg, &priv->regs->ctl);
+
+ return 0;
+}
+
+static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags)
+{
+ struct udevice *bus = dev->parent;
+ struct sun4i_spi_priv *priv = dev_get_priv(bus);
+ struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
+
+ u32 len = bitlen / 8;
+ u32 reg;
+ u8 nbytes;
+ int ret;
+
+ priv->tx_buf = dout;
+ priv->rx_buf = din;
+
+ if (bitlen % 8) {
+ debug("%s: non byte-aligned SPI transfer.\n", __func__);
+ return -ENAVAIL;
+ }
+
+ if (flags & SPI_XFER_BEGIN)
+ sun4i_spi_set_cs(bus, slave_plat->cs, true);
+
+ reg = readl(&priv->regs->ctl);
+
+ /* Reset FIFOs */
+ writel(reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST, &priv->regs->ctl);
+
+ while (len) {
+ /* Setup the transfer now... */
+ nbytes = min(len, (u32)(SUN4I_FIFO_DEPTH - 1));
+
+ /* Setup the counters */
+ writel(SUN4I_BURST_CNT(nbytes), &priv->regs->bc);
+ writel(SUN4I_XMIT_CNT(nbytes), &priv->regs->tc);
+
+ /* Fill the TX FIFO */
+ sun4i_spi_fill_fifo(priv, nbytes);
+
+ /* Start the transfer */
+ reg = readl(&priv->regs->ctl);
+ writel(reg | SUN4I_CTL_XCH, &priv->regs->ctl);
+
+ /* Wait transfer to complete */
+ ret = wait_for_bit_le32(&priv->regs->ctl, SUN4I_CTL_XCH_MASK,
+ false, SUN4I_SPI_TIMEOUT_US, false);
+ if (ret) {
+ printf("ERROR: sun4i_spi: Timeout transferring data\n");
+ sun4i_spi_set_cs(bus, slave_plat->cs, false);
+ return ret;
+ }
+
+ /* Drain the RX FIFO */
+ sun4i_spi_drain_fifo(priv, nbytes);
+
+ len -= nbytes;
+ }
+
+ if (flags & SPI_XFER_END)
+ sun4i_spi_set_cs(bus, slave_plat->cs, false);
+
+ return 0;
+}
+
+static int sun4i_spi_set_speed(struct udevice *dev, uint speed)
+{
+ struct sun4i_spi_platdata *plat = dev_get_platdata(dev);
+ struct sun4i_spi_priv *priv = dev_get_priv(dev);
+ unsigned int div;
+ u32 reg;
+
+ if (speed > plat->max_hz)
+ speed = plat->max_hz;
+
+ if (speed < SUN4I_SPI_MIN_RATE)
+ speed = SUN4I_SPI_MIN_RATE;
+ /*
+ * Setup clock divider.
+ *
+ * We have two choices there. Either we can use the clock
+ * divide rate 1, which is calculated thanks to this formula:
+ * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1))
+ * Or we can use CDR2, which is calculated with the formula:
+ * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
+ * Whether we use the former or the latter is set through the
+ * DRS bit.
+ *
+ * First try CDR2, and if we can't reach the expected
+ * frequency, fall back to CDR1.
+ */
+
+ div = SUN4I_SPI_MAX_RATE / (2 * speed);
+ reg = readl(&priv->regs->cctl);
+
+ if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) {
+ if (div > 0)
+ div--;
+
+ reg &= ~(SUN4I_CLK_CTL_CDR2_MASK | SUN4I_CLK_CTL_DRS);
+ reg |= SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS;
+ } else {
+ div = __ilog2(SUN4I_SPI_MAX_RATE) - __ilog2(speed);
+ reg &= ~((SUN4I_CLK_CTL_CDR1_MASK << 8) | SUN4I_CLK_CTL_DRS);
+ reg |= SUN4I_CLK_CTL_CDR1(div);
+ }
+
+ priv->freq = speed;
+ writel(reg, &priv->regs->cctl);
+
+ return 0;
+}
+
+static int sun4i_spi_set_mode(struct udevice *dev, uint mode)
+{
+ struct sun4i_spi_priv *priv = dev_get_priv(dev);
+ u32 reg;
+
+ reg = readl(&priv->regs->ctl);
+ reg &= ~(SUN4I_CTL_CPOL | SUN4I_CTL_CPHA);
+
+ if (mode & SPI_CPOL)
+ reg |= SUN4I_CTL_CPOL;
+
+ if (mode & SPI_CPHA)
+ reg |= SUN4I_CTL_CPHA;
+
+ priv->mode = mode;
+ writel(reg, &priv->regs->ctl);
+
+ return 0;
+}
+
+static const struct dm_spi_ops sun4i_spi_ops = {
+ .claim_bus = sun4i_spi_claim_bus,
+ .release_bus = sun4i_spi_release_bus,
+ .xfer = sun4i_spi_xfer,
+ .set_speed = sun4i_spi_set_speed,
+ .set_mode = sun4i_spi_set_mode,
+};
+
+static const struct udevice_id sun4i_spi_ids[] = {
+ { .compatible = "allwinner,sun4i-a10-spi" },
+ { }
+};
+
+U_BOOT_DRIVER(sun4i_spi) = {
+ .name = "sun4i_spi",
+ .id = UCLASS_SPI,
+ .of_match = sun4i_spi_ids,
+ .ops = &sun4i_spi_ops,
+ .ofdata_to_platdata = sun4i_spi_ofdata_to_platdata,
+ .platdata_auto_alloc_size = sizeof(struct sun4i_spi_platdata),
+ .priv_auto_alloc_size = sizeof(struct sun4i_spi_priv),
+ .probe = sun4i_spi_probe,
+};
diff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig
index 93264ddd34..94629dffd2 100644
--- a/drivers/tpm/Kconfig
+++ b/drivers/tpm/Kconfig
@@ -4,9 +4,6 @@
menu "TPM support"
-comment "Please select only one TPM revision"
- depends on TPM_V1 && TPM_V2
-
config TPM_V1
bool "TPMv1.x support"
depends on TPM
@@ -15,11 +12,12 @@ config TPM_V1
Major TPM versions are not compatible at all, choose either
one or the other. This option enables TPMv1.x drivers/commands.
-if TPM_V1 && !TPM_V2
+if TPM_V1
config TPM_TIS_SANDBOX
bool "Enable sandbox TPM driver"
depends on TPM_V1 && SANDBOX
+ default y
help
This driver emulates a TPMv1.x, providing access to base functions
such as reading and writing TPM private data. This is enough to
@@ -62,7 +60,6 @@ config TPM_TIS_I2C_BURST_LIMITATION_LEN
config TPM_TIS_LPC
bool "Enable support for Infineon SLB9635/45 TPMs on LPC"
depends on TPM_V1 && X86
- select TPM_DRIVER_SELECTED
help
This driver supports Infineon TPM devices connected on the LPC bus.
The usual tpm operations and the 'tpm' command can be used to talk
@@ -123,16 +120,17 @@ endif # TPM_V1
config TPM_V2
bool "TPMv2.x support"
depends on TPM
+ default y
help
Major TPM versions are not compatible at all, choose either
one or the other. This option enables TPMv2.x drivers/commands.
-if TPM_V2 && !TPM_V1
+if TPM_V2
config TPM2_TIS_SANDBOX
bool "Enable sandbox TPMv2.x driver"
depends on TPM_V2 && SANDBOX
- select TPM_DRIVER_SELECTED
+ default y
help
This driver emulates a TPMv2.x, providing access to base functions
such as basic configuration, PCR extension and PCR read. Extended
@@ -141,7 +139,6 @@ config TPM2_TIS_SANDBOX
config TPM2_TIS_SPI
bool "Enable support for TPMv2.x SPI chips"
depends on TPM_V2 && DM_SPI
- select TPM_DRIVER_SELECTED
help
This driver supports TPMv2.x devices connected on the SPI bus.
The usual TPM operations and the 'tpm' command can be used to talk
diff --git a/drivers/tpm/tpm-uclass.c b/drivers/tpm/tpm-uclass.c
index 412697eedc..c83f53ab86 100644
--- a/drivers/tpm/tpm-uclass.c
+++ b/drivers/tpm/tpm-uclass.c
@@ -7,11 +7,8 @@
#include <common.h>
#include <dm.h>
#include <linux/unaligned/be_byteshift.h>
-#if defined(CONFIG_TPM_V1)
#include <tpm-v1.h>
-#elif defined(CONFIG_TPM_V2)
#include <tpm-v2.h>
-#endif
#include "tpm_internal.h"
int tpm_open(struct udevice *dev)
diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
index 3240cc5dba..66f6c9ba82 100644
--- a/drivers/tpm/tpm2_tis_sandbox.c
+++ b/drivers/tpm/tpm2_tis_sandbox.c
@@ -232,7 +232,7 @@ static int sandbox_tpm2_fill_buf(u8 **recv, size_t *recv_len, u16 tag, u32 rc)
*recv += sizeof(rc);
/* Add trailing \0 */
- *recv = '\0';
+ *recv = NULL;
return 0;
}
@@ -590,6 +590,9 @@ static int sandbox_tpm2_probe(struct udevice *dev)
struct sandbox_tpm2 *tpm = dev_get_priv(dev);
struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
+ /* Use the TPM v2 stack */
+ priv->version = TPM_V2;
+
memset(tpm, 0, sizeof(*tpm));
priv->pcr_count = 32;
diff --git a/drivers/tpm/tpm2_tis_spi.c b/drivers/tpm/tpm2_tis_spi.c
index c5d17a679d..8878130bd7 100644
--- a/drivers/tpm/tpm2_tis_spi.c
+++ b/drivers/tpm/tpm2_tis_spi.c
@@ -510,6 +510,7 @@ static int tpm_tis_spi_cleanup(struct udevice *dev)
static int tpm_tis_spi_open(struct udevice *dev)
{
struct tpm_chip *chip = dev_get_priv(dev);
+ struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
if (chip->is_open)
return -EBUSY;
@@ -575,6 +576,9 @@ static int tpm_tis_spi_probe(struct udevice *dev)
struct tpm_chip *chip = dev_get_priv(dev);
int ret;
+ /* Use the TPM v2 stack */
+ priv->version = TPM_V2;
+
if (IS_ENABLED(CONFIG_DM_GPIO)) {
struct gpio_desc reset_gpio;
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 5ee9032dc9..a2d7e10938 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -410,7 +410,6 @@ config VIDEO_MVEBU
config I2C_EDID
bool "Enable EDID library"
- depends on DM_I2C
default n
help
This enables library for accessing EDID data from an LCD panel.
diff --git a/drivers/video/panel-uclass.c b/drivers/video/panel-uclass.c
index 2841bb3f3a..aec44a8bf7 100644
--- a/drivers/video/panel-uclass.c
+++ b/drivers/video/panel-uclass.c
@@ -18,6 +18,17 @@ int panel_enable_backlight(struct udevice *dev)
return ops->enable_backlight(dev);
}
+int panel_get_display_timing(struct udevice *dev,
+ struct display_timing *timings)
+{
+ struct panel_ops *ops = panel_get_ops(dev);
+
+ if (!ops->get_display_timing)
+ return -ENOSYS;
+
+ return ops->get_display_timing(dev, timings);
+}
+
UCLASS_DRIVER(panel) = {
.id = UCLASS_PANEL,
.name = "panel",
diff --git a/drivers/video/sunxi/sunxi_de2.c b/drivers/video/sunxi/sunxi_de2.c
index 4ed035d556..8333ddc44c 100644
--- a/drivers/video/sunxi/sunxi_de2.c
+++ b/drivers/video/sunxi/sunxi_de2.c
@@ -347,6 +347,9 @@ int sunxi_simplefb_setup(void *blob)
if (ret) {
debug("DE2 not present\n");
return 0;
+ } else if (!device_active(de2)) {
+ debug("DE2 present but not probed\n");
+ return 0;
}
ret = uclass_find_device_by_name(UCLASS_DISPLAY,