From 6d7a33301a05472bc788415c1d1575041e478931 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 10 Aug 2015 22:50:11 +0200 Subject: ddr: altera: Replace float multiplication with integer one This gem is really really rare, there was an actual float used in the Altera DDR init code, which pulled in floating point ops from the libgcc, just wow. Since we don't support floating point operations the same way Linux does not support them, replace this with an integer multiplication and division combo. This removes some 2kiB of size from the SPL as the floating point ops are no longer pulled in from libgcc. This was detected by enabling CONFIG_USE_PRIVATE_LIBGCC=y , which does not contain the floating point bits. Signed-off-by: Marek Vasut --- drivers/ddr/altera/sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ddr/altera/sequencer.c b/drivers/ddr/altera/sequencer.c index 2bd01092ee..f3621cf5de 100644 --- a/drivers/ddr/altera/sequencer.c +++ b/drivers/ddr/altera/sequencer.c @@ -3247,7 +3247,7 @@ static void mem_skip_calibrate(void) * (1.25 * iocfg->dll_chain_length - 2) */ scc_mgr_set_dqdqs_output_phase(i, - 1.25 * iocfg->dll_chain_length - 2); + ((125 * iocfg->dll_chain_length) / 100) - 2); } writel(0xff, &sdr_scc_mgr->dqs_ena); writel(0xff, &sdr_scc_mgr->dqs_io_ena); -- cgit v1.2.1 From 35e47b7132fa515e32189077ec7b80090562c709 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 10 Aug 2015 23:01:43 +0200 Subject: ddr: altera: Repair uninited variable Fix the following problem: drivers/ddr/altera/sequencer.c: In function 'sdram_calibration_full': drivers/ddr/altera/sequencer.c:1943:25: warning: 'found_failing_read' may be used uninitialized in this function [-Wmaybe-uninitialized] if (found_passing_read && found_failing_read) ^ drivers/ddr/altera/sequencer.c:1803:26: note: 'found_failing_read' was declared here u32 found_passing_read, found_failing_read, initial_failing_dtap; ^ Signed-off-by: Marek Vasut --- drivers/ddr/altera/sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ddr/altera/sequencer.c b/drivers/ddr/altera/sequencer.c index f3621cf5de..79c265faa2 100644 --- a/drivers/ddr/altera/sequencer.c +++ b/drivers/ddr/altera/sequencer.c @@ -1800,7 +1800,7 @@ static int rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase(const u32 grp) u32 d, p, i; u32 dtaps_per_ptap; u32 work_bgn, work_end; - u32 found_passing_read, found_failing_read, initial_failing_dtap; + u32 found_passing_read, found_failing_read = 0, initial_failing_dtap; int ret; debug("%s:%d %u\n", __func__, __LINE__, grp); -- cgit v1.2.1 From e30a70c2d3bcd3a60b7dc9d7f933bbad9912670a Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 23 Jun 2015 15:54:19 +0200 Subject: gpio: Add DW APB GPIO driver Add driver for the DesignWare APB GPIO IP block. This driver is DM capable and probes from DT. Signed-off-by: Marek Vasut Cc: Simon Glass --- drivers/gpio/Kconfig | 7 ++ drivers/gpio/Makefile | 1 + drivers/gpio/dwapb_gpio.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+) create mode 100644 drivers/gpio/dwapb_gpio.c (limited to 'drivers') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 5934597c4e..9a5d29debb 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -14,6 +14,13 @@ config DM_GPIO particular GPIOs that they provide. The uclass interface is defined in include/asm-generic/gpio.h. +config DWAPB_GPIO + bool "DWAPB GPIO driver" + depends on DM && DM_GPIO + default n + help + Support for the Designware APB GPIO driver. + config LPC32XX_GPIO bool "LPC32XX GPIO driver" depends on DM diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 26f2574c1c..ba185949bf 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -6,6 +6,7 @@ # ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_DWAPB_GPIO) += dwapb_gpio.o obj-$(CONFIG_AXP_GPIO) += axp_gpio.o endif obj-$(CONFIG_DM_GPIO) += gpio-uclass.o diff --git a/drivers/gpio/dwapb_gpio.c b/drivers/gpio/dwapb_gpio.c new file mode 100644 index 0000000000..72cec48800 --- /dev/null +++ b/drivers/gpio/dwapb_gpio.c @@ -0,0 +1,167 @@ +/* + * (C) Copyright 2015 Marek Vasut + * + * DesignWare APB GPIO driver + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define GPIO_SWPORTA_DR 0x00 +#define GPIO_SWPORTA_DDR 0x04 +#define GPIO_INTEN 0x30 +#define GPIO_INTMASK 0x34 +#define GPIO_INTTYPE_LEVEL 0x38 +#define GPIO_INT_POLARITY 0x3c +#define GPIO_INTSTATUS 0x40 +#define GPIO_PORTA_DEBOUNCE 0x48 +#define GPIO_PORTA_EOI 0x4c +#define GPIO_EXT_PORTA 0x50 + +struct gpio_dwapb_platdata { + const char *name; + int bank; + int pins; + fdt_addr_t base; +}; + +static int dwapb_gpio_direction_input(struct udevice *dev, unsigned pin) +{ + struct gpio_dwapb_platdata *plat = dev_get_platdata(dev); + + clrbits_le32(plat->base + GPIO_SWPORTA_DDR, 1 << pin); + return 0; +} + +static int dwapb_gpio_direction_output(struct udevice *dev, unsigned pin, + int val) +{ + struct gpio_dwapb_platdata *plat = dev_get_platdata(dev); + + setbits_le32(plat->base + GPIO_SWPORTA_DDR, 1 << pin); + + if (val) + setbits_le32(plat->base + GPIO_SWPORTA_DR, 1 << pin); + else + clrbits_le32(plat->base + GPIO_SWPORTA_DR, 1 << pin); + + return 0; +} + +static int dwapb_gpio_get_value(struct udevice *dev, unsigned pin) +{ + struct gpio_dwapb_platdata *plat = dev_get_platdata(dev); + return !!(readl(plat->base + GPIO_EXT_PORTA) & (1 << pin)); +} + + +static int dwapb_gpio_set_value(struct udevice *dev, unsigned pin, int val) +{ + struct gpio_dwapb_platdata *plat = dev_get_platdata(dev); + + if (val) + setbits_le32(plat->base + GPIO_SWPORTA_DR, 1 << pin); + else + clrbits_le32(plat->base + GPIO_SWPORTA_DR, 1 << pin); + + return 0; +} + +static const struct dm_gpio_ops gpio_dwapb_ops = { + .direction_input = dwapb_gpio_direction_input, + .direction_output = dwapb_gpio_direction_output, + .get_value = dwapb_gpio_get_value, + .set_value = dwapb_gpio_set_value, +}; + +static int gpio_dwapb_probe(struct udevice *dev) +{ + struct gpio_dev_priv *priv = dev_get_uclass_priv(dev); + struct gpio_dwapb_platdata *plat = dev->platdata; + + if (!plat) + return 0; + + priv->gpio_count = plat->pins; + priv->bank_name = plat->name; + + return 0; +} + +static int gpio_dwapb_bind(struct udevice *dev) +{ + struct gpio_dwapb_platdata *plat = dev_get_platdata(dev); + const void *blob = gd->fdt_blob; + struct udevice *subdev; + fdt_addr_t base; + int ret, node, bank = 0; + + /* If this is a child device, there is nothing to do here */ + if (plat) + return 0; + + base = fdtdec_get_addr(blob, dev->of_offset, "reg"); + if (base == FDT_ADDR_T_NONE) { + debug("Can't get the GPIO register base address\n"); + return -ENXIO; + } + + for (node = fdt_first_subnode(blob, dev->of_offset); + node > 0; + node = fdt_next_subnode(blob, node)) { + if (!fdtdec_get_bool(blob, node, "gpio-controller")) + continue; + + plat = NULL; + plat = calloc(1, sizeof(*plat)); + if (!plat) + return -ENOMEM; + + plat->base = base; + plat->bank = bank; + plat->pins = fdtdec_get_int(blob, node, "snps,nr-gpios", 0); + ret = fdt_get_string(blob, node, "bank-name", &plat->name); + if (ret) + goto err; + + ret = device_bind(dev, dev->driver, plat->name, + plat, -1, &subdev); + if (ret) + goto err; + + subdev->of_offset = node; + bank++; + } + + return 0; + +err: + free(plat); + return ret; +} + +static const struct udevice_id gpio_dwapb_ids[] = { + { .compatible = "snps,dw-apb-gpio" }, + { } +}; + +U_BOOT_DRIVER(gpio_dwapb) = { + .name = "gpio-dwapb", + .id = UCLASS_GPIO, + .of_match = gpio_dwapb_ids, + .ops = &gpio_dwapb_ops, + .bind = gpio_dwapb_bind, + .probe = gpio_dwapb_probe, +}; -- cgit v1.2.1