diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clk/clk_zynqmp.c | 7 | ||||
-rw-r--r-- | drivers/firmware/firmware-zynqmp.c | 19 | ||||
-rw-r--r-- | drivers/gpio/gpio_slg7xl45106.c | 2 | ||||
-rw-r--r-- | drivers/mmc/zynq_sdhci.c | 9 | ||||
-rw-r--r-- | drivers/net/phy/ethernet_id.c | 49 | ||||
-rw-r--r-- | drivers/net/phy/phy.c | 2 | ||||
-rw-r--r-- | drivers/net/zynq_gem.c | 86 | ||||
-rw-r--r-- | drivers/pwm/Kconfig | 7 | ||||
-rw-r--r-- | drivers/pwm/Makefile | 1 | ||||
-rw-r--r-- | drivers/pwm/pwm-cadence-ttc.c | 261 | ||||
-rw-r--r-- | drivers/serial/serial_zynq.c | 10 | ||||
-rw-r--r-- | drivers/timer/cadence-ttc.c | 12 |
12 files changed, 427 insertions, 38 deletions
diff --git a/drivers/clk/clk_zynqmp.c b/drivers/clk/clk_zynqmp.c index 9038fb8bef..45c679a627 100644 --- a/drivers/clk/clk_zynqmp.c +++ b/drivers/clk/clk_zynqmp.c @@ -238,6 +238,12 @@ static u32 zynqmp_clk_get_register(enum zynqmp_clk id) return CRF_APB_DBG_TRACE_CTRL; case dbg_tstmp: return CRF_APB_DBG_TSTMP_CTRL; + case dp_video_ref: + return CRF_APB_DP_VIDEO_REF_CTRL; + case dp_audio_ref: + return CRF_APB_DP_AUDIO_REF_CTRL; + case dp_stc_ref: + return CRF_APB_DP_STC_REF_CTRL; case gpu_ref ... gpu_pp1_ref: return CRF_APB_GPU_REF_CTRL; case ddr_ref: @@ -673,6 +679,7 @@ static ulong zynqmp_clk_get_rate(struct clk *clk) case dll_ref: return zynqmp_clk_get_dll_rate(priv); case gem_tsu_ref: + case dp_video_ref ... dp_stc_ref: case pl0 ... pl3: case gem0_ref ... gem3_ref: case gem0_tx ... gem3_tx: diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index 8916c55896..0f0d2b07c0 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -140,6 +140,19 @@ unsigned int zynqmp_firmware_version(void) return pm_api_version; }; +int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config, u32 value) +{ + int ret; + + ret = xilinx_pm_request(PM_IOCTL, node, IOCTL_SET_GEM_CONFIG, + config, value, NULL); + if (ret) + printf("%s: node %d: set_gem_config %d failed\n", + __func__, node, config); + + return ret; +} + int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value) { int ret; @@ -334,7 +347,11 @@ static int zynqmp_firmware_bind(struct udevice *dev) int ret; struct udevice *child; - if (IS_ENABLED(CONFIG_ZYNQMP_POWER_DOMAIN)) { + if ((IS_ENABLED(CONFIG_SPL_BUILD) && + IS_ENABLED(CONFIG_SPL_POWER_DOMAIN) && + IS_ENABLED(CONFIG_ZYNQMP_POWER_DOMAIN)) || + (!IS_ENABLED(CONFIG_SPL_BUILD) && + IS_ENABLED(CONFIG_ZYNQMP_POWER_DOMAIN))) { ret = device_bind_driver_to_node(dev, "zynqmp_power_domain", "zynqmp_power_domain", dev_ofnode(dev), &child); diff --git a/drivers/gpio/gpio_slg7xl45106.c b/drivers/gpio/gpio_slg7xl45106.c index 2cbf7488ad..4ad06c18b4 100644 --- a/drivers/gpio/gpio_slg7xl45106.c +++ b/drivers/gpio/gpio_slg7xl45106.c @@ -11,6 +11,7 @@ #include <asm/gpio.h> #include <dm.h> #include <i2c.h> +#include <dt-bindings/gpio/gpio.h> #include <asm/arch/hardware.h> #define SLG7XL45106_REG 0xdb @@ -26,6 +27,7 @@ static int slg7xl45106_i2c_gpo_xlate(struct udevice *dev, struct ofnode_phandle_args *args) { desc->offset = (unsigned int)args->args[0]; + desc->flags = (args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0); return 0; } diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index d96f5d543f..a59d96c6bd 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -765,6 +765,15 @@ static int sdhci_zynqmp_set_dynamic_config(struct arasan_sdhci_priv *priv, mhz = DIV64_U64_ROUND_UP(clock, 1000000); + if (mhz > 100 && mhz <= 200) + mhz = 200; + else if (mhz > 50 && mhz <= 100) + mhz = 100; + else if (mhz > 25 && mhz <= 50) + mhz = 50; + else + mhz = 25; + ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_BASECLK, mhz); if (ret) { dev_err(dev, "SD_CONFIG_BASECLK failed\n"); diff --git a/drivers/net/phy/ethernet_id.c b/drivers/net/phy/ethernet_id.c index 5617ac3ad6..1a78a751ed 100644 --- a/drivers/net/phy/ethernet_id.c +++ b/drivers/net/phy/ethernet_id.c @@ -12,7 +12,7 @@ #include <asm/gpio.h> struct phy_device *phy_connect_phy_id(struct mii_dev *bus, struct udevice *dev, - phy_interface_t interface) + int phyaddr, phy_interface_t interface) { struct phy_device *phydev; struct ofnode_phandle_args phandle_args; @@ -33,35 +33,42 @@ struct phy_device *phy_connect_phy_id(struct mii_dev *bus, struct udevice *dev, ret = ofnode_read_eth_phy_id(node, &vendor, &device); if (ret) { - dev_err(dev, "Failed to read eth PHY id, err: %d\n", ret); + debug("Failed to read eth PHY id, err: %d\n", ret); return NULL; } - ret = gpio_request_by_name_nodev(node, "reset-gpios", 0, &gpio, - GPIOD_ACTIVE_LOW); - if (!ret) { - assert = ofnode_read_u32_default(node, "reset-assert-us", 0); - deassert = ofnode_read_u32_default(node, - "reset-deassert-us", 0); - ret = dm_gpio_set_value(&gpio, 1); - if (ret) { - dev_err(dev, "Failed assert gpio, err: %d\n", ret); - return NULL; - } + if (!IS_ENABLED(CONFIG_DM_ETH_PHY)) { + ret = gpio_request_by_name_nodev(node, "reset-gpios", 0, &gpio, + GPIOD_ACTIVE_LOW); + if (!ret) { + assert = ofnode_read_u32_default(node, + "reset-assert-us", 0); + deassert = ofnode_read_u32_default(node, + "reset-deassert-us", + 0); + ret = dm_gpio_set_value(&gpio, 1); + if (ret) { + dev_err(dev, + "Failed assert gpio, err: %d\n", ret); + return NULL; + } - udelay(assert); + udelay(assert); - ret = dm_gpio_set_value(&gpio, 0); - if (ret) { - dev_err(dev, "Failed deassert gpio, err: %d\n", ret); - return NULL; - } + ret = dm_gpio_set_value(&gpio, 0); + if (ret) { + dev_err(dev, + "Failed deassert gpio, err: %d\n", + ret); + return NULL; + } - udelay(deassert); + udelay(deassert); + } } id = vendor << 16 | device; - phydev = phy_device_create(bus, 0, id, false, interface); + phydev = phy_device_create(bus, phyaddr, id, false, interface); if (phydev) phydev->node = node; diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 92fff5b72c..d4731860f7 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -1049,7 +1049,7 @@ struct phy_device *phy_connect(struct mii_dev *bus, int addr, #ifdef CONFIG_PHY_ETHERNET_ID if (!phydev) - phydev = phy_connect_phy_id(bus, dev, interface); + phydev = phy_connect_phy_id(bus, dev, addr, interface); #endif #ifdef CONFIG_PHY_XILINX_GMII2RGMII diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 3118d14726..4c83ccc1df 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -33,6 +33,8 @@ #include <linux/bitops.h> #include <linux/err.h> #include <linux/errno.h> +#include <eth_phy.h> +#include <zynqmp_firmware.h> /* Bit/mask specification */ #define ZYNQ_GEM_PHYMNTNC_OP_MASK 0x40020000 /* operation mask bits */ @@ -321,6 +323,9 @@ static int zynq_phy_init(struct udevice *dev) /* Enable only MDIO bus */ writel(ZYNQ_GEM_NWCTRL_MDEN_MASK, ®s_mdio->nwctrl); + if (IS_ENABLED(CONFIG_DM_ETH_PHY)) + priv->phyaddr = eth_phy_get_addr(dev); + priv->phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface); if (!priv->phydev) @@ -710,6 +715,40 @@ static int zynq_gem_reset_init(struct udevice *dev) return 0; } +static int gem_zynqmp_set_dynamic_config(struct udevice *dev) +{ + u32 pm_info[2]; + int ret; + + if (IS_ENABLED(CONFIG_ARCH_ZYNQMP)) { + if (!zynqmp_pm_is_function_supported(PM_IOCTL, + IOCTL_SET_GEM_CONFIG)) { + ret = ofnode_read_u32_array(dev_ofnode(dev), + "power-domains", + pm_info, + ARRAY_SIZE(pm_info)); + if (ret) { + dev_err(dev, + "Failed to read power-domains info\n"); + return ret; + } + + ret = zynqmp_pm_set_gem_config(pm_info[1], + GEM_CONFIG_FIXED, 0); + if (ret) + return ret; + + ret = zynqmp_pm_set_gem_config(pm_info[1], + GEM_CONFIG_SGMII_MODE, + 1); + if (ret) + return ret; + } + } + + return 0; +} + static int zynq_gem_probe(struct udevice *dev) { void *bd_space; @@ -771,25 +810,48 @@ static int zynq_gem_probe(struct udevice *dev) } } - priv->bus = mdio_alloc(); - priv->bus->read = zynq_gem_miiphy_read; - priv->bus->write = zynq_gem_miiphy_write; - priv->bus->priv = priv; + if (IS_ENABLED(CONFIG_DM_ETH_PHY)) + priv->bus = eth_phy_get_mdio_bus(dev); - ret = mdio_register_seq(priv->bus, dev_seq(dev)); - if (ret) - goto err2; + if (!priv->bus) { + priv->bus = mdio_alloc(); + priv->bus->read = zynq_gem_miiphy_read; + priv->bus->write = zynq_gem_miiphy_write; + priv->bus->priv = priv; + + ret = mdio_register_seq(priv->bus, dev_seq(dev)); + if (ret) + goto err2; + } + + if (IS_ENABLED(CONFIG_DM_ETH_PHY)) + eth_phy_set_mdio_bus(dev, priv->bus); ret = zynq_phy_init(dev); if (ret) goto err3; if (priv->interface == PHY_INTERFACE_MODE_SGMII && phy.dev) { + if (IS_ENABLED(CONFIG_DM_ETH_PHY)) { + if (device_is_compatible(dev, "cdns,zynqmp-gem")) { + ret = gem_zynqmp_set_dynamic_config(dev); + if (ret) { + dev_err + (dev, + "Failed to set gem dynamic config\n"); + return ret; + } + } + } ret = generic_phy_power_on(&phy); if (ret) return ret; } + printf("\nZYNQ GEM: %lx, mdio bus %lx, phyaddr %d, interface %s\n", + (ulong)priv->iobase, (ulong)priv->mdiobase, priv->phydev->addr, + phy_string_for_interface(priv->interface)); + return ret; err3: @@ -841,8 +903,10 @@ static int zynq_gem_of_to_plat(struct udevice *dev) ofnode parent; debug("phy-handle does exist %s\n", dev->name); - priv->phyaddr = ofnode_read_u32_default(phandle_args.node, - "reg", -1); + if (!(IS_ENABLED(CONFIG_DM_ETH_PHY))) + priv->phyaddr = ofnode_read_u32_default + (phandle_args.node, "reg", -1); + priv->phy_of_node = phandle_args.node; priv->max_speed = ofnode_read_u32_default(phandle_args.node, "max-speed", @@ -870,10 +934,6 @@ static int zynq_gem_of_to_plat(struct udevice *dev) priv->int_pcs = dev_read_bool(dev, "is-internal-pcspma"); - printf("\nZYNQ GEM: %lx, mdio bus %lx, phyaddr %d, interface %s\n", - (ulong)priv->iobase, (ulong)priv->mdiobase, priv->phyaddr, - phy_string_for_interface(priv->interface)); - priv->clk_en_info = dev_get_driver_data(dev); return 0; diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 6be612d58a..cb54e67fae 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -23,6 +23,13 @@ config PWM_AT91 help Support for PWM hardware on AT91 based SoC. +config PWM_CADENCE_TTC + bool "Enable support for the Cadence TTC PWM" + depends on DM_PWM && !CADENCE_TTC_TIMER + help + Cadence TTC can be configured as timer which is done via + CONFIG_CADENCE_TTC_TIMER or as PWM. This is covering only PWM now. + config PWM_CROS_EC bool "Enable support for the Chrome OS EC PWM" depends on DM_PWM diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 5d31812d52..bd119a666a 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_DM_PWM) += pwm-uclass.o obj-$(CONFIG_PWM_ASPEED) += pwm-aspeed.o obj-$(CONFIG_PWM_AT91) += pwm-at91.o +obj-$(CONFIG_PWM_CADENCE_TTC) += pwm-cadence-ttc.o obj-$(CONFIG_PWM_CROS_EC) += cros_ec_pwm.o obj-$(CONFIG_PWM_EXYNOS) += exynos_pwm.o obj-$(CONFIG_PWM_IMX) += pwm-imx.o pwm-imx-util.o diff --git a/drivers/pwm/pwm-cadence-ttc.c b/drivers/pwm/pwm-cadence-ttc.c new file mode 100644 index 0000000000..dc3b314b0c --- /dev/null +++ b/drivers/pwm/pwm-cadence-ttc.c @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) Copyright 2021 Xilinx, Inc. Michal Simek + */ + +#define LOG_CATEGORY UCLASS_PWM + +#include <clk.h> +#include <common.h> +#include <div64.h> +#include <dm.h> +#include <log.h> +#include <pwm.h> +#include <asm/io.h> +#include <log.h> +#include <div64.h> +#include <linux/bitfield.h> +#include <linux/math64.h> +#include <linux/log2.h> +#include <dm/device_compat.h> + +#define CLOCK_CONTROL 0 +#define COUNTER_CONTROL 0xc +#define INTERVAL_COUNTER 0x24 +#define MATCH_1_COUNTER 0x30 + +#define CLK_FALLING_EDGE BIT(6) +#define CLK_SRC_EXTERNAL BIT(5) +#define CLK_PRESCALE_MASK GENMASK(4, 1) +#define CLK_PRESCALE_ENABLE BIT(0) + +#define COUNTER_WAVE_POL BIT(6) +#define COUNTER_WAVE_DISABLE BIT(5) +#define COUNTER_RESET BIT(4) +#define COUNTER_MATCH_ENABLE BIT(3) +#define COUNTER_DECREMENT_ENABLE BIT(2) +#define COUNTER_INTERVAL_ENABLE BIT(1) +#define COUNTER_COUNTING_DISABLE BIT(0) + +#define NSEC_PER_SEC 1000000000L + +#define TTC_REG(reg, channel) ((reg) + (channel) * sizeof(u32)) +#define TTC_CLOCK_CONTROL(reg, channel) \ + TTC_REG((reg) + CLOCK_CONTROL, (channel)) +#define TTC_COUNTER_CONTROL(reg, channel) \ + TTC_REG((reg) + COUNTER_CONTROL, (channel)) +#define TTC_INTERVAL_COUNTER(reg, channel) \ + TTC_REG((reg) + INTERVAL_COUNTER, (channel)) +#define TTC_MATCH_1_COUNTER(reg, channel) \ + TTC_REG((reg) + MATCH_1_COUNTER, (channel)) + +struct cadence_ttc_pwm_plat { + u8 *regs; + u32 timer_width; +}; + +struct cadence_ttc_pwm_priv { + u8 *regs; + u32 timer_width; + u32 timer_mask; + unsigned long frequency; + bool invert[2]; +}; + +static int cadence_ttc_pwm_set_invert(struct udevice *dev, uint channel, + bool polarity) +{ + struct cadence_ttc_pwm_priv *priv = dev_get_priv(dev); + + if (channel > 2) { + dev_err(dev, "Unsupported channel number %d(max 2)\n", channel); + return -EINVAL; + } + + priv->invert[channel] = polarity; + + dev_dbg(dev, "polarity=%u. Please config PWM again\n", polarity); + + return 0; +} + +static int cadence_ttc_pwm_set_config(struct udevice *dev, uint channel, + uint period_ns, uint duty_ns) +{ + struct cadence_ttc_pwm_priv *priv = dev_get_priv(dev); + u32 counter_ctrl, clock_ctrl; + int period_clocks, duty_clocks, prescaler; + + dev_dbg(dev, "channel %d, duty %d/period %d ns\n", channel, + duty_ns, period_ns); + + if (channel > 2) { + dev_err(dev, "Unsupported channel number %d(max 2)\n", channel); + return -EINVAL; + } + + /* Make sure counter is stopped */ + counter_ctrl = readl(TTC_COUNTER_CONTROL(priv->regs, channel)); + setbits_le32(TTC_COUNTER_CONTROL(priv->regs, channel), + COUNTER_COUNTING_DISABLE | COUNTER_WAVE_DISABLE); + + /* Calculate period, prescaler and set clock control register */ + period_clocks = div64_u64(((int64_t)period_ns * priv->frequency), + NSEC_PER_SEC); + + prescaler = ilog2(period_clocks) + 1 - priv->timer_width; + if (prescaler < 0) + prescaler = 0; + + clock_ctrl = readl(TTC_CLOCK_CONTROL(priv->regs, channel)); + + if (!prescaler) { + clock_ctrl &= ~(CLK_PRESCALE_ENABLE | CLK_PRESCALE_MASK); + } else { + clock_ctrl &= ~CLK_PRESCALE_MASK; + clock_ctrl |= CLK_PRESCALE_ENABLE; + clock_ctrl |= FIELD_PREP(CLK_PRESCALE_MASK, prescaler - 1); + }; + + /* External source is not handled by this driver now */ + clock_ctrl &= ~CLK_SRC_EXTERNAL; + + writel(clock_ctrl, TTC_CLOCK_CONTROL(priv->regs, channel)); + + /* Calculate interval and set counter control value */ + duty_clocks = div64_u64(((int64_t)duty_ns * priv->frequency), + NSEC_PER_SEC); + + writel((period_clocks >> prescaler) & priv->timer_mask, + TTC_INTERVAL_COUNTER(priv->regs, channel)); + writel((duty_clocks >> prescaler) & priv->timer_mask, + TTC_MATCH_1_COUNTER(priv->regs, channel)); + + /* Restore/reset counter */ + counter_ctrl &= ~COUNTER_DECREMENT_ENABLE; + counter_ctrl |= COUNTER_INTERVAL_ENABLE | + COUNTER_RESET | + COUNTER_MATCH_ENABLE; + + if (priv->invert[channel]) + counter_ctrl |= COUNTER_WAVE_POL; + else + counter_ctrl &= ~COUNTER_WAVE_POL; + + writel(counter_ctrl, TTC_COUNTER_CONTROL(priv->regs, channel)); + + dev_dbg(dev, "%d/%d clocks, prescaler 2^%d\n", duty_clocks, + period_clocks, prescaler); + + return 0; +}; + +static int cadence_ttc_pwm_set_enable(struct udevice *dev, uint channel, + bool enable) +{ + struct cadence_ttc_pwm_priv *priv = dev_get_priv(dev); + + if (channel > 2) { + dev_err(dev, "Unsupported channel number %d(max 2)\n", channel); + return -EINVAL; + } + + dev_dbg(dev, "Enable: %d, channel %d\n", enable, channel); + + if (enable) { + clrbits_le32(TTC_COUNTER_CONTROL(priv->regs, channel), + COUNTER_COUNTING_DISABLE | + COUNTER_WAVE_DISABLE); + setbits_le32(TTC_COUNTER_CONTROL(priv->regs, channel), + COUNTER_RESET); + } else { + setbits_le32(TTC_COUNTER_CONTROL(priv->regs, channel), + COUNTER_COUNTING_DISABLE | + COUNTER_WAVE_DISABLE); + } + + return 0; +}; + +static int cadence_ttc_pwm_probe(struct udevice *dev) +{ + struct cadence_ttc_pwm_priv *priv = dev_get_priv(dev); + struct cadence_ttc_pwm_plat *plat = dev_get_plat(dev); + struct clk clk; + int ret; + + priv->regs = plat->regs; + priv->timer_width = plat->timer_width; + priv->timer_mask = GENMASK(priv->timer_width - 1, 0); + + ret = clk_get_by_index(dev, 0, &clk); + if (ret < 0) { + dev_err(dev, "failed to get clock\n"); + return ret; + } + + priv->frequency = clk_get_rate(&clk); + if (IS_ERR_VALUE(priv->frequency)) { + dev_err(dev, "failed to get rate\n"); + return priv->frequency; + } + dev_dbg(dev, "Clk frequency: %ld\n", priv->frequency); + + ret = clk_enable(&clk); + if (ret) { + dev_err(dev, "failed to enable clock\n"); + return ret; + } + + return 0; +} + +static int cadence_ttc_pwm_of_to_plat(struct udevice *dev) +{ + struct cadence_ttc_pwm_plat *plat = dev_get_plat(dev); + const char *cells; + + cells = dev_read_prop(dev, "#pwm-cells", NULL); + if (!cells) + return -EINVAL; + + plat->regs = dev_read_addr_ptr(dev); + + plat->timer_width = dev_read_u32_default(dev, "timer-width", 16); + + return 0; +} + +static int cadence_ttc_pwm_bind(struct udevice *dev) +{ + const char *cells; + + cells = dev_read_prop(dev, "#pwm-cells", NULL); + if (!cells) + return -ENODEV; + + return 0; +} + +static const struct pwm_ops cadence_ttc_pwm_ops = { + .set_invert = cadence_ttc_pwm_set_invert, + .set_config = cadence_ttc_pwm_set_config, + .set_enable = cadence_ttc_pwm_set_enable, +}; + +static const struct udevice_id cadence_ttc_pwm_ids[] = { + { .compatible = "cdns,ttc" }, + { } +}; + +U_BOOT_DRIVER(cadence_ttc_pwm) = { + .name = "cadence_ttc_pwm", + .id = UCLASS_PWM, + .of_match = cadence_ttc_pwm_ids, + .ops = &cadence_ttc_pwm_ops, + .bind = cadence_ttc_pwm_bind, + .of_to_plat = cadence_ttc_pwm_of_to_plat, + .probe = cadence_ttc_pwm_probe, + .priv_auto = sizeof(struct cadence_ttc_pwm_priv), + .plat_auto = sizeof(struct cadence_ttc_pwm_plat), +}; diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c index fd999368ab..6bb003dc15 100644 --- a/drivers/serial/serial_zynq.c +++ b/drivers/serial/serial_zynq.c @@ -21,6 +21,7 @@ #define ZYNQ_UART_SR_TXACTIVE BIT(11) /* TX active */ #define ZYNQ_UART_SR_TXFULL BIT(4) /* TX FIFO full */ +#define ZYNQ_UART_SR_TXEMPTY BIT(3) /* TX FIFO empty */ #define ZYNQ_UART_SR_RXEMPTY BIT(1) /* RX FIFO empty */ #define ZYNQ_UART_CR_TX_EN BIT(4) /* TX enabled */ @@ -107,8 +108,13 @@ static void _uart_zynq_serial_init(struct uart_zynq *regs) static int _uart_zynq_serial_putc(struct uart_zynq *regs, const char c) { - if (readl(®s->channel_sts) & ZYNQ_UART_SR_TXFULL) - return -EAGAIN; + if (CONFIG_IS_ENABLED(DEBUG_UART_ZYNQ)) { + if (!(readl(®s->channel_sts) & ZYNQ_UART_SR_TXEMPTY)) + return -EAGAIN; + } else { + if (readl(®s->channel_sts) & ZYNQ_UART_SR_TXFULL) + return -EAGAIN; + } writel(c, ®s->tx_rx_fifo); diff --git a/drivers/timer/cadence-ttc.c b/drivers/timer/cadence-ttc.c index 2f95d45ecd..2eff45060a 100644 --- a/drivers/timer/cadence-ttc.c +++ b/drivers/timer/cadence-ttc.c @@ -97,6 +97,17 @@ static int cadence_ttc_of_to_plat(struct udevice *dev) return 0; } +static int cadence_ttc_bind(struct udevice *dev) +{ + const char *cells; + + cells = dev_read_prop(dev, "#pwm-cells", NULL); + if (cells) + return -ENODEV; + + return 0; +} + static const struct timer_ops cadence_ttc_ops = { .get_count = cadence_ttc_get_count, }; @@ -114,4 +125,5 @@ U_BOOT_DRIVER(cadence_ttc) = { .priv_auto = sizeof(struct cadence_ttc_priv), .probe = cadence_ttc_probe, .ops = &cadence_ttc_ops, + .bind = cadence_ttc_bind, }; |