summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2022-03-07 16:20:36 -0500
committerTom Rini <[email protected]>2022-03-07 16:20:36 -0500
commit0bf4e0bb935e5c7fc016142e0228882610ecbf39 (patch)
tree4c454f86cbbe76a633a380383ba8635d6f226a71 /drivers
parentfd690a5e932010d0309a859169aeb77af94dff24 (diff)
parent14d8610090fe5aef1b2d0f4d80ec6d4009e61056 (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/Kconfig10
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-aspeed.c299
-rw-r--r--drivers/led/Kconfig7
-rw-r--r--drivers/led/Makefile1
-rw-r--r--drivers/led/led_bcm6753.c270
-rw-r--r--drivers/mmc/omap_hsmmc.c1
-rw-r--r--drivers/mtd/nand/raw/Kconfig6
-rw-r--r--drivers/mtd/nand/raw/brcmnand/Makefile1
-rw-r--r--drivers/mtd/nand/raw/brcmnand/bcm6753_nand.c124
-rw-r--r--drivers/watchdog/Kconfig3
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.