diff options
| author | Tom Rini <[email protected]> | 2022-03-07 16:20:36 -0500 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2022-03-07 16:20:36 -0500 |
| commit | 0bf4e0bb935e5c7fc016142e0228882610ecbf39 (patch) | |
| tree | 4c454f86cbbe76a633a380383ba8635d6f226a71 /drivers | |
| parent | fd690a5e932010d0309a859169aeb77af94dff24 (diff) | |
| parent | 14d8610090fe5aef1b2d0f4d80ec6d4009e61056 (diff) | |
Merge branch '2022-03-07-add-platforms' into next
- bcm6753 support
- Aspeed GPIO driver
- AM33xx DT-related MMC updates
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpio/Kconfig | 10 | ||||
| -rw-r--r-- | drivers/gpio/Makefile | 1 | ||||
| -rw-r--r-- | drivers/gpio/gpio-aspeed.c | 299 | ||||
| -rw-r--r-- | drivers/led/Kconfig | 7 | ||||
| -rw-r--r-- | drivers/led/Makefile | 1 | ||||
| -rw-r--r-- | drivers/led/led_bcm6753.c | 270 | ||||
| -rw-r--r-- | drivers/mmc/omap_hsmmc.c | 1 | ||||
| -rw-r--r-- | drivers/mtd/nand/raw/Kconfig | 6 | ||||
| -rw-r--r-- | drivers/mtd/nand/raw/brcmnand/Makefile | 1 | ||||
| -rw-r--r-- | drivers/mtd/nand/raw/brcmnand/bcm6753_nand.c | 124 | ||||
| -rw-r--r-- | drivers/watchdog/Kconfig | 3 |
11 files changed, 721 insertions, 2 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 8d0e47c67d9..be64303d7f9 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -87,7 +87,8 @@ config ALTERA_PIO config BCM6345_GPIO bool "BCM6345 GPIO driver" depends on DM_GPIO && (ARCH_BMIPS || ARCH_BCM68360 || \ - ARCH_BCM6858 || ARCH_BCM63158) + ARCH_BCM6858 || ARCH_BCM63158 || \ + ARCH_BCM6753) help This driver supports the GPIO banks on BCM6345 SoCs. @@ -126,6 +127,13 @@ config ATMEL_PIO4 may be dedicated as a general purpose I/O or be assigned to a function of an embedded peripheral. +config ASPEED_GPIO + bool "Aspeed GPIO Driver" + help + Say yes here to support the Aspeed GPIO driver. The controller + is found in the AST2400, AST2500 and AST2600 BMC SoCs and + provides access to over 200 GPIOs on each chip. + config DA8XX_GPIO bool "DA8xx GPIO Driver" help diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 63e9be6034f..720297952cd 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_$(SPL_TPL_)DM_GPIO) += gpio-uclass.o obj-$(CONFIG_$(SPL_)DM_PCA953X) += pca953x_gpio.o +obj-$(CONFIG_ASPEED_GPIO) += gpio-aspeed.o obj-$(CONFIG_AT91_GPIO) += at91_gpio.o obj-$(CONFIG_ATMEL_PIO4) += atmel_pio4.o obj-$(CONFIG_BCM6345_GPIO) += bcm6345_gpio.o diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c new file mode 100644 index 00000000000..a8a2afcb5c8 --- /dev/null +++ b/drivers/gpio/gpio-aspeed.c @@ -0,0 +1,299 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2015 IBM Corp. + * Joel Stanley <[email protected]> + * Ryan Chen <[email protected]> + * + * Implementation extracted from the Linux kernel and adapted for u-boot. + */ +#include <common.h> +#include <asm/io.h> +#include <asm/gpio.h> + +#include <config.h> +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <asm/io.h> +#include <linux/bug.h> +#include <linux/sizes.h> + +struct aspeed_gpio_priv { + void *regs; +}; + +struct aspeed_gpio_bank { + u16 val_regs; /* +0: Rd: read input value, Wr: set write latch + * +4: Rd/Wr: Direction (0=in, 1=out) + */ + u16 rdata_reg; /* Rd: read write latch, Wr: <none> */ + u16 irq_regs; + u16 debounce_regs; + u16 tolerance_regs; + u16 cmdsrc_regs; + const char names[4][3]; +}; + +static const struct aspeed_gpio_bank aspeed_gpio_banks[] = { + { + .val_regs = 0x0000, + .rdata_reg = 0x00c0, + .irq_regs = 0x0008, + .debounce_regs = 0x0040, + .tolerance_regs = 0x001c, + .cmdsrc_regs = 0x0060, + .names = { "A", "B", "C", "D" }, + }, + { + .val_regs = 0x0020, + .rdata_reg = 0x00c4, + .irq_regs = 0x0028, + .debounce_regs = 0x0048, + .tolerance_regs = 0x003c, + .cmdsrc_regs = 0x0068, + .names = { "E", "F", "G", "H" }, + }, + { + .val_regs = 0x0070, + .rdata_reg = 0x00c8, + .irq_regs = 0x0098, + .debounce_regs = 0x00b0, + .tolerance_regs = 0x00ac, + .cmdsrc_regs = 0x0090, + .names = { "I", "J", "K", "L" }, + }, + { + .val_regs = 0x0078, + .rdata_reg = 0x00cc, + .irq_regs = 0x00e8, + .debounce_regs = 0x0100, + .tolerance_regs = 0x00fc, + .cmdsrc_regs = 0x00e0, + .names = { "M", "N", "O", "P" }, + }, + { + .val_regs = 0x0080, + .rdata_reg = 0x00d0, + .irq_regs = 0x0118, + .debounce_regs = 0x0130, + .tolerance_regs = 0x012c, + .cmdsrc_regs = 0x0110, + .names = { "Q", "R", "S", "T" }, + }, + { + .val_regs = 0x0088, + .rdata_reg = 0x00d4, + .irq_regs = 0x0148, + .debounce_regs = 0x0160, + .tolerance_regs = 0x015c, + .cmdsrc_regs = 0x0140, + .names = { "U", "V", "W", "X" }, + }, + { + .val_regs = 0x01E0, + .rdata_reg = 0x00d8, + .irq_regs = 0x0178, + .debounce_regs = 0x0190, + .tolerance_regs = 0x018c, + .cmdsrc_regs = 0x0170, + .names = { "Y", "Z", "AA", "AB" }, + }, + { + .val_regs = 0x01e8, + .rdata_reg = 0x00dc, + .irq_regs = 0x01a8, + .debounce_regs = 0x01c0, + .tolerance_regs = 0x01bc, + .cmdsrc_regs = 0x01a0, + .names = { "AC", "", "", "" }, + }, +}; + +enum aspeed_gpio_reg { + reg_val, + reg_rdata, + reg_dir, + reg_irq_enable, + reg_irq_type0, + reg_irq_type1, + reg_irq_type2, + reg_irq_status, + reg_debounce_sel1, + reg_debounce_sel2, + reg_tolerance, + reg_cmdsrc0, + reg_cmdsrc1, +}; + +#define GPIO_VAL_VALUE 0x00 +#define GPIO_VAL_DIR 0x04 + +#define GPIO_IRQ_ENABLE 0x00 +#define GPIO_IRQ_TYPE0 0x04 +#define GPIO_IRQ_TYPE1 0x08 +#define GPIO_IRQ_TYPE2 0x0c +#define GPIO_IRQ_STATUS 0x10 + +#define GPIO_DEBOUNCE_SEL1 0x00 +#define GPIO_DEBOUNCE_SEL2 0x04 + +#define GPIO_CMDSRC_0 0x00 +#define GPIO_CMDSRC_1 0x04 +#define GPIO_CMDSRC_ARM 0 +#define GPIO_CMDSRC_LPC 1 +#define GPIO_CMDSRC_COLDFIRE 2 +#define GPIO_CMDSRC_RESERVED 3 + +/* This will be resolved at compile time */ +static inline void __iomem *bank_reg(struct aspeed_gpio_priv *gpio, + const struct aspeed_gpio_bank *bank, + const enum aspeed_gpio_reg reg) +{ + switch (reg) { + case reg_val: + return gpio->regs + bank->val_regs + GPIO_VAL_VALUE; + case reg_rdata: + return gpio->regs + bank->rdata_reg; + case reg_dir: + return gpio->regs + bank->val_regs + GPIO_VAL_DIR; + case reg_irq_enable: + return gpio->regs + bank->irq_regs + GPIO_IRQ_ENABLE; + case reg_irq_type0: + return gpio->regs + bank->irq_regs + GPIO_IRQ_TYPE0; + case reg_irq_type1: + return gpio->regs + bank->irq_regs + GPIO_IRQ_TYPE1; + case reg_irq_type2: + return gpio->regs + bank->irq_regs + GPIO_IRQ_TYPE2; + case reg_irq_status: + return gpio->regs + bank->irq_regs + GPIO_IRQ_STATUS; + case reg_debounce_sel1: + return gpio->regs + bank->debounce_regs + GPIO_DEBOUNCE_SEL1; + case reg_debounce_sel2: + return gpio->regs + bank->debounce_regs + GPIO_DEBOUNCE_SEL2; + case reg_tolerance: + return gpio->regs + bank->tolerance_regs; + case reg_cmdsrc0: + return gpio->regs + bank->cmdsrc_regs + GPIO_CMDSRC_0; + case reg_cmdsrc1: + return gpio->regs + bank->cmdsrc_regs + GPIO_CMDSRC_1; + } + BUG(); +} + +#define GPIO_BANK(x) ((x) >> 5) +#define GPIO_OFFSET(x) ((x) & 0x1f) +#define GPIO_BIT(x) BIT(GPIO_OFFSET(x)) + +static const struct aspeed_gpio_bank *to_bank(unsigned int offset) +{ + unsigned int bank = GPIO_BANK(offset); + + WARN_ON(bank >= ARRAY_SIZE(aspeed_gpio_banks)); + return &aspeed_gpio_banks[bank]; +} + +static int +aspeed_gpio_direction_input(struct udevice *dev, unsigned int offset) +{ + struct aspeed_gpio_priv *priv = dev_get_priv(dev); + const struct aspeed_gpio_bank *bank = to_bank(offset); + u32 dir = readl(bank_reg(priv, bank, reg_dir)); + + dir &= ~GPIO_BIT(offset); + writel(dir, bank_reg(priv, bank, reg_dir)); + + return 0; +} + +static int aspeed_gpio_direction_output(struct udevice *dev, unsigned int offset, + int value) +{ + struct aspeed_gpio_priv *priv = dev_get_priv(dev); + const struct aspeed_gpio_bank *bank = to_bank(offset); + u32 dir = readl(bank_reg(priv, bank, reg_dir)); + u32 output = readl(bank_reg(priv, bank, reg_val)); + + dir |= GPIO_BIT(offset); + writel(dir, bank_reg(priv, bank, reg_dir)); + + if (value) + output |= GPIO_BIT(offset); + else + output &= ~GPIO_BIT(offset); + + writel(output, bank_reg(priv, bank, reg_val)); + + return 0; +} + +static int aspeed_gpio_get_value(struct udevice *dev, unsigned int offset) +{ + struct aspeed_gpio_priv *priv = dev_get_priv(dev); + const struct aspeed_gpio_bank *bank = to_bank(offset); + + return !!(readl(bank_reg(priv, bank, reg_val)) & GPIO_BIT(offset)); +} + +static int +aspeed_gpio_set_value(struct udevice *dev, unsigned int offset, int value) +{ + struct aspeed_gpio_priv *priv = dev_get_priv(dev); + const struct aspeed_gpio_bank *bank = to_bank(offset); + u32 data = readl(bank_reg(priv, bank, reg_val)); + + if (value) + data |= GPIO_BIT(offset); + else + data &= ~GPIO_BIT(offset); + + writel(data, bank_reg(priv, bank, reg_val)); + + return 0; +} + +static int aspeed_gpio_get_function(struct udevice *dev, unsigned int offset) +{ + struct aspeed_gpio_priv *priv = dev_get_priv(dev); + const struct aspeed_gpio_bank *bank = to_bank(offset); + + if (readl(bank_reg(priv, bank, reg_dir)) & GPIO_BIT(offset)) + return GPIOF_OUTPUT; + + return GPIOF_INPUT; +} + +static const struct dm_gpio_ops aspeed_gpio_ops = { + .direction_input = aspeed_gpio_direction_input, + .direction_output = aspeed_gpio_direction_output, + .get_value = aspeed_gpio_get_value, + .set_value = aspeed_gpio_set_value, + .get_function = aspeed_gpio_get_function, +}; + +static int aspeed_gpio_probe(struct udevice *dev) +{ + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct aspeed_gpio_priv *priv = dev_get_priv(dev); + + uc_priv->bank_name = dev->name; + ofnode_read_u32(dev_ofnode(dev), "ngpios", &uc_priv->gpio_count); + priv->regs = devfdt_get_addr_ptr(dev); + + return 0; +} + +static const struct udevice_id aspeed_gpio_ids[] = { + { .compatible = "aspeed,ast2400-gpio", }, + { .compatible = "aspeed,ast2500-gpio", }, + { .compatible = "aspeed,ast2600-gpio", }, + { } +}; + +U_BOOT_DRIVER(gpio_aspeed) = { + .name = "gpio-aspeed", + .id = UCLASS_GPIO, + .of_match = aspeed_gpio_ids, + .ops = &aspeed_gpio_ops, + .probe = aspeed_gpio_probe, + .priv_auto = sizeof(struct aspeed_gpio_priv), +}; diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig index cc87fbf395b..430d0760ba5 100644 --- a/drivers/led/Kconfig +++ b/drivers/led/Kconfig @@ -28,6 +28,13 @@ config LED_BCM6358 LED HW controller accessed via MMIO registers. HW has no blinking capabilities and up to 32 LEDs can be controlled. +config LED_BCM6753 + bool "LED Support for BCM6753" + depends on LED && ARCH_BCM6753 + help + This option enables support for LEDs connected to the BCM6753 + HW has blinking and fading capabilities and up to 32 LEDs can be controlled. + config LED_BCM6858 bool "LED Support for BCM6858" depends on LED && (ARCH_BCM68360 || ARCH_BCM6858 || ARCH_BCM63158) diff --git a/drivers/led/Makefile b/drivers/led/Makefile index 8e3ae7f1465..2aa2c2173af 100644 --- a/drivers/led/Makefile +++ b/drivers/led/Makefile @@ -6,6 +6,7 @@ obj-y += led-uclass.o obj-$(CONFIG_LED_BCM6328) += led_bcm6328.o obj-$(CONFIG_LED_BCM6358) += led_bcm6358.o +obj-$(CONFIG_LED_BCM6753) += led_bcm6753.o obj-$(CONFIG_LED_BCM6858) += led_bcm6858.o obj-$(CONFIG_$(SPL_)LED_GPIO) += led_gpio.o obj-$(CONFIG_LED_CORTINA) += led_cortina.o diff --git a/drivers/led/led_bcm6753.c b/drivers/led/led_bcm6753.c new file mode 100644 index 00000000000..a32bd8204fa --- /dev/null +++ b/drivers/led/led_bcm6753.c @@ -0,0 +1,270 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 Philippe Reynes <[email protected]> + * + * based on: + * drivers/led/led_bcm6858.c + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <led.h> +#include <log.h> +#include <asm/io.h> +#include <dm/lists.h> +#include <linux/bitops.h> + +#define LEDS_MAX 32 +#define LEDS_WAIT 100 + +/* LED Mode register */ +#define LED_MODE_REG 0x0 +#define LED_MODE_OFF 0 +#define LED_MODE_ON 1 +#define LED_MODE_MASK 1 + +/* LED Controller Global settings register */ +#define CLED_CTRL_REG 0x00 +#define CLED_CTRL_SERIAL_LED_DATA_PPOL BIT(1) +#define CLED_CTRL_SERIAL_LED_CLK_POL BIT(2) +#define CLED_CTRL_SERIAL_LED_EN_POL BIT(3) +#define CLED_CTRL_SERIAL_LED_MSB_FIRST BIT(4) +#define CLED_CTRL_MASK 0x1E +/* LED Controller IP LED source select register */ +#define CLED_HW_LED_EN_REG 0x04 +/* Hardware LED Polarity register */ +#define CLED_HW_LED_IP_PPOL_REG 0x0c +/* Soft LED Set Register */ +#define CLED_SW_LED_IP_SET_REG 0x10 +/* Parallel LED Output Polarity Register */ +#define CLED_PLED_OP_PPOL_REG 0x18 +/* LED Channel activate register */ +#define CLED_LED_CH_ACTIVATE_REG 0x1c +/* LED 0 Config 0 reg */ +#define CLED_LED_0_CONFIG_0 0x20 +/* Soft LED Clear Register */ +#define CLED_SW_LED_IP_CLEAR_REG 0x444 +/* Soft LED Status Register */ +#define CLED_SW_LED_IP_STATUS_REG 0x448 + +/* Size of all registers used for the config of one LED */ +#define CLED_CONFIG_SIZE (4 * sizeof(u32)) + +#define CLED_CONFIG0_MODE 0 +#define CLED_CONFIG0_MODE_MASK (BIT(0) | BIT(1)) +#define CLED_CONFIG0_MODE_STEADY 0 +#define CLED_CONFIG0_MODE_FADING 1 +#define CLED_CONFIG0_MODE_PULSATING 2 + +#define CLED_CONFIG0_FLASH_CTRL_SHIFT 3 +#define CLED_CONFIG0_FLASH_CTRL_MASK (BIT(3) | BIT(4) | BIT(5)) + +struct bcm6753_led_priv { + void __iomem *regs; + u8 pin; +}; + +/* + * The value for flash rate are: + * 0 : no blinking + * 1 : rate is 25 Hz => 40 ms (period) + * 2 : rate is 12.5 Hz => 80 ms (period) + * 3 : rate is 6.25 Hz => 160 ms (period) + * 4 : rate is 3.125 Hz => 320 ms (period) + * 5 : rate is 1.5625 Hz => 640 ms (period) + * 6 : rate is 0.7815 Hz => 1280 ms (period) + * 7 : rate is 0.390625 Hz => 2560 ms (period) + */ +static const int bcm6753_flash_rate[8] = { + 0, 40, 80, 160, 320, 640, 1280, 2560 +}; + +static u32 bcm6753_flash_rate_value(int period_ms) +{ + unsigned long value = 7; + int i; + + for (i = 0; i < ARRAY_SIZE(bcm6753_flash_rate); i++) { + if (period_ms <= bcm6753_flash_rate[i]) { + value = i; + break; + } + } + + return value; +} + +static int bcm6753_led_set_period(struct udevice *dev, int period_ms) +{ + struct bcm6753_led_priv *priv = dev_get_priv(dev); + u32 offset, shift, value; + + offset = CLED_LED_0_CONFIG_0 + (CLED_CONFIG_SIZE * priv->pin); + value = bcm6753_flash_rate_value(period_ms); + shift = CLED_CONFIG0_FLASH_CTRL_SHIFT; + + /* set mode steady */ + clrbits_32(priv->regs + offset, CLED_CONFIG0_MODE_MASK); + setbits_32(priv->regs + offset, CLED_CONFIG0_MODE_STEADY); + + /* set flash rate */ + clrbits_32(priv->regs + offset, CLED_CONFIG0_FLASH_CTRL_MASK); + setbits_32(priv->regs + offset, value << shift); + + /* enable config */ + setbits_32(priv->regs + CLED_LED_CH_ACTIVATE_REG, 1 << priv->pin); + + return 0; +} + +static enum led_state_t bcm6753_led_get_state(struct udevice *dev) +{ + struct bcm6753_led_priv *priv = dev_get_priv(dev); + enum led_state_t state = LEDST_OFF; + u32 sw_led_ip_status; + + sw_led_ip_status = readl(priv->regs + CLED_SW_LED_IP_STATUS_REG); + if (sw_led_ip_status & (1 << priv->pin)) + state = LEDST_ON; + + return state; +} + +static int bcm6753_led_set_state(struct udevice *dev, enum led_state_t state) +{ + struct bcm6753_led_priv *priv = dev_get_priv(dev); + + switch (state) { + case LEDST_OFF: + setbits_32(priv->regs + CLED_SW_LED_IP_CLEAR_REG, (1 << priv->pin)); + if (IS_ENABLED(CONFIG_LED_BLINK)) + bcm6753_led_set_period(dev, 0); + break; + case LEDST_ON: + setbits_32(priv->regs + CLED_SW_LED_IP_SET_REG, (1 << priv->pin)); + if (IS_ENABLED(CONFIG_LED_BLINK)) + bcm6753_led_set_period(dev, 0); + break; + case LEDST_TOGGLE: + if (bcm6753_led_get_state(dev) == LEDST_OFF) + return bcm6753_led_set_state(dev, LEDST_ON); + else + return bcm6753_led_set_state(dev, LEDST_OFF); + break; +#ifdef CONFIG_LED_BLINK + case LEDST_BLINK: + setbits_32(priv->regs + CLED_SW_LED_IP_SET_REG, (1 << priv->pin)); + break; +#endif + default: + return -EINVAL; + } + + return 0; +} + +static const struct led_ops bcm6753_led_ops = { + .get_state = bcm6753_led_get_state, + .set_state = bcm6753_led_set_state, +#ifdef CONFIG_LED_BLINK + .set_period = bcm6753_led_set_period, +#endif +}; + +static int bcm6753_led_probe(struct udevice *dev) +{ + struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev); + + /* Top-level LED node */ + if (!uc_plat->label) { + void __iomem *regs; + u32 set_bits = 0; + + regs = dev_remap_addr(dev); + if (!regs) + return -EINVAL; + + if (dev_read_bool(dev, "brcm,serial-led-msb-first")) + set_bits |= CLED_CTRL_SERIAL_LED_MSB_FIRST; + if (dev_read_bool(dev, "brcm,serial-led-en-pol")) + set_bits |= CLED_CTRL_SERIAL_LED_EN_POL; + if (dev_read_bool(dev, "brcm,serial-led-clk-pol")) + set_bits |= CLED_CTRL_SERIAL_LED_CLK_POL; + if (dev_read_bool(dev, "brcm,serial-led-data-ppol")) + set_bits |= CLED_CTRL_SERIAL_LED_DATA_PPOL; + + clrsetbits_32(regs + CLED_CTRL_REG, CLED_CTRL_MASK, set_bits); + } else { + struct bcm6753_led_priv *priv = dev_get_priv(dev); + void __iomem *regs; + unsigned int pin; + + regs = dev_remap_addr(dev_get_parent(dev)); + if (!regs) + return -EINVAL; + + pin = dev_read_u32_default(dev, "reg", LEDS_MAX); + if (pin >= LEDS_MAX) + return -EINVAL; + + priv->regs = regs; + priv->pin = pin; + + /* this led is managed by software */ + clrbits_32(regs + CLED_HW_LED_EN_REG, 1 << pin); + + /* configure the polarity */ + if (dev_read_bool(dev, "active-low")) + clrbits_32(regs + CLED_PLED_OP_PPOL_REG, 1 << pin); + else + setbits_32(regs + CLED_PLED_OP_PPOL_REG, 1 << pin); + } + + return 0; +} + +static int bcm6753_led_bind(struct udevice *parent) +{ + ofnode node; + + dev_for_each_subnode(node, parent) { + struct led_uc_plat *uc_plat; + struct udevice *dev; + const char *label; + int ret; + + label = ofnode_read_string(node, "label"); + if (!label) { + debug("%s: node %s has no label\n", __func__, + ofnode_get_name(node)); + return -EINVAL; + } + + ret = device_bind_driver_to_node(parent, "bcm6753-led", + ofnode_get_name(node), + node, &dev); + if (ret) + return ret; + + uc_plat = dev_get_uclass_plat(dev); + uc_plat->label = label; + } + + return 0; +} + +static const struct udevice_id bcm6753_led_ids[] = { + { .compatible = "brcm,bcm6753-leds" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(bcm6753_led) = { + .name = "bcm6753-led", + .id = UCLASS_LED, + .of_match = bcm6753_led_ids, + .bind = bcm6753_led_bind, + .probe = bcm6753_led_probe, + .priv_auto = sizeof(struct bcm6753_led_priv), + .ops = &bcm6753_led_ops, +}; diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index 820065800fe..b2f4a4e7219 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -2019,6 +2019,7 @@ static const struct udevice_id omap_hsmmc_ids[] = { { .compatible = "ti,omap3-hsmmc" }, { .compatible = "ti,omap4-hsmmc" }, { .compatible = "ti,am33xx-hsmmc" }, + { .compatible = "ti,am335-sdhci" }, { .compatible = "ti,dra7-hsmmc", .data = (ulong)&dra7_mmc_of_data }, { } }; diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index 0e826c19298..1eab21e2064 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -91,6 +91,12 @@ config NAND_BRCMNAND_6368 help Enable support for broadcom nand driver on bcm6368. +config NAND_BRCMNAND_6753 + bool "Support Broadcom NAND controller on bcm6753" + depends on NAND_BRCMNAND && ARCH_BCM6753 + help + Enable support for broadcom nand driver on bcm6753. + config NAND_BRCMNAND_68360 bool "Support Broadcom NAND controller on bcm68360" depends on NAND_BRCMNAND && ARCH_BCM68360 diff --git a/drivers/mtd/nand/raw/brcmnand/Makefile b/drivers/mtd/nand/raw/brcmnand/Makefile index 5d9e7e3f3b5..f46a7edae32 100644 --- a/drivers/mtd/nand/raw/brcmnand/Makefile +++ b/drivers/mtd/nand/raw/brcmnand/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_NAND_BRCMNAND_6368) += bcm6368_nand.o obj-$(CONFIG_NAND_BRCMNAND_63158) += bcm63158_nand.o +obj-$(CONFIG_NAND_BRCMNAND_6753) += bcm6753_nand.o obj-$(CONFIG_NAND_BRCMNAND_68360) += bcm68360_nand.o obj-$(CONFIG_NAND_BRCMNAND_6838) += bcm6838_nand.o obj-$(CONFIG_NAND_BRCMNAND_6858) += bcm6858_nand.o diff --git a/drivers/mtd/nand/raw/brcmnand/bcm6753_nand.c b/drivers/mtd/nand/raw/brcmnand/bcm6753_nand.c new file mode 100644 index 00000000000..feae66ef25a --- /dev/null +++ b/drivers/mtd/nand/raw/brcmnand/bcm6753_nand.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <common.h> +#include <asm/io.h> +#include <memalign.h> +#include <nand.h> +#include <linux/bitops.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <dm.h> + +#include "brcmnand.h" + +struct bcm6753_nand_soc { + struct brcmnand_soc soc; + void __iomem *base; +}; + +#define BCM6753_NAND_INT 0x00 +#define BCM6753_NAND_STATUS_SHIFT 0 +#define BCM6753_NAND_STATUS_MASK (0xfff << BCM6753_NAND_STATUS_SHIFT) + +#define BCM6753_NAND_INT_EN 0x04 +#define BCM6753_NAND_ENABLE_SHIFT 0 +#define BCM6753_NAND_ENABLE_MASK (0xffff << BCM6753_NAND_ENABLE_SHIFT) + +enum { + BCM6753_NP_READ = BIT(0), + BCM6753_BLOCK_ERASE = BIT(1), + BCM6753_COPY_BACK = BIT(2), + BCM6753_PAGE_PGM = BIT(3), + BCM6753_CTRL_READY = BIT(4), + BCM6753_DEV_RBPIN = BIT(5), + BCM6753_ECC_ERR_UNC = BIT(6), + BCM6753_ECC_ERR_CORR = BIT(7), +}; + +static bool bcm6753_nand_intc_ack(struct brcmnand_soc *soc) +{ + struct bcm6753_nand_soc *priv = + container_of(soc, struct bcm6753_nand_soc, soc); + void __iomem *mmio = priv->base + BCM6753_NAND_INT; + u32 val = brcmnand_readl(mmio); + + if (val & (BCM6753_CTRL_READY << BCM6753_NAND_STATUS_SHIFT)) { + /* Ack interrupt */ + val &= ~BCM6753_NAND_STATUS_MASK; + val |= BCM6753_CTRL_READY << BCM6753_NAND_STATUS_SHIFT; + brcmnand_writel(val, mmio); + return true; + } + + return false; +} + +static void bcm6753_nand_intc_set(struct brcmnand_soc *soc, bool en) +{ + struct bcm6753_nand_soc *priv = + container_of(soc, struct bcm6753_nand_soc, soc); + void __iomem *mmio = priv->base + BCM6753_NAND_INT_EN; + u32 val = brcmnand_readl(mmio); + + /* Don't ack any interrupts */ + val &= ~BCM6753_NAND_STATUS_MASK; + + if (en) + val |= BCM6753_CTRL_READY << BCM6753_NAND_ENABLE_SHIFT; + else + val &= ~(BCM6753_CTRL_READY << BCM6753_NAND_ENABLE_SHIFT); + + brcmnand_writel(val, mmio); +} + +static int bcm6753_nand_probe(struct udevice *dev) +{ + struct udevice *pdev = dev; + struct bcm6753_nand_soc *priv = dev_get_priv(dev); + struct brcmnand_soc *soc; + struct resource res; + + soc = &priv->soc; + + dev_read_resource_byname(pdev, "nand-int-base", &res); + priv->base = devm_ioremap(dev, res.start, resource_size(&res)); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + soc->ctlrdy_ack = bcm6753_nand_intc_ack; + soc->ctlrdy_set_enabled = bcm6753_nand_intc_set; + + /* Disable and ack all interrupts */ + brcmnand_writel(0, priv->base + BCM6753_NAND_INT_EN); + brcmnand_writel(0, priv->base + BCM6753_NAND_INT); + + return brcmnand_probe(pdev, soc); +} + +static const struct udevice_id bcm6753_nand_dt_ids[] = { + { + .compatible = "brcm,nand-bcm6753", + }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(bcm6753_nand) = { + .name = "bcm6753-nand", + .id = UCLASS_MTD, + .of_match = bcm6753_nand_dt_ids, + .probe = bcm6753_nand_probe, + .priv_auto = sizeof(struct bcm6753_nand_soc), +}; + +void board_nand_init(void) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_MTD, + DM_DRIVER_GET(bcm6753_nand), &dev); + if (ret && ret != -ENODEV) + pr_err("Failed to initialize %s. (error %d)\n", dev->name, + ret); +} diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index cabac290539..1f3ca99f9aa 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -129,7 +129,8 @@ config WDT_AT91 config WDT_BCM6345 bool "BCM6345 watchdog timer support" depends on WDT && (ARCH_BMIPS || ARCH_BCM68360 || \ - ARCH_BCM6858 || ARCH_BCM63158) + ARCH_BCM6858 || ARCH_BCM63158 || \ + ARCH_BCM6753) help Select this to enable watchdog timer for BCM6345 SoCs. The watchdog timer is stopped when initialized. |
