diff options
Diffstat (limited to 'drivers')
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(®s->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(®s->gpiodir); - - gpio_priv = gpio - priv->gpio_min; - if (direction == GPIO_DIRECTION_OUT) - val &= ~(1 << gpio_priv); - else - val |= 1 << gpio_priv; - - writel(val, ®s->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(®s->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, ®s->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(®s->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(®->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, ®->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, |