From 1eddf549319541ae41b2c8f1cb7a01fe3b737b53 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Thu, 16 Aug 2018 23:13:34 -0500 Subject: DM: GPIO: Fix da8xx GPIO indexing over GPIO 32 The GPIO banks are broken up into two 16-bit registers for each bank set. Unfortunately, the math that determines how to shift blindly shifted by the number of the gpio. This worked for gpio numbers under 32, but higher gpio's are broken. This fixes the gpio index, so the bank is passed and the shift amount within the register is passed now instead of the gpio number. Fixes: 8e51c0f25406("dm: gpio: Add DM compatibility to GPIO driver for Davinci") Signed-off-by: Adam Ford --- drivers/gpio/da8xx_gpio.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/da8xx_gpio.c b/drivers/gpio/da8xx_gpio.c index 1a1d37ae2a4..3e95f039f06 100644 --- a/drivers/gpio/da8xx_gpio.c +++ b/drivers/gpio/da8xx_gpio.c @@ -13,6 +13,7 @@ #include #include #include +#include #ifndef CONFIG_DM_GPIO static struct gpio_registry { @@ -429,20 +430,27 @@ int gpio_set_value(unsigned int gpio, int value) static struct davinci_gpio *davinci_get_gpio_bank(struct udevice *dev, unsigned int offset) { struct davinci_gpio_bank *bank = dev_get_priv(dev); + unsigned int addr; - /* The device tree is not broken into banks but the infrastructure is + /* + * The device tree is not broken into banks but the infrastructure is * expecting it this way, so we'll first include the 0x10 offset, then * calculate the bank manually based on the offset. + * Casting 'addr' as Unsigned long is needed to make the math work. */ - - return ((struct davinci_gpio *)bank->base) + 0x10 + (offset >> 5); + addr = ((unsigned long)(struct davinci_gpio *)bank->base) + + 0x10 + (0x28 * (offset >> 5)); + return (struct davinci_gpio *)addr; } static int davinci_gpio_direction_input(struct udevice *dev, unsigned int offset) { struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); - _gpio_direction_input(base, offset); + /* + * Fetch the address based on GPIO, but only pass the masked low 32-bits + */ + _gpio_direction_input(base, (offset & 0x1f)); return 0; } @@ -451,7 +459,7 @@ static int davinci_gpio_direction_output(struct udevice *dev, unsigned int offse { struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); - _gpio_direction_output(base, offset, value); + _gpio_direction_output(base, (offset & 0x1f), value); return 0; } @@ -459,7 +467,7 @@ static int davinci_gpio_get_value(struct udevice *dev, unsigned int offset) { struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); - return _gpio_get_value(base, offset); + return _gpio_get_value(base, (offset & 0x1f)); } static int davinci_gpio_set_value(struct udevice *dev, unsigned int offset, @@ -467,7 +475,7 @@ static int davinci_gpio_set_value(struct udevice *dev, unsigned int offset, { struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); - _gpio_set_value(base, offset, value); + _gpio_set_value(base, (offset & 0x1f), value); return 0; } -- cgit v1.2.3 From 9440b3d3d0bec6a7aa40307aff0699ec48e74a71 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Thu, 16 Aug 2018 23:21:57 -0500 Subject: dm: gpio: da8xx_gpio: Add support for GPIO_ACTIVE_LOW/HIGH With DM and device tree support, let's use the GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW from the device tree as they are intended. Signed-off-by: Adam Ford --- drivers/gpio/da8xx_gpio.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/da8xx_gpio.c b/drivers/gpio/da8xx_gpio.c index 3e95f039f06..b0d49cb46f0 100644 --- a/drivers/gpio/da8xx_gpio.c +++ b/drivers/gpio/da8xx_gpio.c @@ -493,12 +493,25 @@ static int davinci_gpio_get_function(struct udevice *dev, unsigned int offset) return GPIOF_OUTPUT; } +static int davinci_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, + struct ofnode_phandle_args *args) +{ + desc->offset = args->args[0]; + + if (args->args[1] & GPIO_ACTIVE_LOW) + desc->flags = GPIOD_ACTIVE_LOW; + else + desc->flags = 0; + return 0; +} + static const struct dm_gpio_ops gpio_davinci_ops = { .direction_input = davinci_gpio_direction_input, .direction_output = davinci_gpio_direction_output, .get_value = davinci_gpio_get_value, .set_value = davinci_gpio_set_value, .get_function = davinci_gpio_get_function, + .xlate = davinci_gpio_xlate, }; static int davinci_gpio_probe(struct udevice *dev) -- cgit v1.2.3 From 535f46dad920094df12b2d19f071db2e6a8ae0ab Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Fri, 17 Aug 2018 14:37:58 -0500 Subject: GPIO: omap_gpio: Fix gpio name names with device tree The GPIO bank numbers do not appear in the device tree, so this patch makes the gpio name based on the address (ie gpio@49054000_31 vs gpio4_31) adam Signed-off-by: Adam Ford Tested-by: Derald D. Woods --- drivers/gpio/omap_gpio.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c index 651f6994e41..0f1ddeff929 100644 --- a/drivers/gpio/omap_gpio.c +++ b/drivers/gpio/omap_gpio.c @@ -288,11 +288,9 @@ static int omap_gpio_probe(struct udevice *dev) struct gpio_bank *bank = dev_get_priv(dev); struct omap_gpio_platdata *plat = dev_get_platdata(dev); struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); - int banknum; char name[18], *str; - banknum = plat->bank_index; - sprintf(name, "GPIO%d_", banknum + 1); + sprintf(name, "gpio@%4x_", (unsigned int)plat->base); str = strdup(name); if (!str) return -ENOMEM; -- cgit v1.2.3 From e5f7a261db470e97f2018cdff41407af6353d969 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Sun, 19 Aug 2018 20:54:00 -0500 Subject: regulator: pbias: Add additional compatible flags The driver was developed with references for more than just dra7, but never included. At least for omap3, this appears to be functional. Signed-off-by: Adam Ford --- drivers/power/regulator/pbias_regulator.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/power/regulator/pbias_regulator.c b/drivers/power/regulator/pbias_regulator.c index 8f06e27b898..366f97b38b7 100644 --- a/drivers/power/regulator/pbias_regulator.c +++ b/drivers/power/regulator/pbias_regulator.c @@ -108,6 +108,10 @@ static struct dm_pmic_ops pbias_ops = { static const struct udevice_id pbias_ids[] = { { .compatible = "ti,pbias-dra7" }, + { .compatible = "ti,pbias-omap2" }, + { .compatible = "ti,pbias-omap3" }, + { .compatible = "ti,pbias-omap4" }, + { .compatible = "ti,pbias-omap5" }, { } }; -- cgit v1.2.3 From afa8cdd60755784a74ec4683106a2abe718f9623 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Mon, 20 Aug 2018 20:24:34 -0500 Subject: DM: I2C: Reduce overhead when used with OF_PLATDATA Platforms with limited resources in SPL may enably OF_PLATDATA, this limits some of the library functions and cannot extract data from the device tree. This patch adds additional wrappers around these functions to only allow them when OF_CONTROL is enabled and OF_PLATDATA is not. Signed-off-by: Adam Ford --- drivers/i2c/i2c-uclass.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c index 5e58dd0916c..c5a3c4e2016 100644 --- a/drivers/i2c/i2c-uclass.c +++ b/drivers/i2c/i2c-uclass.c @@ -562,7 +562,7 @@ int i2c_deblock(struct udevice *bus) return ops->deblock(bus); } -#if CONFIG_IS_ENABLED(OF_CONTROL) +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) int i2c_chip_ofdata_to_platdata(struct udevice *dev, struct dm_i2c_chip *chip) { int addr; @@ -584,7 +584,7 @@ int i2c_chip_ofdata_to_platdata(struct udevice *dev, struct dm_i2c_chip *chip) static int i2c_post_probe(struct udevice *dev) { -#if CONFIG_IS_ENABLED(OF_CONTROL) +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) struct dm_i2c_bus *i2c = dev_get_uclass_priv(dev); i2c->speed_hz = dev_read_u32_default(dev, "clock-frequency", 100000); @@ -597,7 +597,7 @@ static int i2c_post_probe(struct udevice *dev) static int i2c_child_post_bind(struct udevice *dev) { -#if CONFIG_IS_ENABLED(OF_CONTROL) +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) struct dm_i2c_chip *plat = dev_get_parent_platdata(dev); if (!dev_of_valid(dev)) @@ -612,7 +612,7 @@ UCLASS_DRIVER(i2c) = { .id = UCLASS_I2C, .name = "i2c", .flags = DM_UC_FLAG_SEQ_ALIAS, -#if CONFIG_IS_ENABLED(OF_CONTROL) +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) .post_bind = dm_scan_fdt_dev, #endif .post_probe = i2c_post_probe, -- cgit v1.2.3 From 410c505cc145d570662ef0f841a942e650f8b1df Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Mon, 20 Aug 2018 20:24:35 -0500 Subject: DM: OMAP24XX_I2C: Reduce overhead when used with OF_PLATDATA Platforms with limited resources in SPL may enably OF_PLATDATA, this limits some of the library functions and cannot extract data from the device tree. This patch adds additional wrappers around these functions to only allow them when OF_CONTROL is enabled and OF_PLATDATA is not. Signed-off-by: Adam Ford --- drivers/i2c/omap24xx_i2c.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c index 0759585c9e1..54bf35e552e 100644 --- a/drivers/i2c/omap24xx_i2c.c +++ b/drivers/i2c/omap24xx_i2c.c @@ -890,6 +890,7 @@ static int omap_i2c_probe(struct udevice *bus) return 0; } +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) static int omap_i2c_ofdata_to_platdata(struct udevice *bus) { struct omap_i2c *priv = dev_get_priv(bus); @@ -901,23 +902,26 @@ static int omap_i2c_ofdata_to_platdata(struct udevice *bus) return 0; } -static const struct dm_i2c_ops omap_i2c_ops = { - .xfer = omap_i2c_xfer, - .probe_chip = omap_i2c_probe_chip, - .set_bus_speed = omap_i2c_set_bus_speed, -}; - static const struct udevice_id omap_i2c_ids[] = { { .compatible = "ti,omap3-i2c" }, { .compatible = "ti,omap4-i2c" }, { } }; +#endif + +static const struct dm_i2c_ops omap_i2c_ops = { + .xfer = omap_i2c_xfer, + .probe_chip = omap_i2c_probe_chip, + .set_bus_speed = omap_i2c_set_bus_speed, +}; U_BOOT_DRIVER(i2c_omap) = { .name = "i2c_omap", .id = UCLASS_I2C, +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) .of_match = omap_i2c_ids, .ofdata_to_platdata = omap_i2c_ofdata_to_platdata, +#endif .probe = omap_i2c_probe, .priv_auto_alloc_size = sizeof(struct omap_i2c), .ops = &omap_i2c_ops, -- cgit v1.2.3 From 99571b41c6c21ccd3737971a51727e6f4d89126d Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Mon, 20 Aug 2018 20:27:48 -0500 Subject: DM: omap_gpio: Reduce overhead when used with OF_PLATDATA Platforms with limited resources in SPL may enable OF_PLATDATA, this limits some of the library functions and cannot extract data from the device tree. This patch adds additional wrappers around these functions to only allow them when OF_CONTROL is enabled and OF_PLATDATA is not. Signed-off-by: Adam Ford Reviewed-by: Simon Glass --- drivers/gpio/omap_gpio.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c index 0f1ddeff929..555eba26622 100644 --- a/drivers/gpio/omap_gpio.c +++ b/drivers/gpio/omap_gpio.c @@ -335,6 +335,7 @@ static int omap_gpio_bind(struct udevice *dev) } #endif +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) static const struct udevice_id omap_gpio_ids[] = { { .compatible = "ti,omap3-gpio" }, { .compatible = "ti,omap4-gpio" }, @@ -342,7 +343,6 @@ static const struct udevice_id omap_gpio_ids[] = { { } }; -#if CONFIG_IS_ENABLED(OF_CONTROL) static int omap_gpio_ofdata_to_platdata(struct udevice *dev) { struct omap_gpio_platdata *plat = dev_get_platdata(dev); @@ -361,14 +361,15 @@ U_BOOT_DRIVER(gpio_omap) = { .name = "gpio_omap", .id = UCLASS_GPIO, #if CONFIG_IS_ENABLED(OF_CONTROL) +#if !CONFIG_IS_ENABLED(OF_PLATDATA) + .of_match = omap_gpio_ids, .ofdata_to_platdata = of_match_ptr(omap_gpio_ofdata_to_platdata), - .bind = dm_scan_fdt_dev, .platdata_auto_alloc_size = sizeof(struct omap_gpio_platdata), +#endif #else .bind = omap_gpio_bind, #endif .ops = &gpio_omap_ops, - .of_match = omap_gpio_ids, .probe = omap_gpio_probe, .priv_auto_alloc_size = sizeof(struct gpio_bank), .flags = DM_FLAG_PRE_RELOC, -- cgit v1.2.3 From 307a214329908e4abc0f978b9a10b1467e3872c6 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Tue, 21 Aug 2018 07:16:56 -0500 Subject: mmc: omap_hsmmc: Make DM_GPIO calls dependent on DM_GPIO The getcd and getwp functions when DM_MMC is enabled are assumming the DM_GPIO is enabled. In cases (like SPL) where DM_GPIO may not be enabled, wrap these calls in an #ifdef Signed-off-by: Adam Ford --- drivers/mmc/omap_hsmmc.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index caaa9146049..4d171f457ec 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -1365,9 +1365,10 @@ static int omap_hsmmc_set_ios(struct udevice *dev) static int omap_hsmmc_getcd(struct udevice *dev) { struct omap_hsmmc_data *priv = dev_get_priv(dev); - int value; - + int value = -1; +#if CONFIG_IS_ENABLED(DM_GPIO) value = dm_gpio_get_value(&priv->cd_gpio); +#endif /* if no CD return as 1 */ if (value < 0) return 1; @@ -1379,10 +1380,11 @@ static int omap_hsmmc_getcd(struct udevice *dev) static int omap_hsmmc_getwp(struct udevice *dev) { + int value = 0; +#if CONFIG_IS_ENABLED(DM_GPIO) struct omap_hsmmc_data *priv = dev_get_priv(dev); - int value; - value = dm_gpio_get_value(&priv->wp_gpio); +#endif /* if no WP return as 0 */ if (value < 0) return 0; @@ -1901,9 +1903,11 @@ static int omap_hsmmc_probe(struct udevice *dev) device_get_supply_regulator(dev, "pbias-supply", &priv->pbias_supply); #endif -#if defined(OMAP_HSMMC_USE_GPIO) && CONFIG_IS_ENABLED(OF_CONTROL) +#if defined(OMAP_HSMMC_USE_GPIO) +#if CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(DM_GPIO) gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN); gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio, GPIOD_IS_IN); +#endif #endif mmc->dev = dev; -- cgit v1.2.3 From df6565c36c607104590e954d093b92a58a9d5d28 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Thu, 9 Aug 2018 06:15:12 -0500 Subject: MMC: Enable DM_MMC for Davinci With CONFIG_BLK becoming a requirement, the Davinci MMC driver needs to be updated with DM_MMC support. Since SPL is tiny and many boards do not support DM in SPL, this retains the backwards compatibility for those boards who need to initialize MMC manually in SPL. Signed-off-by: Peter Howard Signed-off-by: Adam Ford --- drivers/mmc/davinci_mmc.c | 158 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 147 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/davinci_mmc.c b/drivers/mmc/davinci_mmc.c index d7cb88a40ab..db950ea5ec5 100644 --- a/drivers/mmc/davinci_mmc.c +++ b/drivers/mmc/davinci_mmc.c @@ -7,9 +7,10 @@ #include #include -#include +#include #include #include +#include #include #include #include @@ -23,10 +24,38 @@ #define set_bit(addr, val) set_val((addr), (get_val(addr) | (val))) #define clear_bit(addr, val) set_val((addr), (get_val(addr) & ~(val))) +#ifdef CONFIG_DM_MMC +struct davinci_of_data { + const char *name; + u8 version; +}; + +/* Davinci MMC board definitions */ +struct davinci_mmc_priv { + struct davinci_mmc_regs *reg_base; /* Register base address */ + uint input_clk; /* Input clock to MMC controller */ + uint version; /* MMC Controller version */ +}; + +struct davinci_mmc_plat +{ + struct mmc_config cfg; + struct mmc mmc; +}; +#endif + /* Set davinci clock prescalar value based on the required clock in HZ */ +#if !CONFIG_IS_ENABLED(DM_MMC) static void dmmc_set_clock(struct mmc *mmc, uint clock) { struct davinci_mmc *host = mmc->priv; +#else + +static void davinci_mmc_set_clock(struct udevice *dev, uint clock) +{ + struct davinci_mmc_priv *host = dev_get_priv(dev); + struct mmc *mmc = mmc_get_mmc_dev(dev); +#endif struct davinci_mmc_regs *regs = host->reg_base; uint clkrt, sysclk2, act_clock; @@ -120,13 +149,19 @@ static int dmmc_check_status(volatile struct davinci_mmc_regs *regs, } /* - * Sends a command out on the bus. Takes the mmc pointer, + * Sends a command out on the bus. Takes the device pointer, * a command pointer, and an optional data pointer. */ -static int -dmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) +#if !CONFIG_IS_ENABLED(DM_MMC) +static int dmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { struct davinci_mmc *host = mmc->priv; +#else +static int +davinci_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, struct mmc_data *data) +{ + struct davinci_mmc_priv *host = dev_get_priv(dev); +#endif volatile struct davinci_mmc_regs *regs = host->reg_base; uint mmcstatus, status_rdy, status_err; uint i, cmddata, bytes_left = 0; @@ -312,9 +347,15 @@ dmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) } /* Initialize Davinci MMC controller */ +#if !CONFIG_IS_ENABLED(DM_MMC) static int dmmc_init(struct mmc *mmc) { struct davinci_mmc *host = mmc->priv; +#else +static int davinci_dm_mmc_init(struct udevice *dev) +{ + struct davinci_mmc_priv *host = dev_get_priv(dev); +#endif struct davinci_mmc_regs *regs = host->reg_base; /* Clear status registers explicitly - soft reset doesn't clear it @@ -347,11 +388,19 @@ static int dmmc_init(struct mmc *mmc) } /* Set buswidth or clock as indicated by the MMC framework */ +#if !CONFIG_IS_ENABLED(DM_MMC) static int dmmc_set_ios(struct mmc *mmc) { struct davinci_mmc *host = mmc->priv; struct davinci_mmc_regs *regs = host->reg_base; +#else +static int davinci_mmc_set_ios(struct udevice *dev) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); + struct davinci_mmc_priv *host = dev_get_priv(dev); + struct davinci_mmc_regs *regs = host->reg_base; +#endif /* Set the bus width */ if (mmc->bus_width == 4) set_bit(®s->mmcctl, MMCCTL_WIDTH_4_BIT); @@ -359,21 +408,33 @@ static int dmmc_set_ios(struct mmc *mmc) clear_bit(®s->mmcctl, MMCCTL_WIDTH_4_BIT); /* Set clock speed */ - if (mmc->clock) + if (mmc->clock) { +#if !CONFIG_IS_ENABLED(DM_MMC) dmmc_set_clock(mmc, mmc->clock); - +#else + davinci_mmc_set_clock(dev, mmc->clock); +#endif + } return 0; } +#if !CONFIG_IS_ENABLED(DM_MMC) static const struct mmc_ops dmmc_ops = { - .send_cmd = dmmc_send_cmd, - .set_ios = dmmc_set_ios, - .init = dmmc_init, + .send_cmd = dmmc_send_cmd, + .set_ios = dmmc_set_ios, + .init = dmmc_init, }; +#else +static const struct dm_mmc_ops davinci_mmc_ops = { + .send_cmd = davinci_mmc_send_cmd, + .set_ios = davinci_mmc_set_ios, +}; +#endif +#if !CONFIG_IS_ENABLED(DM_MMC) /* Called from board_mmc_init during startup. Can be called multiple times - * depending on the number of slots available on board and controller - */ +* depending on the number of slots available on board and controller +*/ int davinci_mmc_init(bd_t *bis, struct davinci_mmc *host) { host->cfg.name = "davinci"; @@ -389,3 +450,78 @@ int davinci_mmc_init(bd_t *bis, struct davinci_mmc *host) return 0; } +#else + + +static int davinci_mmc_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct davinci_mmc_plat *plat = dev_get_platdata(dev); + struct davinci_mmc_priv *priv = dev_get_priv(dev); + struct mmc_config *cfg = &plat->cfg; + struct davinci_of_data *data = + (struct davinci_of_data *)dev_get_driver_data(dev); + cfg->f_min = 200000; + cfg->f_max = 25000000; + cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34, + cfg->host_caps = MMC_MODE_4BIT, /* DA850 supports only 4-bit SD/MMC */ + cfg->b_max = DAVINCI_MAX_BLOCKS; + + if (data) { + cfg->name = data->name; + priv->version = data->version; + } + + priv->reg_base = (struct davinci_mmc_regs *)dev_read_addr(dev); + priv->input_clk = clk_get(DAVINCI_MMCSD_CLKID); + + upriv->mmc = &plat->mmc; + + return davinci_dm_mmc_init(dev); +} + +static int davinci_mmc_bind(struct udevice *dev) +{ + struct davinci_mmc_plat *plat = dev_get_platdata(dev); + + return mmc_bind(dev, &plat->mmc, &plat->cfg); +} + + +const struct davinci_of_data davinci_mmc_host_info[] = { + { + .name = "dm6441-mmc", + .version = MMC_CTLR_VERSION_1, + }, + { + .name = "da830-mmc", + .version = MMC_CTLR_VERSION_2, + }, + {}, +}; + +static const struct udevice_id davinci_mmc_ids[] = { + { + .compatible = "ti,dm6441-mmc", + .data = (ulong) &davinci_mmc_host_info[MMC_CTLR_VERSION_1] + }, + { + .compatible = "ti,da830-mmc", + .data = (ulong) &davinci_mmc_host_info[MMC_CTLR_VERSION_2] + }, + {}, +}; + +U_BOOT_DRIVER(davinci_mmc_drv) = { + .name = "davinci_mmc", + .id = UCLASS_MMC, + .of_match = davinci_mmc_ids, +#if CONFIG_BLK + .bind = davinci_mmc_bind, +#endif + .probe = davinci_mmc_probe, + .ops = &davinci_mmc_ops, + .platdata_auto_alloc_size = sizeof(struct davinci_mmc_plat), + .priv_auto_alloc_size = sizeof(struct davinci_mmc_priv), +}; +#endif -- cgit v1.2.3 From 04355de71def5e91898e2dc2a36d2eda47ba12b4 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Mon, 3 Sep 2018 03:47:52 -0500 Subject: MMC: davinici_mmc: Enable CD and WP with DM and OF_CONTROL When used with a device tree, this will extract the card detect and write protect pins from the device tree and configure them accordingly. This assumes the GPIO_ACTIVE_LOW/HIGH is supported by da8xx_gpio. Signed-off-by: Adam Ford --- drivers/mmc/davinci_mmc.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/davinci_mmc.c b/drivers/mmc/davinci_mmc.c index db950ea5ec5..0d63279db00 100644 --- a/drivers/mmc/davinci_mmc.c +++ b/drivers/mmc/davinci_mmc.c @@ -15,6 +15,7 @@ #include #include #include +#include #define DAVINCI_MAX_BLOCKS (32) #define WATCHDOG_COUNT (100000) @@ -35,6 +36,8 @@ struct davinci_mmc_priv { struct davinci_mmc_regs *reg_base; /* Register base address */ uint input_clk; /* Input clock to MMC controller */ uint version; /* MMC Controller version */ + struct gpio_desc cd_gpio; /* Card Detect GPIO */ + struct gpio_desc wp_gpio; /* Write Protect GPIO */ }; struct davinci_mmc_plat @@ -425,9 +428,41 @@ static const struct mmc_ops dmmc_ops = { .init = dmmc_init, }; #else + +static int davinci_mmc_getcd(struct udevice *dev) +{ + int value = -1; +#if CONFIG_IS_ENABLED(DM_GPIO) + struct davinci_mmc_priv *priv = dev_get_priv(dev); + value = dm_gpio_get_value(&priv->cd_gpio); +#endif + /* if no CD return as 1 */ + if (value < 0) + return 1; + + return value; +} + +static int davinci_mmc_getwp(struct udevice *dev) +{ + int value = -1; +#if CONFIG_IS_ENABLED(DM_GPIO) + struct davinci_mmc_priv *priv = dev_get_priv(dev); + + value = dm_gpio_get_value(&priv->wp_gpio); +#endif + /* if no WP return as 0 */ + if (value < 0) + return 0; + + return value; +} + static const struct dm_mmc_ops davinci_mmc_ops = { .send_cmd = davinci_mmc_send_cmd, .set_ios = davinci_mmc_set_ios, + .get_cd = davinci_mmc_getcd, + .get_wp = davinci_mmc_getwp, }; #endif @@ -475,6 +510,12 @@ static int davinci_mmc_probe(struct udevice *dev) priv->reg_base = (struct davinci_mmc_regs *)dev_read_addr(dev); priv->input_clk = clk_get(DAVINCI_MMCSD_CLKID); +#if CONFIG_IS_ENABLED(DM_GPIO) + /* These GPIOs are optional */ + gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN); + gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio, GPIOD_IS_IN); +#endif + upriv->mmc = &plat->mmc; return davinci_dm_mmc_init(dev); -- cgit v1.2.3 From ca1d6ca3653c5aa7679a55fd84a20e175d3b8e64 Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Thu, 16 Aug 2018 02:08:11 +0300 Subject: i2c: Drop CONFIG_SYS_I2C_MXS Last user of this driver went away in May 2017, in commit eb5ba3aefdf0f6 ("i2c: Drop use of CONFIG_I2C_HARD") Signed-off-by: Tuomas Tynkkynen --- drivers/i2c/Makefile | 1 - drivers/i2c/mxs_i2c.c | 319 -------------------------------------------------- 2 files changed, 320 deletions(-) delete mode 100644 drivers/i2c/mxs_i2c.c (limited to 'drivers') diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index da368cc02a0..f2cbe78c53b 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -24,7 +24,6 @@ obj-$(CONFIG_SYS_I2C_LPC32XX) += lpc32xx_i2c.o obj-$(CONFIG_SYS_I2C_MESON) += meson_i2c.o obj-$(CONFIG_SYS_I2C_MVTWSI) += mvtwsi.o obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o -obj-$(CONFIG_SYS_I2C_MXS) += mxs_i2c.o obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o obj-$(CONFIG_SYS_I2C_RCAR_I2C) += rcar_i2c.o obj-$(CONFIG_SYS_I2C_RCAR_IIC) += rcar_iic.o diff --git a/drivers/i2c/mxs_i2c.c b/drivers/i2c/mxs_i2c.c deleted file mode 100644 index 6766d375479..00000000000 --- a/drivers/i2c/mxs_i2c.c +++ /dev/null @@ -1,319 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Freescale i.MX28 I2C Driver - * - * Copyright (C) 2011 Marek Vasut - * on behalf of DENX Software Engineering GmbH - * - * Partly based on Linux kernel i2c-mxs.c driver: - * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K. - * - * Which was based on a (non-working) driver which was: - * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define MXS_I2C_MAX_TIMEOUT 1000000 - -static struct mxs_i2c_regs *mxs_i2c_get_base(struct i2c_adapter *adap) -{ - if (adap->hwadapnr == 0) - return (struct mxs_i2c_regs *)MXS_I2C0_BASE; - else - return (struct mxs_i2c_regs *)MXS_I2C1_BASE; -} - -static unsigned int mxs_i2c_get_bus_speed(struct i2c_adapter *adap) -{ - struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(adap); - uint32_t clk = mxc_get_clock(MXC_XTAL_CLK); - uint32_t timing0; - - timing0 = readl(&i2c_regs->hw_i2c_timing0); - /* - * This is a reverse version of the algorithm presented in - * i2c_set_bus_speed(). Please refer there for details. - */ - return clk / ((((timing0 >> 16) - 3) * 2) + 38); -} - -static uint mxs_i2c_set_bus_speed(struct i2c_adapter *adap, uint speed) -{ - struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(adap); - /* - * The timing derivation algorithm. There is no documentation for this - * algorithm available, it was derived by using the scope and fiddling - * with constants until the result observed on the scope was good enough - * for 20kHz, 50kHz, 100kHz, 200kHz, 300kHz and 400kHz. It should be - * possible to assume the algorithm works for other frequencies as well. - * - * Note it was necessary to cap the frequency on both ends as it's not - * possible to configure completely arbitrary frequency for the I2C bus - * clock. - */ - uint32_t clk = mxc_get_clock(MXC_XTAL_CLK); - uint32_t base = ((clk / speed) - 38) / 2; - uint16_t high_count = base + 3; - uint16_t low_count = base - 3; - uint16_t rcv_count = (high_count * 3) / 4; - uint16_t xmit_count = low_count / 4; - - if (speed > 540000) { - printf("MXS I2C: Speed too high (%d Hz)\n", speed); - return -EINVAL; - } - - if (speed < 12000) { - printf("MXS I2C: Speed too low (%d Hz)\n", speed); - return -EINVAL; - } - - writel((high_count << 16) | rcv_count, &i2c_regs->hw_i2c_timing0); - writel((low_count << 16) | xmit_count, &i2c_regs->hw_i2c_timing1); - - writel((0x0030 << I2C_TIMING2_BUS_FREE_OFFSET) | - (0x0030 << I2C_TIMING2_LEADIN_COUNT_OFFSET), - &i2c_regs->hw_i2c_timing2); - - return 0; -} - -static void mxs_i2c_reset(struct i2c_adapter *adap) -{ - struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(adap); - int ret; - int speed = mxs_i2c_get_bus_speed(adap); - - ret = mxs_reset_block(&i2c_regs->hw_i2c_ctrl0_reg); - if (ret) { - debug("MXS I2C: Block reset timeout\n"); - return; - } - - writel(I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ | I2C_CTRL1_NO_SLAVE_ACK_IRQ | - I2C_CTRL1_EARLY_TERM_IRQ | I2C_CTRL1_MASTER_LOSS_IRQ | - I2C_CTRL1_SLAVE_STOP_IRQ | I2C_CTRL1_SLAVE_IRQ, - &i2c_regs->hw_i2c_ctrl1_clr); - - writel(I2C_QUEUECTRL_PIO_QUEUE_MODE, &i2c_regs->hw_i2c_queuectrl_set); - - mxs_i2c_set_bus_speed(adap, speed); -} - -static void mxs_i2c_setup_read(struct i2c_adapter *adap, uint8_t chip, int len) -{ - struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(adap); - - writel(I2C_QUEUECMD_RETAIN_CLOCK | I2C_QUEUECMD_PRE_SEND_START | - I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION | - (1 << I2C_QUEUECMD_XFER_COUNT_OFFSET), - &i2c_regs->hw_i2c_queuecmd); - - writel((chip << 1) | 1, &i2c_regs->hw_i2c_data); - - writel(I2C_QUEUECMD_SEND_NAK_ON_LAST | I2C_QUEUECMD_MASTER_MODE | - (len << I2C_QUEUECMD_XFER_COUNT_OFFSET) | - I2C_QUEUECMD_POST_SEND_STOP, &i2c_regs->hw_i2c_queuecmd); - - writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set); -} - -static int mxs_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, - int alen, uchar *buf, int blen, int stop) -{ - struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(adap); - uint32_t data, tmp; - int i, remain, off; - int timeout = MXS_I2C_MAX_TIMEOUT; - - if ((alen > 4) || (alen == 0)) { - debug("MXS I2C: Invalid address length\n"); - return -EINVAL; - } - - if (stop) - stop = I2C_QUEUECMD_POST_SEND_STOP; - - writel(I2C_QUEUECMD_PRE_SEND_START | - I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION | - ((blen + alen + 1) << I2C_QUEUECMD_XFER_COUNT_OFFSET) | stop, - &i2c_regs->hw_i2c_queuecmd); - - data = (chip << 1) << 24; - - for (i = 0; i < alen; i++) { - data >>= 8; - data |= ((char *)&addr)[alen - i - 1] << 24; - if ((i & 3) == 2) - writel(data, &i2c_regs->hw_i2c_data); - } - - off = i; - for (; i < off + blen; i++) { - data >>= 8; - data |= buf[i - off] << 24; - if ((i & 3) == 2) - writel(data, &i2c_regs->hw_i2c_data); - } - - remain = 24 - ((i & 3) * 8); - if (remain) - writel(data >> remain, &i2c_regs->hw_i2c_data); - - writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set); - - while (--timeout) { - tmp = readl(&i2c_regs->hw_i2c_queuestat); - if (tmp & I2C_QUEUESTAT_WR_QUEUE_EMPTY) - break; - } - - if (!timeout) { - debug("MXS I2C: Failed transmitting data!\n"); - return -EINVAL; - } - - return 0; -} - -static int mxs_i2c_wait_for_ack(struct i2c_adapter *adap) -{ - struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(adap); - uint32_t tmp; - int timeout = MXS_I2C_MAX_TIMEOUT; - - for (;;) { - tmp = readl(&i2c_regs->hw_i2c_ctrl1); - if (tmp & I2C_CTRL1_NO_SLAVE_ACK_IRQ) { - debug("MXS I2C: No slave ACK\n"); - goto err; - } - - if (tmp & ( - I2C_CTRL1_EARLY_TERM_IRQ | I2C_CTRL1_MASTER_LOSS_IRQ | - I2C_CTRL1_SLAVE_STOP_IRQ | I2C_CTRL1_SLAVE_IRQ)) { - debug("MXS I2C: Error (CTRL1 = %08x)\n", tmp); - goto err; - } - - if (tmp & I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ) - break; - - if (!timeout--) { - debug("MXS I2C: Operation timed out\n"); - goto err; - } - - udelay(1); - } - - return 0; - -err: - mxs_i2c_reset(adap); - return 1; -} - -static int mxs_i2c_if_read(struct i2c_adapter *adap, uint8_t chip, - uint addr, int alen, uint8_t *buffer, - int len) -{ - struct mxs_i2c_regs *i2c_regs = mxs_i2c_get_base(adap); - uint32_t tmp = 0; - int timeout = MXS_I2C_MAX_TIMEOUT; - int ret; - int i; - - ret = mxs_i2c_write(adap, chip, addr, alen, NULL, 0, 0); - if (ret) { - debug("MXS I2C: Failed writing address\n"); - return ret; - } - - ret = mxs_i2c_wait_for_ack(adap); - if (ret) { - debug("MXS I2C: Failed writing address\n"); - return ret; - } - - mxs_i2c_setup_read(adap, chip, len); - ret = mxs_i2c_wait_for_ack(adap); - if (ret) { - debug("MXS I2C: Failed reading address\n"); - return ret; - } - - for (i = 0; i < len; i++) { - if (!(i & 3)) { - while (--timeout) { - tmp = readl(&i2c_regs->hw_i2c_queuestat); - if (!(tmp & I2C_QUEUESTAT_RD_QUEUE_EMPTY)) - break; - } - - if (!timeout) { - debug("MXS I2C: Failed receiving data!\n"); - return -ETIMEDOUT; - } - - tmp = readl(&i2c_regs->hw_i2c_queuedata); - } - buffer[i] = tmp & 0xff; - tmp >>= 8; - } - - return 0; -} - -static int mxs_i2c_if_write(struct i2c_adapter *adap, uint8_t chip, - uint addr, int alen, uint8_t *buffer, - int len) -{ - int ret; - ret = mxs_i2c_write(adap, chip, addr, alen, buffer, len, 1); - if (ret) { - debug("MXS I2C: Failed writing address\n"); - return ret; - } - - ret = mxs_i2c_wait_for_ack(adap); - if (ret) - debug("MXS I2C: Failed writing address\n"); - - return ret; -} - -static int mxs_i2c_probe(struct i2c_adapter *adap, uint8_t chip) -{ - int ret; - ret = mxs_i2c_write(adap, chip, 0, 1, NULL, 0, 1); - if (!ret) - ret = mxs_i2c_wait_for_ack(adap); - mxs_i2c_reset(adap); - return ret; -} - -static void mxs_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr) -{ - mxs_i2c_reset(adap); - mxs_i2c_set_bus_speed(adap, speed); - - return; -} - -U_BOOT_I2C_ADAP_COMPLETE(mxs0, mxs_i2c_init, mxs_i2c_probe, - mxs_i2c_if_read, mxs_i2c_if_write, - mxs_i2c_set_bus_speed, - CONFIG_SYS_I2C_SPEED, 0, 0) -U_BOOT_I2C_ADAP_COMPLETE(mxs1, mxs_i2c_init, mxs_i2c_probe, - mxs_i2c_if_read, mxs_i2c_if_write, - mxs_i2c_set_bus_speed, - CONFIG_SYS_I2C_SPEED, 0, 1) -- cgit v1.2.3 From 71f2700b92ab6e419741dc81c27d77cddfaab45f Mon Sep 17 00:00:00 2001 From: Ley Foon Tan Date: Thu, 16 Aug 2018 13:46:30 +0800 Subject: gpio: dwapb_gpio: Enable get_function support Enabled get_function support for dwapb where the function will return the state of GPIO port. Signed-off-by: Chin Liang See Signed-off-by: Ley Foon Tan --- drivers/gpio/dwapb_gpio.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/dwapb_gpio.c b/drivers/gpio/dwapb_gpio.c index a118f58b226..e7e9b1e3873 100644 --- a/drivers/gpio/dwapb_gpio.c +++ b/drivers/gpio/dwapb_gpio.c @@ -78,11 +78,25 @@ static int dwapb_gpio_set_value(struct udevice *dev, unsigned pin, int val) return 0; } +static int dwapb_gpio_get_function(struct udevice *dev, unsigned offset) +{ + struct gpio_dwapb_platdata *plat = dev_get_platdata(dev); + u32 gpio; + + gpio = readl(plat->base + GPIO_SWPORT_DDR(plat->bank)); + + if (gpio & BIT(offset)) + return GPIOF_OUTPUT; + else + return GPIOF_INPUT; +} + 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, + .get_function = dwapb_gpio_get_function, }; static int gpio_dwapb_probe(struct udevice *dev) -- cgit v1.2.3 From db6a158bc3fbf44fa71d18bf92f48961a500b4cc Mon Sep 17 00:00:00 2001 From: Ley Foon Tan Date: Tue, 4 Sep 2018 14:04:58 +0800 Subject: gpio: dwapb_gpio: Add reset ctrl to driver Add code to reset all reset signals as in gpio DT node. A reset property is an optional feature, so only print out a warning and do not fail if a reset property is not present. If a reset property is discovered, then use it to deassert, thus bringing the IP out of reset. Signed-off-by: Ley Foon Tan --- drivers/gpio/dwapb_gpio.c | 51 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/dwapb_gpio.c b/drivers/gpio/dwapb_gpio.c index e7e9b1e3873..3f6f2e875a3 100644 --- a/drivers/gpio/dwapb_gpio.c +++ b/drivers/gpio/dwapb_gpio.c @@ -15,6 +15,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -29,6 +30,10 @@ DECLARE_GLOBAL_DATA_PTR; #define GPIO_PORTA_EOI 0x4c #define GPIO_EXT_PORT(p) (0x50 + (p) * 4) +struct gpio_dwapb_priv { + struct reset_ctl_bulk resets; +}; + struct gpio_dwapb_platdata { const char *name; int bank; @@ -99,13 +104,42 @@ static const struct dm_gpio_ops gpio_dwapb_ops = { .get_function = dwapb_gpio_get_function, }; +static int gpio_dwapb_reset(struct udevice *dev) +{ + int ret; + struct gpio_dwapb_priv *priv = dev_get_priv(dev); + + ret = reset_get_bulk(dev, &priv->resets); + if (ret) { + /* Return 0 if error due to !CONFIG_DM_RESET and reset + * DT property is not present. + */ + if (ret == -ENOENT || ret == -ENOTSUPP) + return 0; + + dev_warn(dev, "Can't get reset: %d\n", ret); + return ret; + } + + ret = reset_deassert_bulk(&priv->resets); + if (ret) { + reset_release_bulk(&priv->resets); + dev_err(dev, "Failed to reset: %d\n", ret); + return ret; + } + + return 0; +} + 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; + if (!plat) { + /* Reset on parent device only */ + return gpio_dwapb_reset(dev); + } priv->gpio_count = plat->pins; priv->bank_name = plat->name; @@ -166,6 +200,17 @@ err: return ret; } +static int gpio_dwapb_remove(struct udevice *dev) +{ + struct gpio_dwapb_platdata *plat = dev_get_platdata(dev); + struct gpio_dwapb_priv *priv = dev_get_priv(dev); + + if (!plat && priv) + return reset_release_bulk(&priv->resets); + + return 0; +} + static const struct udevice_id gpio_dwapb_ids[] = { { .compatible = "snps,dw-apb-gpio" }, { } @@ -178,4 +223,6 @@ U_BOOT_DRIVER(gpio_dwapb) = { .ops = &gpio_dwapb_ops, .bind = gpio_dwapb_bind, .probe = gpio_dwapb_probe, + .remove = gpio_dwapb_remove, + .priv_auto_alloc_size = sizeof(struct gpio_dwapb_priv), }; -- cgit v1.2.3 From 9ea354444d156b1f7c1d1990a32215c257b38e16 Mon Sep 17 00:00:00 2001 From: Ley Foon Tan Date: Thu, 16 Aug 2018 02:05:54 +0800 Subject: gpio: dwapb_gpio: Change to use dev_read_addr() This changes the driver to use dev_read_addr() which is safe both for flat trees and live trees. Signed-off-by: Ley Foon Tan --- drivers/gpio/dwapb_gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/dwapb_gpio.c b/drivers/gpio/dwapb_gpio.c index 3f6f2e875a3..0f6574d5da1 100644 --- a/drivers/gpio/dwapb_gpio.c +++ b/drivers/gpio/dwapb_gpio.c @@ -159,7 +159,7 @@ static int gpio_dwapb_bind(struct udevice *dev) if (plat) return 0; - base = fdtdec_get_addr(blob, dev_of_offset(dev), "reg"); + base = dev_read_addr(dev); if (base == FDT_ADDR_T_NONE) { debug("Can't get the GPIO register base address\n"); return -ENXIO; -- cgit v1.2.3 From 02d8d3259133ea7af6031e4a780bdac1462ae057 Mon Sep 17 00:00:00 2001 From: Dalon Westergreen Date: Tue, 11 Sep 2018 10:06:14 -0700 Subject: socfpga: stratix10: fix sdram_calculate_size Incorrect type of size variable results in 0 being returned for sdram sizes greater than or equal to 4GB. Signed-off-by: Dalon Westergreen --- drivers/ddr/altera/sdram_s10.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ddr/altera/sdram_s10.c b/drivers/ddr/altera/sdram_s10.c index 48f4f47b14b..a48567c1093 100644 --- a/drivers/ddr/altera/sdram_s10.c +++ b/drivers/ddr/altera/sdram_s10.c @@ -371,11 +371,11 @@ int sdram_mmr_init_full(unsigned int unused) * Calculate SDRAM device size based on SDRAM controller parameters. * Size is specified in bytes. */ -unsigned long sdram_calculate_size(void) +phys_size_t sdram_calculate_size(void) { u32 dramaddrw = hmc_readl(DRAMADDRW); - u32 size = 1 << (DRAMADDRW_CFG_CS_ADDR_WIDTH(dramaddrw) + + phys_size_t size = 1 << (DRAMADDRW_CFG_CS_ADDR_WIDTH(dramaddrw) + DRAMADDRW_CFG_BANK_GRP_ADDR_WIDTH(dramaddrw) + DRAMADDRW_CFG_BANK_ADDR_WIDTH(dramaddrw) + DRAMADDRW_CFG_ROW_ADDR_WIDTH(dramaddrw) + -- cgit v1.2.3 From 5c349e179db794eff99dd5d3bbac6845d173709e Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Tue, 4 Sep 2018 11:37:25 +0200 Subject: usb: ehci-generic: Add vbus-supply regulator support Add vbus-supply regulator support. On some board vbus is not controlled by the phy but by an external regulator. Signed-off-by: Patrice Chotard --- drivers/usb/host/ehci-generic.c | 62 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index cc2f33826a3..0270f3bc95a 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -11,6 +11,7 @@ #include #include #include "ehci.h" +#include /* * Even though here we don't explicitly use "struct ehci_ctrl" @@ -22,10 +23,56 @@ struct generic_ehci { struct clk *clocks; struct reset_ctl *resets; struct phy phy; +#ifdef CONFIG_DM_REGULATOR + struct udevice *vbus_supply; +#endif int clock_count; int reset_count; }; +#ifdef CONFIG_DM_REGULATOR +static int ehci_enable_vbus_supply(struct udevice *dev) +{ + struct generic_ehci *priv = dev_get_priv(dev); + int ret; + + ret = device_get_supply_regulator(dev, "vbus-supply", + &priv->vbus_supply); + if (ret && ret != -ENOENT) + return ret; + + if (priv->vbus_supply) { + ret = regulator_set_enable(priv->vbus_supply, true); + if (ret) { + dev_err(dev, "Error enabling VBUS supply\n"); + return ret; + } + } else { + dev_dbg(dev, "No vbus supply\n"); + } + + return 0; +} + +static int ehci_disable_vbus_supply(struct generic_ehci *priv) +{ + if (priv->vbus_supply) + return regulator_set_enable(priv->vbus_supply, false); + else + return 0; +} +#else +static int ehci_enable_vbus_supply(struct udevice *dev) +{ + return 0; +} + +static int ehci_disable_vbus_supply(struct generic_ehci *priv) +{ + return 0; +} +#endif + static int ehci_usb_probe(struct udevice *dev) { struct generic_ehci *priv = dev_get_priv(dev); @@ -95,10 +142,14 @@ static int ehci_usb_probe(struct udevice *dev) } } - err = ehci_setup_phy(dev, &priv->phy, 0); + err = ehci_enable_vbus_supply(dev); if (err) goto reset_err; + err = ehci_setup_phy(dev, &priv->phy, 0); + if (err) + goto regulator_err; + hccr = map_physmem(dev_read_addr(dev), 0x100, MAP_NOCACHE); hcor = (struct ehci_hcor *)((uintptr_t)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); @@ -114,6 +165,11 @@ phy_err: if (ret) dev_err(dev, "failed to shutdown usb phy\n"); +regulator_err: + ret = ehci_disable_vbus_supply(priv); + if (ret) + dev_err(dev, "failed to disable VBUS supply\n"); + reset_err: ret = reset_release_all(priv->resets, priv->reset_count); if (ret) @@ -139,6 +195,10 @@ static int ehci_usb_remove(struct udevice *dev) if (ret) return ret; + ret = ehci_disable_vbus_supply(priv); + if (ret) + return ret; + ret = reset_release_all(priv->resets, priv->reset_count); if (ret) return ret; -- cgit v1.2.3