All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/8] Cortina Access Drivers Package 2
@ 2020-03-20  0:57 Alex Nemirovsky
  2020-03-20  0:57 ` [PATCH v2 1/8] mmc: ca_dw_mmc: add DesignWare based DM support for CAxxxx SoCs Alex Nemirovsky
                   ` (7 more replies)
  0 siblings, 8 replies; 18+ messages in thread
From: Alex Nemirovsky @ 2020-03-20  0:57 UTC (permalink / raw)
  To: u-boot


This release adds the following drivers and
integrates support  into the Cortina Access
Presidio Engineering Board:

CAxxxx SoC eMMC/SD controller
CAxxxx SoC I2C controller
CAxxxx Soc LED controller
CAxxxx SPI NAND and NOR controller

Changes in v3:
- Fixup syntax issues related to checkpatch.pl cleanup

Changes in v2:
- Add I2C controller
- Add LED controller
- Add SPI NAND and NOR controller

Alex Nemirovsky (3):
  board: presidio-asic: Add eMMC board support
  board: presidio-asic: Add I2C support
  board: presidio-asic: Add SPI NAND and NOR support

Arthur Li (2):
  mmc: ca_dw_mmc: add DesignWare based DM support for CAxxxx SoCs
  i2c: i2c-cortina: added CAxxxx I2C support

Jway Lin (2):
  led: led_cortina: Add CAxxx LED support
  board: presidio: add LED support

Pengpeng Chen (1):
  spi: ca_sflash: Add CAxxxx SPI Flash Controller

 MAINTAINERS                                      |  10 +
 arch/arm/dts/ca-presidio-engboard.dts            |  39 +-
 board/cortina/presidio-asic/presidio.c           |  16 +-
 configs/cortina_presidio-asic-emmc_defconfig     |  38 ++
 configs/cortina_presidio-asic-spi-nand_defconfig |  48 ++
 configs/cortina_presidio-asic-spi-nor_defconfig  |  59 +++
 drivers/i2c/Kconfig                              |   7 +
 drivers/i2c/Makefile                             |   1 +
 drivers/i2c/i2c-cortina.c                        | 346 ++++++++++++++
 drivers/i2c/i2c-cortina.h                        |  92 ++++
 drivers/led/Kconfig                              |   8 +
 drivers/led/Makefile                             |   1 +
 drivers/led/led_cortina.c                        | 308 ++++++++++++
 drivers/mmc/Kconfig                              |  11 +
 drivers/mmc/Makefile                             |   1 +
 drivers/mmc/ca_dw_mmc.c                          | 181 +++++++
 drivers/spi/Kconfig                              |   8 +
 drivers/spi/Makefile                             |   1 +
 drivers/spi/ca_sflash.c                          | 576 +++++++++++++++++++++++
 19 files changed, 1745 insertions(+), 6 deletions(-)
 create mode 100644 configs/cortina_presidio-asic-emmc_defconfig
 create mode 100644 configs/cortina_presidio-asic-spi-nand_defconfig
 create mode 100644 configs/cortina_presidio-asic-spi-nor_defconfig
 create mode 100644 drivers/i2c/i2c-cortina.c
 create mode 100644 drivers/i2c/i2c-cortina.h
 create mode 100644 drivers/led/led_cortina.c
 create mode 100644 drivers/mmc/ca_dw_mmc.c
 create mode 100644 drivers/spi/ca_sflash.c

-- 
2.7.4

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v2 1/8] mmc: ca_dw_mmc: add DesignWare based DM support for CAxxxx SoCs
  2020-03-20  0:57 [PATCH v2 0/8] Cortina Access Drivers Package 2 Alex Nemirovsky
@ 2020-03-20  0:57 ` Alex Nemirovsky
  2020-03-24  7:16   ` Jaehoon Chung
  2020-03-20  0:57 ` [PATCH v2 2/8] board: presidio-asic: Add eMMC board support Alex Nemirovsky
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 18+ messages in thread
From: Alex Nemirovsky @ 2020-03-20  0:57 UTC (permalink / raw)
  To: u-boot

From: Arthur Li <arthur.li@cortina-access.com>

Initial DesignWare based DM support for Cortina Access CAxxxx SoCs.

Signed-off-by: Arthur Li <arthur.li@cortina-access.com>
Signed-off-by: Alex Nemirovsky <alex.nemirovsky@cortina-access.com>
CC: Peng Fan <peng.fan@nxp.com>

---

Changes in v3: None
Changes in v2:
- Add I2C controller
- Add LED controller
- Add SPI NAND and NOR controller

 MAINTAINERS             |   2 +
 drivers/mmc/Kconfig     |  11 +++
 drivers/mmc/Makefile    |   1 +
 drivers/mmc/ca_dw_mmc.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 195 insertions(+)
 create mode 100644 drivers/mmc/ca_dw_mmc.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 82e4159..bb45d3c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -180,6 +180,7 @@ F:	board/cortina/common/
 F:	drivers/gpio/cortina_gpio.c
 F:	drivers/watchdog/cortina_wdt.c
 F:	drivers/serial/serial_cortina.c
+F:	drivers/mmc/ca_dw_mmc.c
 
 ARM/CZ.NIC TURRIS MOX SUPPORT
 M:	Marek Behun <marek.behun@nic.cz>
@@ -670,6 +671,7 @@ F:	board/cortina/common/
 F:	drivers/gpio/cortina_gpio.c
 F:	drivers/watchdog/cortina_wdt.c
 F:	drivers/serial/serial_cortina.c
+F:	drivers/mmc/ca_dw_mmc.c
 
 MIPS MSCC
 M:	Gregory CLEMENT <gregory.clement@bootlin.com>
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 2f0eedc..bb38787 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -205,6 +205,17 @@ config MMC_DW
 	  block, this provides host support for SD and MMC interfaces, in both
 	  PIO, internal DMA mode and external DMA mode.
 
+config MMC_DW_CORTINA
+	bool "Cortina specific extensions for Synopsys DW Memory Card Interface"
+	depends on DM_MMC
+	depends on MMC_DW
+	depends on BLK
+	default n
+	help
+	  This selects support for Cortina SoC specific extensions to the
+	  Synopsys DesignWare Memory Card Interface driver. Select this option
+	  for platforms based on Cortina CAxxxx Soc's.
+
 config MMC_DW_EXYNOS
 	bool "Exynos specific extensions for Synopsys DW Memory Card Interface"
 	depends on ARCH_EXYNOS
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 9c1f8e5..615b724 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -20,6 +20,7 @@ endif
 obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o
 obj-$(CONFIG_MMC_DAVINCI)		+= davinci_mmc.o
 obj-$(CONFIG_MMC_DW)			+= dw_mmc.o
+obj-$(CONFIG_MMC_DW_CORTINA)		+= ca_dw_mmc.o
 obj-$(CONFIG_MMC_DW_EXYNOS)		+= exynos_dw_mmc.o
 obj-$(CONFIG_MMC_DW_K3)			+= hi6220_dw_mmc.o
 obj-$(CONFIG_MMC_DW_ROCKCHIP)		+= rockchip_dw_mmc.o
diff --git a/drivers/mmc/ca_dw_mmc.c b/drivers/mmc/ca_dw_mmc.c
new file mode 100644
index 0000000..acbc850
--- /dev/null
+++ b/drivers/mmc/ca_dw_mmc.c
@@ -0,0 +1,181 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019 Cortina Access
+ * Arthur Li <arthur.li@cortina-access.com>
+ */
+
+#include <common.h>
+#include <dwmmc.h>
+#include <fdtdec.h>
+#include <linux/libfdt.h>
+#include <malloc.h>
+#include <errno.h>
+#include <dm.h>
+#include <mapmem.h>
+
+#define SD_CLK_SEL_MASK (0x3)
+#define SD_DLL_DEFAULT  (0x143000)
+#define SD_SCLK_MAX (200000000)
+
+#define SD_CLK_SEL_200MHZ (0x2)
+#define SD_CLK_SEL_100MHZ (0x1)
+
+#define IO_DRV_SD_DS_OFFSET (16)
+#define IO_DRV_SD_DS_MASK   (0xff << IO_DRV_SD_DS_OFFSET)
+
+#define MIN_FREQ (400000)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct ca_mmc_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+
+struct ca_dwmmc_priv_data {
+	struct dwmci_host host;
+	void __iomem *sd_dll_reg;
+	void __iomem *io_drv_reg;
+	u8 ds;
+};
+
+static void ca_dwmci_clksel(struct dwmci_host *host)
+{
+	struct ca_dwmmc_priv_data *priv = host->priv;
+	u32 val = readl(priv->sd_dll_reg);
+
+	if (host->bus_hz >= 200000000) {
+		val &= ~SD_CLK_SEL_MASK;
+		val |= SD_CLK_SEL_200MHZ;
+	} else if (host->bus_hz >= 100000000) {
+		val &= ~SD_CLK_SEL_MASK;
+		val |= SD_CLK_SEL_100MHZ;
+	} else {
+		val &= ~SD_CLK_SEL_MASK;
+	}
+
+	writel(val, priv->sd_dll_reg);
+}
+
+static void ca_dwmci_board_init(struct dwmci_host *host)
+{
+	struct ca_dwmmc_priv_data *priv = host->priv;
+	u32 val = readl(priv->io_drv_reg);
+
+	writel(SD_DLL_DEFAULT, priv->sd_dll_reg);
+
+	val &= ~IO_DRV_SD_DS_MASK;
+	if (priv && priv->ds)
+		val |= priv->ds << IO_DRV_SD_DS_OFFSET;
+	writel(val, priv->io_drv_reg);
+}
+
+unsigned int ca_dwmci_get_mmc_clock(struct dwmci_host *host, uint freq)
+{
+	struct ca_dwmmc_priv_data *priv = host->priv;
+	u8 sd_clk_sel = readl(priv->sd_dll_reg) & SD_CLK_SEL_MASK;
+	u8 clk_div;
+
+	switch (sd_clk_sel) {
+	case 2:
+		clk_div = 1;
+		break;
+	case 1:
+		clk_div = 2;
+		break;
+	default:
+		clk_div = 4;
+	}
+
+	return SD_SCLK_MAX / clk_div / (host->div + 1);
+}
+
+static int ca_dwmmc_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ca_dwmmc_priv_data *priv = dev_get_priv(dev);
+	struct dwmci_host *host = &priv->host;
+	u32 tmp;
+
+	host->name = dev->name;
+	host->dev_index = 0;
+
+	host->buswidth = dev_read_u32_default(dev, "bus-width", 1);
+	if (host->buswidth != 1 && host->buswidth != 4)
+		return -EINVAL;
+
+	host->bus_hz = dev_read_u32_default(dev, "max-frequency", 50000000);
+	priv->ds = dev_read_u32_default(dev, "io_ds", 0x33);
+	host->fifo_mode = dev_read_bool(dev, "fifo-mode");
+
+	dev_read_u32(dev, "sd_dll_ctrl", &tmp);
+	priv->sd_dll_reg = map_sysmem((uintptr_t)tmp, sizeof(uintptr_t));
+	if (!priv->sd_dll_reg)
+		return -EINVAL;
+
+	dev_read_u32(dev, "io_drv_ctrl", &tmp);
+	priv->io_drv_reg = map_sysmem((uintptr_t)tmp, sizeof(uintptr_t));
+	if (!priv->io_drv_reg)
+		return -EINVAL;
+
+	host->ioaddr = dev_read_addr_ptr(dev);
+	if (host->ioaddr == (void *)FDT_ADDR_T_NONE) {
+		printf("DWMMC: base address is invalid\n");
+		return -EINVAL;
+	}
+
+	host->priv = priv;
+
+	return 0;
+}
+
+struct dm_mmc_ops ca_dwmci_dm_ops;
+
+static int ca_dwmmc_probe(struct udevice *dev)
+{
+	struct ca_mmc_plat *plat = dev_get_platdata(dev);
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct ca_dwmmc_priv_data *priv = dev_get_priv(dev);
+	struct dwmci_host *host = &priv->host;
+
+	memcpy(&ca_dwmci_dm_ops, &dm_dwmci_ops, sizeof(struct dm_mmc_ops));
+
+	dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, MIN_FREQ);
+	if (host->buswidth == 1) {
+		(&plat->cfg)->host_caps &= ~MMC_MODE_8BIT;
+		(&plat->cfg)->host_caps &= ~MMC_MODE_4BIT;
+	}
+
+	host->mmc = &plat->mmc;
+	host->mmc->priv = &priv->host;
+	upriv->mmc = host->mmc;
+	host->mmc->dev = dev;
+	host->clksel = ca_dwmci_clksel;
+	host->board_init = ca_dwmci_board_init;
+	host->get_mmc_clk = ca_dwmci_get_mmc_clock;
+
+	return dwmci_probe(dev);
+}
+
+static int ca_dwmmc_bind(struct udevice *dev)
+{
+	struct ca_mmc_plat *plat = dev_get_platdata(dev);
+
+	return dwmci_bind(dev, &plat->mmc, &plat->cfg);
+}
+
+static const struct udevice_id ca_dwmmc_ids[] = {
+	{ .compatible = "snps,dw-cortina" },
+	{ }
+};
+
+U_BOOT_DRIVER(ca_dwmmc_drv) = {
+	.name		= "cortina_dwmmc",
+	.id		= UCLASS_MMC,
+	.of_match	= ca_dwmmc_ids,
+	.ofdata_to_platdata = ca_dwmmc_ofdata_to_platdata,
+	.bind		= ca_dwmmc_bind,
+	.ops		= &ca_dwmci_dm_ops,
+	.probe		= ca_dwmmc_probe,
+	.priv_auto_alloc_size	= sizeof(struct ca_dwmmc_priv_data),
+	.platdata_auto_alloc_size = sizeof(struct ca_mmc_plat),
+};
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 2/8] board: presidio-asic: Add eMMC board support
  2020-03-20  0:57 [PATCH v2 0/8] Cortina Access Drivers Package 2 Alex Nemirovsky
  2020-03-20  0:57 ` [PATCH v2 1/8] mmc: ca_dw_mmc: add DesignWare based DM support for CAxxxx SoCs Alex Nemirovsky
@ 2020-03-20  0:57 ` Alex Nemirovsky
  2020-03-20  0:57 ` [PATCH v2 3/8] i2c: i2c-cortina: added CAxxxx I2C support Alex Nemirovsky
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Alex Nemirovsky @ 2020-03-20  0:57 UTC (permalink / raw)
  To: u-boot

Add initial eMMC support for Cortina Access Presidio
Engineering Board

Signed-off-by: Alex Nemirovsky <alex.nemirovsky@cortina-access.com>
CC: Peng Fan <peng.fan@nxp.com>
---

Changes in v3: None
Changes in v2: None

 configs/cortina_presidio-asic-emmc_defconfig | 33 ++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 configs/cortina_presidio-asic-emmc_defconfig

diff --git a/configs/cortina_presidio-asic-emmc_defconfig b/configs/cortina_presidio-asic-emmc_defconfig
new file mode 100644
index 0000000..e10008a
--- /dev/null
+++ b/configs/cortina_presidio-asic-emmc_defconfig
@@ -0,0 +1,33 @@
+CONFIG_ARM=y
+# CONFIG_SYS_ARCH_TIMER is not set
+CONFIG_TARGET_PRESIDIO_ASIC=y
+CONFIG_SYS_TEXT_BASE=0x04000000
+CONFIG_ENV_SIZE=0x20000
+CONFIG_DM_GPIO=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_IDENT_STRING="Presidio-SoC"
+CONFIG_SHOW_BOOT_PROGRESS=y
+CONFIG_BOOTDELAY=3
+CONFIG_BOARD_EARLY_INIT_R=y
+CONFIG_SYS_PROMPT="G3#"
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_WDT=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIMER=y
+CONFIG_CMD_SMC=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_LIVE=y
+CONFIG_DEFAULT_DEVICE_TREE="ca-presidio-engboard"
+# CONFIG_NET is not set
+CONFIG_DM=y
+CONFIG_CORTINA_GPIO=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_CORTINA=y
+CONFIG_DM_SERIAL=y
+CONFIG_CORTINA_UART=y
+CONFIG_WDT=y
+CONFIG_WDT_CORTINA=y
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 3/8] i2c: i2c-cortina: added CAxxxx I2C support
  2020-03-20  0:57 [PATCH v2 0/8] Cortina Access Drivers Package 2 Alex Nemirovsky
  2020-03-20  0:57 ` [PATCH v2 1/8] mmc: ca_dw_mmc: add DesignWare based DM support for CAxxxx SoCs Alex Nemirovsky
  2020-03-20  0:57 ` [PATCH v2 2/8] board: presidio-asic: Add eMMC board support Alex Nemirovsky
@ 2020-03-20  0:57 ` Alex Nemirovsky
  2020-03-20  6:25   ` Heiko Schocher
  2020-03-20  0:57 ` [PATCH v2 4/8] board: presidio-asic: Add " Alex Nemirovsky
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 18+ messages in thread
From: Alex Nemirovsky @ 2020-03-20  0:57 UTC (permalink / raw)
  To: u-boot

From: Arthur Li <arthur.li@cortina-access.com>

Add I2C controller support for Cortina Access CAxxxx SoCs

Signed-off-by: Arthur Li <arthur.li@cortina-access.com>
Signed-off-by: Alex Nemirovsky <alex.nemirovsky@cortina-access.com>
CC: Heiko Schocher <hs@denx.de>
---

Changes in v3: None
Changes in v2: None

 MAINTAINERS               |   4 +
 drivers/i2c/Kconfig       |   7 +
 drivers/i2c/Makefile      |   1 +
 drivers/i2c/i2c-cortina.c | 346 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/i2c-cortina.h |  92 ++++++++++++
 5 files changed, 450 insertions(+)
 create mode 100644 drivers/i2c/i2c-cortina.c
 create mode 100644 drivers/i2c/i2c-cortina.h

diff --git a/MAINTAINERS b/MAINTAINERS
index bb45d3c..b147faa 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -181,6 +181,8 @@ F:	drivers/gpio/cortina_gpio.c
 F:	drivers/watchdog/cortina_wdt.c
 F:	drivers/serial/serial_cortina.c
 F:	drivers/mmc/ca_dw_mmc.c
+F:	drivers/i2c/i2c-cortina.c
+F:	drivers/i2c/i2c-cortina.h
 
 ARM/CZ.NIC TURRIS MOX SUPPORT
 M:	Marek Behun <marek.behun@nic.cz>
@@ -672,6 +674,8 @@ F:	drivers/gpio/cortina_gpio.c
 F:	drivers/watchdog/cortina_wdt.c
 F:	drivers/serial/serial_cortina.c
 F:	drivers/mmc/ca_dw_mmc.c
+F:	drivers/i2c/i2c-cortina.c
+F:	drivers/i2c/i2c-cortina.h
 
 MIPS MSCC
 M:	Gregory CLEMENT <gregory.clement@bootlin.com>
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 03d2fed..b98a4aa 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -85,6 +85,13 @@ config SYS_I2C_CADENCE
 	  Say yes here to select Cadence I2C Host Controller. This controller is
 	  e.g. used by Xilinx Zynq.
 
+config SYS_I2C_CA
+	tristate "Cortina-Access I2C Controller"
+	depends on DM_I2C && CORTINA_PLATFORM
+	default n
+	help
+	  Say yes here to select Cortina-Access I2C Host Controller.
+
 config SYS_I2C_DAVINCI
 	bool "Davinci I2C Controller"
 	depends on (ARCH_KEYSTONE || ARCH_DAVINCI)
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index f5a471f..5d18cf7 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_SYS_I2C) += i2c_core.o
 obj-$(CONFIG_SYS_I2C_ASPEED) += ast_i2c.o
 obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
 obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
+obj-$(CONFIG_SYS_I2C_CA) += i2c-cortina.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
 obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
 ifdef CONFIG_DM_PCI
diff --git a/drivers/i2c/i2c-cortina.c b/drivers/i2c/i2c-cortina.c
new file mode 100644
index 0000000..99c63f3
--- /dev/null
+++ b/drivers/i2c/i2c-cortina.c
@@ -0,0 +1,346 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2020
+ * Arthur Li, Cortina Access, arthur.li at cortina-access.com.
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <dm.h>
+#include <mapmem.h>
+#include "i2c-cortina.h"
+
+static void set_speed(struct i2c_regs *regs, int i2c_spd)
+{
+	union ca_biw_cfg i2c_cfg;
+
+	i2c_cfg.wrd = readl(&regs->i2c_cfg);
+	i2c_cfg.bf.core_en = 0;
+	writel(i2c_cfg.wrd, &regs->i2c_cfg);
+
+	switch (i2c_spd) {
+	case IC_SPEED_MODE_MAX:
+		i2c_cfg.bf.prer =
+			CORTINA_PER_IO_FREQ / (5 * I2C_MAX_SPEED) - 1;
+		break;
+
+	case IC_SPEED_MODE_STANDARD:
+		i2c_cfg.bf.prer =
+			CORTINA_PER_IO_FREQ / (5 * I2C_STANDARD_SPEED) - 1;
+		break;
+
+	case IC_SPEED_MODE_FAST:
+	default:
+		i2c_cfg.bf.prer =
+			CORTINA_PER_IO_FREQ / (5 * I2C_FAST_SPEED) - 1;
+		break;
+	}
+
+	i2c_cfg.bf.core_en = 1;
+	writel(i2c_cfg.wrd, &regs->i2c_cfg);
+}
+
+static int ca_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+{
+	struct ca_i2c *priv = dev_get_priv(bus);
+	int i2c_spd;
+
+	if (speed >= I2C_MAX_SPEED) {
+		i2c_spd = IC_SPEED_MODE_MAX;
+		priv->speed = I2C_MAX_SPEED;
+	} else if (speed >= I2C_FAST_SPEED) {
+		i2c_spd = IC_SPEED_MODE_FAST;
+		priv->speed = I2C_FAST_SPEED;
+	} else {
+		i2c_spd = IC_SPEED_MODE_STANDARD;
+		priv->speed = I2C_STANDARD_SPEED;
+	}
+
+	set_speed(priv->regs, i2c_spd);
+
+	return 0;
+}
+
+static int ca_i2c_get_bus_speed(struct udevice *bus)
+{
+	struct ca_i2c *priv = dev_get_priv(bus);
+
+	return priv->speed;
+}
+
+static void ca_i2c_init(struct i2c_regs *regs)
+{
+	union ca_biw_cfg i2c_cfg;
+
+	i2c_cfg.wrd = readl(&regs->i2c_cfg);
+	i2c_cfg.bf.core_en = 0;
+	i2c_cfg.bf.biw_soft_reset = 1;
+	writel(i2c_cfg.wrd, &regs->i2c_cfg);
+	mdelay(10);
+	i2c_cfg.bf.biw_soft_reset = 0;
+	writel(i2c_cfg.wrd, &regs->i2c_cfg);
+
+	set_speed(regs, IC_SPEED_MODE_STANDARD);
+
+	i2c_cfg.wrd = readl(&regs->i2c_cfg);
+	i2c_cfg.bf.core_en = 1;
+	writel(i2c_cfg.wrd, &regs->i2c_cfg);
+}
+
+static int i2c_wait_complete(struct i2c_regs *regs)
+{
+	union ca_biw_ctrl i2c_ctrl;
+	unsigned long start_time_bb = get_timer(0);
+
+	i2c_ctrl.wrd = readl(&regs->i2c_ctrl);
+
+	while (i2c_ctrl.bf.biwdone == 0) {
+		i2c_ctrl.wrd = readl(&regs->i2c_ctrl);
+
+		if (get_timer(start_time_bb) >
+		   (unsigned long)(I2C_BYTE_TO_BB)) {
+			printf("%s not done!!!\n", __func__);
+			return 1;
+		}
+	}
+
+	/* Clear done bit */
+	writel(i2c_ctrl.wrd, &regs->i2c_ctrl);
+
+	return 0;
+}
+
+static void i2c_setaddress(struct i2c_regs *regs, unsigned int i2c_addr,
+			   int write_read)
+{
+	writel(i2c_addr | write_read, &regs->i2c_txr);
+
+	writel(BIW_CTRL_START | BIW_CTRL_WRITE,
+	       &regs->i2c_ctrl);
+
+	i2c_wait_complete(regs);
+}
+
+static int i2c_wait_for_bus_busy(struct i2c_regs *regs)
+{
+	union ca_biw_ack i2c_ack;
+	unsigned long start_time_bb = get_timer(0);
+
+	i2c_ack.wrd = readl(&regs->i2c_ack);
+
+	while (i2c_ack.bf.biw_busy) {
+		i2c_ack.wrd = readl(&regs->i2c_ack);
+
+		if (get_timer(start_time_bb) >
+		   (unsigned long)(I2C_BYTE_TO_BB)) {
+			printf("%s: timeout!\n", __func__);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static int i2c_xfer_init(struct i2c_regs *regs, uint8_t chip, uint addr,
+			 int alen, int write_read)
+{
+	int addr_len = alen;
+
+	if (i2c_wait_for_bus_busy(regs))
+		return 1;
+	/* First cycle must write addr + offset */
+	chip = ((chip & 0x7F) << 1);
+	if (alen == 0 && write_read == I2C_CMD_RD)
+		i2c_setaddress(regs, chip, I2C_CMD_RD);
+	else
+		i2c_setaddress(regs, chip, I2C_CMD_WT);
+
+	while (alen) {
+		alen--;
+		writel(addr, &regs->i2c_txr);
+		if (write_read == I2C_CMD_RD)
+			writel(BIW_CTRL_WRITE | BIW_CTRL_STOP,
+			       &regs->i2c_ctrl);
+		else
+			writel(BIW_CTRL_WRITE, &regs->i2c_ctrl);
+		i2c_wait_complete(regs);
+	}
+
+	/* Send address again with Read flag if it's read command */
+	if (write_read == I2C_CMD_RD && addr_len > 0)
+		i2c_setaddress(regs, chip, I2C_CMD_RD);
+
+	return 0;
+}
+
+static int i2c_xfer_finish(struct i2c_regs *regs)
+{
+	/* Dummy read makes bus free */
+	writel(BIW_CTRL_READ | BIW_CTRL_STOP, &regs->i2c_ctrl);
+	i2c_wait_complete(regs);
+
+	if (i2c_wait_for_bus_busy(regs)) {
+		printf("Timed out waiting for bus\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+static int ca_i2c_read(struct i2c_regs *regs, uint8_t chip, uint addr,
+		       int alen, uint8_t *buffer, int len)
+{
+	unsigned long start_time_rx;
+	int rc = 0;
+
+	if (i2c_xfer_init(regs, chip, addr, alen, I2C_CMD_RD))
+		return 1;
+
+	start_time_rx = get_timer(0);
+	while (len) {
+		/* ACK_IN is ack value to send during read.
+		 * ack high only on the very last byte!
+		 */
+		if (len == 1) {
+			writel(BIW_CTRL_READ | BIW_CTRL_ACK_IN | BIW_CTRL_STOP,
+			       &regs->i2c_ctrl);
+		} else {
+			writel(BIW_CTRL_READ, &regs->i2c_ctrl);
+		}
+
+		rc = i2c_wait_complete(regs);
+		udelay(1);
+
+		if (rc == 0) {
+			*buffer++ =
+				(uchar) readl(&regs->i2c_rxr);
+			len--;
+			start_time_rx = get_timer(0);
+
+		} else if (get_timer(start_time_rx) > I2C_BYTE_TO) {
+			return 1;
+		}
+	}
+	i2c_xfer_finish(regs);
+	return rc;
+}
+
+static int ca_i2c_write(struct i2c_regs *regs, uint8_t chip, uint addr,
+			int alen, uint8_t *buffer, int len)
+{
+	int rc, nb = len;
+	unsigned long start_time_tx;
+
+	if (i2c_xfer_init(regs, chip, addr, alen, I2C_CMD_WT))
+		return 1;
+
+	start_time_tx = get_timer(0);
+	while (len) {
+		writel(*buffer, &regs->i2c_txr);
+		if (len == 1) {
+			writel(BIW_CTRL_WRITE | BIW_CTRL_STOP,
+			       &regs->i2c_ctrl);
+		} else {
+			writel(BIW_CTRL_WRITE, &regs->i2c_ctrl);
+		}
+
+		rc = i2c_wait_complete(regs);
+
+		if (rc == 0) {
+			len--;
+			buffer++;
+			start_time_tx = get_timer(0);
+		} else if (get_timer(start_time_tx) > (nb * I2C_BYTE_TO)) {
+			printf("Timed out. i2c write Failed\n");
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static int ca_i2c_probe_chip(struct udevice *bus, uint chip_addr,
+			     uint chip_flags)
+{
+	struct ca_i2c *priv = dev_get_priv(bus);
+	int ret;
+	u32 tmp;
+
+	/* Try to read the first location of the chip */
+	ret = ca_i2c_read(priv->regs, chip_addr, 0, 1, (uchar *)&tmp, 1);
+	if (ret)
+		ca_i2c_init(priv->regs);
+
+	return ret;
+}
+
+static int ca_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
+{
+	struct ca_i2c *priv = dev_get_priv(bus);
+	int ret;
+
+	debug("i2c_xfer: %d messages\n", nmsgs);
+	for (; nmsgs > 0; nmsgs--, msg++) {
+		debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
+		if (msg->flags & I2C_M_RD) {
+			ret = ca_i2c_read(priv->regs, msg->addr, 0, 0,
+					  msg->buf, msg->len);
+		} else {
+			ret = ca_i2c_write(priv->regs, msg->addr, 0, 0,
+					   msg->buf, msg->len);
+		}
+
+		if (ret) {
+			debug("i2c_write: error sending\n");
+			return -EREMOTEIO;
+		}
+	}
+
+	return 0;
+}
+
+static const struct dm_i2c_ops ca_i2c_ops = {
+	.xfer		= ca_i2c_xfer,
+	.probe_chip	= ca_i2c_probe_chip,
+	.set_bus_speed	= ca_i2c_set_bus_speed,
+	.get_bus_speed	= ca_i2c_get_bus_speed,
+};
+
+static const struct udevice_id ca_i2c_ids[] = {
+	{ .compatible = "cortina,ca-i2c", },
+	{ }
+};
+
+static int ca_i2c_probe(struct udevice *bus)
+{
+	struct ca_i2c *priv = dev_get_priv(bus);
+
+	ca_i2c_init(priv->regs);
+
+	return 0;
+}
+
+static int ca_i2c_ofdata_to_platdata(struct udevice *bus)
+{
+	struct ca_i2c *priv = dev_get_priv(bus);
+
+	priv->regs = map_sysmem(dev_read_addr(bus), sizeof(struct i2c_regs));
+	if (!priv->regs) {
+		printf("I2C: base address is invalid\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+U_BOOT_DRIVER(i2c_cortina) = {
+	.name	= "i2c_cortina",
+	.id	= UCLASS_I2C,
+	.of_match = ca_i2c_ids,
+	.ofdata_to_platdata = ca_i2c_ofdata_to_platdata,
+	.probe	= ca_i2c_probe,
+	.priv_auto_alloc_size = sizeof(struct ca_i2c),
+	.ops	= &ca_i2c_ops,
+	.flags  = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/i2c/i2c-cortina.h b/drivers/i2c/i2c-cortina.h
new file mode 100644
index 0000000..f1c3dc7
--- /dev/null
+++ b/drivers/i2c/i2c-cortina.h
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2019
+ * Cortina Access, <www.cortina-access.com>
+ */
+
+#ifndef __CA_I2C_H_
+#define __CA_I2C_H_
+
+#if !defined(__ASSEMBLER__) && !defined(__ASSEMBLY__)
+struct i2c_regs {
+	u32 i2c_cfg;
+	u32 i2c_ctrl;
+	u32 i2c_txr;
+	u32 i2c_rxr;
+	u32 i2c_ack;
+	u32 i2c_ie0;
+	u32 i2c_int0;
+	u32 i2c_ie1;
+	u32 i2c_int1;
+	u32 i2c_stat;
+};
+
+union ca_biw_cfg {
+	struct biw_cfg {
+		u32 core_en		: 1;
+		u32 biw_soft_reset	: 1;
+		u32 busywait_en		: 1;
+		u32 stretch_en		: 1;
+		u32 arb_en		: 1;
+		u32 clksync_en		: 1;
+		u32 rsrvd1		: 2;
+		u32 spike_cnt		: 4;
+		u32 rsrvd2		: 4;
+		u32 prer		: 16;
+	} bf;
+	unsigned int wrd;
+};
+
+union ca_biw_ctrl {
+	struct biw_ctrl {
+		u32 biwdone	: 1;
+		u32 rsrvd1	: 2;
+		u32 ack_in	: 1;
+		u32 write	: 1;
+		u32 read	: 1;
+		u32 stop	: 1;
+		u32 start	: 1;
+		u32 rsrvd2	: 24;
+	} bf;
+	unsigned int wrd;
+};
+
+union ca_biw_ack {
+	struct biw_ack {
+		u32 al		:1;
+		u32 biw_busy	:1;
+		u32 ack_out	:1;
+		u32 rsrvd1	:29;
+	} bf;
+	unsigned int wrd;
+};
+#endif /* !__ASSEMBLER__*/
+
+struct ca_i2c {
+	struct i2c_regs *regs;
+	unsigned int speed;
+};
+
+#define I2C_CMD_WT			0
+#define I2C_CMD_RD			1
+
+#define BIW_CTRL_DONE		BIT(0)
+#define BIW_CTRL_ACK_IN		BIT(3)
+#define BIW_CTRL_WRITE		BIT(4)
+#define BIW_CTRL_READ		BIT(5)
+#define BIW_CTRL_STOP		BIT(6)
+#define BIW_CTRL_START		BIT(7)
+
+#define I2C_BYTE_TO		(CONFIG_SYS_HZ / 500)
+#define I2C_STOPDET_TO		(CONFIG_SYS_HZ / 500)
+#define I2C_BYTE_TO_BB		(10)
+
+#define IC_SPEED_MODE_STANDARD	1
+#define IC_SPEED_MODE_FAST	2
+#define IC_SPEED_MODE_MAX	3
+
+#define I2C_MAX_SPEED		1000000
+#define I2C_FAST_SPEED		400000
+#define I2C_STANDARD_SPEED	100000
+
+#endif							/* __CA_I2C_H_ */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 4/8] board: presidio-asic: Add I2C support
  2020-03-20  0:57 [PATCH v2 0/8] Cortina Access Drivers Package 2 Alex Nemirovsky
                   ` (2 preceding siblings ...)
  2020-03-20  0:57 ` [PATCH v2 3/8] i2c: i2c-cortina: added CAxxxx I2C support Alex Nemirovsky
@ 2020-03-20  0:57 ` Alex Nemirovsky
  2020-03-20  0:57 ` [PATCH v2 5/8] led: led_cortina: Add CAxxx LED support Alex Nemirovsky
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Alex Nemirovsky @ 2020-03-20  0:57 UTC (permalink / raw)
  To: u-boot

Add I2C board support for Cortina Access Presidio Engineering Board

Signed-off-by: Alex Nemirovsky <alex.nemirovsky@cortina-access.com>
CC: Heiko Schocher <hs@denx.de>
---

Changes in v3: None
Changes in v2: None

 configs/cortina_presidio-asic-emmc_defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/configs/cortina_presidio-asic-emmc_defconfig b/configs/cortina_presidio-asic-emmc_defconfig
index e10008a..e45e23c 100644
--- a/configs/cortina_presidio-asic-emmc_defconfig
+++ b/configs/cortina_presidio-asic-emmc_defconfig
@@ -10,6 +10,7 @@ CONFIG_SHOW_BOOT_PROGRESS=y
 CONFIG_BOOTDELAY=3
 CONFIG_BOARD_EARLY_INIT_R=y
 CONFIG_SYS_PROMPT="G3#"
+CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_PART=y
 CONFIG_CMD_WDT=y
@@ -24,6 +25,8 @@ CONFIG_DEFAULT_DEVICE_TREE="ca-presidio-engboard"
 # CONFIG_NET is not set
 CONFIG_DM=y
 CONFIG_CORTINA_GPIO=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_CA=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_CORTINA=y
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 5/8] led: led_cortina: Add CAxxx LED support
  2020-03-20  0:57 [PATCH v2 0/8] Cortina Access Drivers Package 2 Alex Nemirovsky
                   ` (3 preceding siblings ...)
  2020-03-20  0:57 ` [PATCH v2 4/8] board: presidio-asic: Add " Alex Nemirovsky
@ 2020-03-20  0:57 ` Alex Nemirovsky
  2020-03-23 15:37   ` Simon Glass
  2020-03-20  0:57 ` [PATCH v2 6/8] board: presidio: add " Alex Nemirovsky
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 18+ messages in thread
From: Alex Nemirovsky @ 2020-03-20  0:57 UTC (permalink / raw)
  To: u-boot

From: Jway Lin <jway.lin@cortina-access.com>

Add Cortina Access LED controller support for CAxxxx SOCs

Signed-off-by: Jway Lin <jway.lin@cortina-access.com>
Signed-off-by: Alex Nemirovsky <alex.nemirovsky@cortina-access.com>
CC: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 MAINTAINERS               |   2 +
 drivers/led/Kconfig       |   8 ++
 drivers/led/Makefile      |   1 +
 drivers/led/led_cortina.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 319 insertions(+)
 create mode 100644 drivers/led/led_cortina.c

diff --git a/MAINTAINERS b/MAINTAINERS
index b147faa..24a2655 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -183,6 +183,7 @@ F:	drivers/serial/serial_cortina.c
 F:	drivers/mmc/ca_dw_mmc.c
 F:	drivers/i2c/i2c-cortina.c
 F:	drivers/i2c/i2c-cortina.h
+F:	drivers/led/led_cortina.c
 
 ARM/CZ.NIC TURRIS MOX SUPPORT
 M:	Marek Behun <marek.behun@nic.cz>
@@ -676,6 +677,7 @@ F:	drivers/serial/serial_cortina.c
 F:	drivers/mmc/ca_dw_mmc.c
 F:	drivers/i2c/i2c-cortina.c
 F:	drivers/i2c/i2c-cortina.h
+F:	drivers/led/led_cortina.c
 
 MIPS MSCC
 M:	Gregory CLEMENT <gregory.clement@bootlin.com>
diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig
index 6675934..cc87fbf 100644
--- a/drivers/led/Kconfig
+++ b/drivers/led/Kconfig
@@ -35,6 +35,14 @@ config LED_BCM6858
 	  This option enables support for LEDs connected to the BCM6858
 	  HW has blinking capabilities and up to 32 LEDs can be controlled.
 
+config LED_CORTINA
+	bool "LED Support for Cortina Access CAxxxx SoCs"
+	depends on LED && (CORTINA_PLATFORM)
+	help
+	  This option enables support for LEDs connected to the Cortina
+	  Access CAxxxx SOCs.
+
+
 config LED_BLINK
 	bool "Support LED blinking"
 	depends on LED
diff --git a/drivers/led/Makefile b/drivers/led/Makefile
index 3654dd3..8e3ae7f 100644
--- a/drivers/led/Makefile
+++ b/drivers/led/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_LED_BCM6328) += led_bcm6328.o
 obj-$(CONFIG_LED_BCM6358) += led_bcm6358.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_cortina.c b/drivers/led/led_cortina.c
new file mode 100644
index 0000000..53435e8
--- /dev/null
+++ b/drivers/led/led_cortina.c
@@ -0,0 +1,308 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Copyright (C) 2020 Cortina-Access
+ * Author: Jway Lin <jway.lin@cortina-access.com>
+ *
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <led.h>
+#include <asm/io.h>
+#include <dm/lists.h>
+#include <linux/compat.h>
+
+#define CORTINA_LED_NUM	16
+
+#define BIT(nr)			(1UL << (nr))
+
+#define cortina_LED_CONTROL			0x00
+#define cortina_LED_CONFIG_0		0x04
+#define cortina_LED_CONFIG_1		0x08
+#define cortina_LED_CONFIG_2		0x0c
+#define cortina_LED_CONFIG_3		0x10
+#define cortina_LED_CONFIG_4		0x14
+#define cortina_LED_CONFIG_5		0x18
+#define cortina_LED_CONFIG_6		0x1c
+#define cortina_LED_CONFIG_7		0x20
+#define cortina_LED_CONFIG_8		0x24
+#define cortina_LED_CONFIG_9		0x28
+#define cortina_LED_CONFIG_10		0x2c
+#define cortina_LED_CONFIG_11		0x30
+#define cortina_LED_CONFIG_12		0x34
+#define cortina_LED_CONFIG_13		0x38
+#define cortina_LED_CONFIG_14		0x3c
+#define cortina_LED_CONFIG_15		0x40
+
+#define cortina_LED_MAX_HW_BLINK		127
+#define cortina_LED_MAX_COUNT		CORTINA_LED_NUM
+#define cortina_LED_MAX_PORT		8
+
+/* LED_CONTROL fields */
+#define cortina_LED_BLINK_RATE1_OFFSET	0
+#define cortina_LED_BLINK_RATE1_MASK	0xFF
+#define cortina_LED_BLINK_RATE2_OFFSET	8
+#define cortina_LED_BLINK_RATE2_MASK	0xFF
+#define cortina_LED_CLK_TEST		BIT(16)
+#define cortina_LED_CLK_POLARITY		BIT(17)
+#define cortina_LED_CLK_TEST_MODE	BIT(16)
+#define cortina_LED_CLK_TEST_RX_TEST	BIT(30)
+#define cortina_LED_CLK_TEST_TX_TEST	BIT(31)
+
+/* LED_CONFIG fields */
+#define cortina_LED_EVENT_ON_OFFSET	0
+#define cortina_LED_EVENT_ON_MASK	0x7
+#define cortina_LED_EVENT_BLINK_OFFSET	3
+#define cortina_LED_EVENT_BLINK_MASK	0x7
+#define cortina_LED_EVENT_OFF_OFFSET	6
+#define cortina_LED_EVENT_OFF_MASK	0x7
+#define cortina_LED_OFF_ON_OFFSET	9
+#define cortina_LED_OFF_ON_MASK		0x3
+#define cortina_LED_PORT_OFFSET		11
+#define cortina_LED_PORT_MASK		0x7
+#define cortina_LED_OFF_VAL		BIT(14)
+#define cortina_LED_SW_EVENT		BIT(15)
+#define cortina_LED_BLINK_SEL		BIT(16)
+
+struct cortina_led_cfg {
+	void __iomem *regs;
+	spinlock_t *lock;	/* protect LED resource access */
+	int idx;
+	bool active_low;
+
+	int off_event;
+	int blink_event;
+	int on_event;
+	int port;
+	int blink;
+	int enable;
+};
+
+struct cortina_led_top_cfg {
+	void __iomem *regs;
+	u16 blink_rate1;
+	u16 blink_rate2;
+};
+
+static struct cortina_led_top_cfg glb_led_ctrl;
+
+static void cortina_led_write(void __iomem *reg, unsigned long data)
+{
+	writel(data, reg);
+}
+
+static unsigned long cortina_led_read(void __iomem *reg)
+{
+	return readl(reg);
+}
+
+static enum led_state_t cortina_led_get_state(struct udevice *dev)
+{
+	struct cortina_led_cfg *priv = dev_get_priv(dev);
+	enum led_state_t state = LEDST_OFF;
+	u32 val;
+
+	val = readl(priv->regs);
+
+	if (val & cortina_LED_SW_EVENT)
+		state = LEDST_ON;
+
+	return state;
+}
+
+static int cortina_led_set_state(struct udevice *dev, enum led_state_t state)
+{
+	u32 val;
+	struct cortina_led_cfg *priv = dev_get_priv(dev);
+
+	val = readl(priv->regs);
+
+	switch (state) {
+	case LEDST_OFF:
+		val &= ~cortina_LED_SW_EVENT;
+		val &= ~(cortina_LED_OFF_ON_MASK << cortina_LED_OFF_ON_OFFSET);
+		val |= 0x3 << cortina_LED_OFF_ON_OFFSET;
+		cortina_led_write(priv->regs, val);
+		break;
+	case LEDST_ON:
+		val |= cortina_LED_SW_EVENT;
+		val &= ~(cortina_LED_OFF_ON_MASK << cortina_LED_OFF_ON_OFFSET);
+		val |= 0x1 << cortina_LED_OFF_ON_OFFSET;
+		cortina_led_write(priv->regs, val);
+		break;
+	case LEDST_TOGGLE:
+		if (cortina_led_get_state(dev) == LEDST_OFF)
+			return cortina_led_set_state(dev, LEDST_ON);
+		else
+			return cortina_led_set_state(dev, LEDST_OFF);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct led_ops cortina_led_ops = {
+	.get_state = cortina_led_get_state,
+	.set_state = cortina_led_set_state,
+};
+
+static int cortina_led_probe(struct udevice *dev)
+{
+	struct led_uc_plat *uc_plat = dev_get_uclass_platdata(dev);
+	void __iomem *regs;
+	u32 reg_value, val;
+	u16 rate1, rate2;
+	struct cortina_led_cfg *priv = dev_get_priv(dev);
+	unsigned int pin;
+	u32 blink, port, off_event, blink_event, on_event;
+
+	/* Top-level LED node */
+	if (!uc_plat->label) {
+		regs = dev_remap_addr(dev);
+
+	if (!regs)
+		return -EINVAL;
+
+	glb_led_ctrl.regs = regs;
+
+	reg_value = 0;
+	reg_value |= cortina_LED_CLK_POLARITY;
+
+	rate1 = dev_read_u32_default(dev, "cortina, blink_rate1", 256);
+	rate2 = dev_read_u32_default(dev, "cortina, blink_rate2", 512);
+
+	val = rate1 / 16 - 1;
+	glb_led_ctrl.blink_rate1 = val > cortina_LED_MAX_HW_BLINK ?
+			    cortina_LED_MAX_HW_BLINK : val;
+	reg_value |= (glb_led_ctrl.blink_rate1 & cortina_LED_BLINK_RATE1_MASK)
+			<< cortina_LED_BLINK_RATE1_OFFSET;
+
+	val = rate2 / 16 - 1;
+	glb_led_ctrl.blink_rate2 = val > cortina_LED_MAX_HW_BLINK ?
+				cortina_LED_MAX_HW_BLINK : val;
+	reg_value |= (glb_led_ctrl.blink_rate2 & cortina_LED_BLINK_RATE2_MASK)
+			<< cortina_LED_BLINK_RATE2_OFFSET;
+
+	cortina_led_write(glb_led_ctrl.regs, reg_value);
+	} else {
+		regs = dev_remap_addr(dev_get_parent(dev));
+
+	if (!regs)
+		return -EINVAL;
+
+	pin = dev_read_u32_default(dev, "pin", cortina_LED_MAX_COUNT);
+
+	if (pin >= cortina_LED_MAX_COUNT)
+		return -EINVAL;
+
+	priv->regs = regs + 4 + (pin * 4);
+
+	val = cortina_led_read(priv->regs);
+
+	if (dev_read_bool(dev, "active-low")) {
+		priv->active_low = true;
+		val |= cortina_LED_OFF_VAL;
+	} else {
+		priv->active_low = false;
+		val &= ~cortina_LED_OFF_VAL;
+	}
+
+	blink = dev_read_u32_default(dev, "blink-sel", 0);
+
+	if (blink == 0) {
+		priv->blink = 0;
+		val &= ~cortina_LED_BLINK_SEL;
+	} else if (blink == 1) {
+		priv->blink = 1;
+		val |= cortina_LED_BLINK_SEL;
+	}
+
+	//Todo : cortina_led_config();
+	off_event = dev_read_u32_default(dev, "off-event", 3);
+	val &= ~(cortina_LED_EVENT_OFF_MASK << cortina_LED_EVENT_OFF_OFFSET);
+	if (off_event != 3) {
+		priv->off_event = off_event;
+		val |= BIT(off_event) << cortina_LED_EVENT_OFF_OFFSET;
+	}
+
+	blink_event = dev_read_u32_default(dev, "blink-event", 3);
+	val &= ~(cortina_LED_EVENT_BLINK_MASK <<
+		 cortina_LED_EVENT_BLINK_OFFSET);
+
+	if (blink_event != 3) {
+		priv->blink_event = blink_event;
+		val |= BIT(blink_event) << cortina_LED_EVENT_BLINK_OFFSET;
+	}
+
+	on_event = dev_read_u32_default(dev, "on-event", 3);
+	val &= ~(cortina_LED_EVENT_ON_MASK << cortina_LED_EVENT_ON_OFFSET);
+	if (on_event != 3) {
+		priv->on_event = on_event;
+		val |= BIT(on_event) << cortina_LED_EVENT_ON_OFFSET;
+	}
+
+	port = dev_read_u32_default(dev, "port", 0);
+	priv->port = port;
+	val &= ~(cortina_LED_PORT_MASK << cortina_LED_PORT_OFFSET);
+	val |= port << cortina_LED_PORT_OFFSET;
+
+	priv->enable = 0;
+
+	/* force off */
+	val &= ~(cortina_LED_OFF_ON_MASK << cortina_LED_OFF_ON_OFFSET);
+	val |= 0x3 << cortina_LED_OFF_ON_OFFSET;
+
+	cortina_led_write(priv->regs, val);
+	}
+
+	return 0;
+}
+
+static int cortina_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, "ca-leds",
+						 ofnode_get_name(node),
+						 node, &dev);
+		if (ret)
+			return ret;
+		uc_plat = dev_get_uclass_platdata(dev);
+		uc_plat->label = label;
+	}
+
+	return 0;
+}
+
+static const struct udevice_id ca_led_ids[] = {
+	{ .compatible = "cortina,ca-leds" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(cortina_led) = {
+	.name = "ca-leds",
+	.id = UCLASS_LED,
+	.of_match = ca_led_ids,
+	.bind = cortina_led_bind,
+	.probe = cortina_led_probe,
+	.priv_auto_alloc_size = sizeof(struct cortina_led_cfg),
+	.ops = &cortina_led_ops,
+};
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 6/8] board: presidio: add LED support
  2020-03-20  0:57 [PATCH v2 0/8] Cortina Access Drivers Package 2 Alex Nemirovsky
                   ` (4 preceding siblings ...)
  2020-03-20  0:57 ` [PATCH v2 5/8] led: led_cortina: Add CAxxx LED support Alex Nemirovsky
@ 2020-03-20  0:57 ` Alex Nemirovsky
  2020-03-23 15:37   ` Simon Glass
  2020-03-20  0:57 ` [PATCH v2 7/8] spi: ca_sflash: Add CAxxxx SPI Flash Controller Alex Nemirovsky
  2020-03-20  0:57 ` [PATCH v2 8/8] board: presidio-asic: Add SPI NAND and NOR support Alex Nemirovsky
  7 siblings, 1 reply; 18+ messages in thread
From: Alex Nemirovsky @ 2020-03-20  0:57 UTC (permalink / raw)
  To: u-boot

From: Jway Lin <jway.lin@cortina-access.com>

Add LED support for Cortina Access Presidio Engineering Board

Signed-off-by: Jway Lin <jway.lin@cortina-access.com>
Signed-off-by: Alex Nemirovsky <alex.nemirovsky@cortina-access.com>
CC: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 arch/arm/dts/ca-presidio-engboard.dts        | 31 ++++++++++++++++++++++++++++
 configs/cortina_presidio-asic-emmc_defconfig |  2 ++
 2 files changed, 33 insertions(+)

diff --git a/arch/arm/dts/ca-presidio-engboard.dts b/arch/arm/dts/ca-presidio-engboard.dts
index c03dacc..ae897e8 100644
--- a/arch/arm/dts/ca-presidio-engboard.dts
+++ b/arch/arm/dts/ca-presidio-engboard.dts
@@ -66,4 +66,35 @@
 			spi-max-frequency = <108000000>;
 		};
 	};
+
+	leds: led-controller at f43200f0 {
+		compatible = "cortina,ca-leds";
+		reg = <0x0 0xf43200f0 0x40>;
+
+		cortina,blink_rate1 = <256>;
+		cortina,blink_rate2 = <512>;
+
+		led at 0 {
+			pin = <0>;
+			active-low;
+			blink-sel =<0>;
+			port = <0>;
+			off-event = <0>;
+			label = "led0";
+		};
+
+		led at 1 {
+			pin = <1>;
+			active-low;
+			blink-sel =<1>;
+			label = "led1";
+		};
+
+		led at 2 {
+			pin = <2>;
+			active-low;
+			label = "led2";
+		};
+
+	};
 };
diff --git a/configs/cortina_presidio-asic-emmc_defconfig b/configs/cortina_presidio-asic-emmc_defconfig
index e45e23c..3c6bd6b 100644
--- a/configs/cortina_presidio-asic-emmc_defconfig
+++ b/configs/cortina_presidio-asic-emmc_defconfig
@@ -27,6 +27,8 @@ CONFIG_DM=y
 CONFIG_CORTINA_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_CA=y
+CONFIG_LED=y
+CONFIG_LED_CORTINA=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_CORTINA=y
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 7/8] spi: ca_sflash: Add CAxxxx SPI Flash Controller
  2020-03-20  0:57 [PATCH v2 0/8] Cortina Access Drivers Package 2 Alex Nemirovsky
                   ` (5 preceding siblings ...)
  2020-03-20  0:57 ` [PATCH v2 6/8] board: presidio: add " Alex Nemirovsky
@ 2020-03-20  0:57 ` Alex Nemirovsky
  2020-03-20  0:57 ` [PATCH v2 8/8] board: presidio-asic: Add SPI NAND and NOR support Alex Nemirovsky
  7 siblings, 0 replies; 18+ messages in thread
From: Alex Nemirovsky @ 2020-03-20  0:57 UTC (permalink / raw)
  To: u-boot

From: Pengpeng Chen <pengpeng.chen@cortina-access.com>

Add SPI Flash controller driver for Cortina Access
CAxxxx SoCs

Signed-off-by: Pengpeng Chen <pengpeng.chen@cortina-access.com>
Signed-off-by: Alex Nemirovsky <alex.nemirovsky@cortina-access.com>
CC: Jagan Teki <jagan@amarulasolutions.com>

---

Changes in v3:
- Fixup syntax issues related to checkpatch.pl cleanup

Changes in v2: None

 MAINTAINERS             |   2 +
 drivers/spi/Kconfig     |   8 +
 drivers/spi/Makefile    |   1 +
 drivers/spi/ca_sflash.c | 576 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 587 insertions(+)
 create mode 100644 drivers/spi/ca_sflash.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 24a2655..8509779 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -184,6 +184,7 @@ F:	drivers/mmc/ca_dw_mmc.c
 F:	drivers/i2c/i2c-cortina.c
 F:	drivers/i2c/i2c-cortina.h
 F:	drivers/led/led_cortina.c
+F:	drivers/spi/ca_sflash.c
 
 ARM/CZ.NIC TURRIS MOX SUPPORT
 M:	Marek Behun <marek.behun@nic.cz>
@@ -678,6 +679,7 @@ F:	drivers/mmc/ca_dw_mmc.c
 F:	drivers/i2c/i2c-cortina.c
 F:	drivers/i2c/i2c-cortina.h
 F:	drivers/led/led_cortina.c
+F:	drivers/spi/ca_sflash.c
 
 MIPS MSCC
 M:	Gregory CLEMENT <gregory.clement@bootlin.com>
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 4166c61..8a244f1 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -106,6 +106,14 @@ config BCMSTB_SPI
 	  be used to access the SPI flash on platforms embedding this
 	  Broadcom SPI core.
 
+config CORTINA_SFLASH
+	bool "Cortina-Access Serial Flash controller driver"
+	depends on DM_SPI && SPI_MEM
+	help
+	  Enable the Cortina-Access Serial Flash controller driver. This driver
+	  can be used to access the SPI NOR/NAND flash on platforms embedding this
+	  Cortina-Access IP core.
+
 config CADENCE_QSPI
 	bool "Cadence QSPI driver"
 	help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 52462e1..32b98b4 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o
 obj-$(CONFIG_BCMSTB_SPI) += bcmstb_spi.o
 obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
 obj-$(CONFIG_CF_SPI) += cf_spi.o
+obj-$(CONFIG_CORTINA_SFLASH) += ca_sflash.o
 obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
 obj-$(CONFIG_DESIGNWARE_SPI) += designware_spi.o
 obj-$(CONFIG_EXYNOS_SPI) += exynos_spi.o
diff --git a/drivers/spi/ca_sflash.c b/drivers/spi/ca_sflash.c
new file mode 100644
index 0000000..0709650
--- /dev/null
+++ b/drivers/spi/ca_sflash.c
@@ -0,0 +1,576 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver for Cortina SPI-FLASH Controller
+ *
+ * Copyright (C) 2020 Cortina Access Inc. All Rights Reserved.
+ *
+ * Author: PengPeng Chen <pengpeng.chen@cortina-access.com>
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <linux/compat.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
+#include <linux/sizes.h>
+#include <spi.h>
+#include <spi-mem.h>
+#include <reset.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct ca_sflash_regs {
+	u32 idr;		/* 0x00:Flash word ID Register */
+	u32 tc;			/* 0x04:Flash Timeout Counter Register */
+	u32 sr;			/* 0x08:Flash Status Register */
+	u32 tr;			/* 0x0C:Flash Type Register */
+	u32 asr;		/* 0x10:Flash ACCESS START/BUSY Register */
+	u32 isr;		/* 0x14:Flash Interrupt Status Register */
+	u32 imr;		/* 0x18:Flash Interrupt Mask Register */
+	u32 fcr;		/* 0x1C:NAND Flash FIFO Control Register */
+	u32 ffsr;		/* 0x20:Flash FIFO Status Register */
+	u32 ffar;		/* 0x24:Flash FIFO ADDRESS Register */
+	u32 ffmar;		/* 0x28:Flash FIFO MATCHING ADDRESS Register */
+	u32 ffdr;		/* 0x2C:Flash FIFO Data Register */
+	u32 ar;			/* 0x30:Serial Flash Access Register */
+	u32 ear;		/* 0x34:Serial Flash Extend Access Register */
+	u32 adr;		/* 0x38:Serial Flash ADdress Register */
+	u32 dr;			/* 0x3C:Serial Flash Data Register */
+	u32 tmr;		/* 0x40:Serial Flash Timing Register */
+};
+
+/*
+ * FLASH_TYPE
+ */
+#define CA_FLASH_TR_PIN			BIT(15)
+#define CA_FLASH_TR_TYPE_MASK		GENMASK(14, 12)
+#define CA_FLASH_TR_TYPE(tp)		(((tp) << 12) & CA_FLASH_TR_TYPE_MASK)
+#define CA_FLASH_TR_WIDTH			BIT(11)
+#define CA_FLASH_TR_SIZE_MASK		GENMASK(10, 9)
+#define CA_FLASH_TR_SIZE(sz)		(((sz) << 9) & CA_FLASH_TR_SIZE_MASK)
+
+/*
+ * FLASH_FLASH_ACCESS_START
+ */
+#define CA_FLASH_ASR_IND_START_EN	BIT(1)
+#define CA_FLASH_ASR_DMA_START_EN	BIT(3)
+#define CA_FLASH_ASR_WR_ACCESS_EN	BIT(9)
+
+/*
+ * FLASH_FLASH_INTERRUPT
+ */
+#define CA_FLASH_ISR_REG_IRQ		BIT(1)
+#define CA_FLASH_ISR_FIFO_IRQ		BIT(2)
+
+/*
+ * FLASH_SF_ACCESS
+ */
+#define CA_SF_AR_OPCODE_MASK		GENMASK(7, 0)
+#define CA_SF_AR_OPCODE(op)		((op) << 0 & CA_SF_AR_OPCODE_MASK)
+#define CA_SF_AR_ACCODE_MASK		GENMASK(11, 8)
+#define CA_SF_AR_ACCODE(ac)		(((ac) << 8) & CA_SF_AR_ACCODE_MASK)
+#define CA_SF_AR_FORCE_TERM		BIT(12)
+#define CA_SF_AR_FORCE_BURST		BIT(13)
+#define CA_SF_AR_AUTO_MODE_EN		BIT(15)
+#define CA_SF_AR_CHIP_EN_ALT		BIT(16)
+#define CA_SF_AR_HI_SPEED_RD		BIT(17)
+#define CA_SF_AR_MIO_INF_DC		BIT(24)
+#define CA_SF_AR_MIO_INF_AC		BIT(25)
+#define CA_SF_AR_MIO_INF_CC		BIT(26)
+#define CA_SF_AR_DDR_MASK		GENMASK(29, 28)
+#define CA_SF_AR_DDR(ddr)		(((ddr) << 28) & CA_SF_AR_DDR_MASK)
+#define CA_SF_AR_MIO_INF_MASK		GENMASK(31, 30)
+#define CA_SF_AR_MIO_INF(io)		(((io) << 30) & CA_SF_AR_MIO_INF_MASK)
+
+/*
+ * FLASH_SF_EXT_ACCESS
+ */
+#define CA_SF_EAR_OPCODE_MASK		GENMASK(7, 0)
+#define CA_SF_EAR_OPCODE(op)		(((op) << 0) & CA_SF_EAR_OPCODE_MASK)
+#define CA_SF_EAR_DATA_CNT_MASK		GENMASK(20, 8)
+#define CA_SF_EAR_DATA_CNT(cnt)		(((cnt) << 8) & CA_SF_EAR_DATA_CNT_MASK)
+#define CA_SF_EAR_DATA_CNT_MAX		(4096)
+#define CA_SF_EAR_ADDR_CNT_MASK		GENMASK(23, 21)
+#define CA_SF_EAR_ADDR_CNT(cnt)		(((cnt) << 21) & CA_SF_EAR_ADDR_CNT_MASK)
+#define CA_SF_EAR_ADDR_CNT_MAX		(5)
+#define CA_SF_EAR_DUMY_CNT_MASK		GENMASK(29, 24)
+#define CA_SF_EAR_DUMY_CNT(cnt)		(((cnt) << 24) & CA_SF_EAR_DUMY_CNT_MASK)
+#define CA_SF_EAR_DUMY_CNT_MAX		(32)
+#define CA_SF_EAR_DRD_CMD_EN		BIT(31)
+
+/*
+ * FLASH_SF_ADDRESS
+ */
+#define CA_SF_ADR_REG_MASK		GENMASK(31, 0)
+#define CA_SF_ADR_REG(addr)		(((addr) << 0) & CA_SF_ADR_REG_MASK)
+
+/*
+ * FLASH_SF_DATA
+ */
+#define CA_SF_DR_REG_MASK		GENMASK(31, 0)
+#define CA_SF_DR_REG(addr)		(((addr) << 0) & CA_SF_DR_REG_MASK)
+
+/*
+ * FLASH_SF_TIMING
+ */
+#define CA_SF_TMR_IDLE_MASK		GENMASK(7, 0)
+#define CA_SF_TMR_IDLE(idle)		(((idle) << 0) & CA_SF_TMR_IDLE_MASK)
+#define CA_SF_TMR_HOLD_MASK		GENMASK(15, 8)
+#define CA_SF_TMR_HOLD(hold)		(((hold) << 8) & CA_SF_TMR_HOLD_MASK)
+#define CA_SF_TMR_SETUP_MASK		GENMASK(23, 16)
+#define CA_SF_TMR_SETUP(setup)		(((setup) << 16) & CA_SF_TMR_SETUP_MASK)
+#define CA_SF_TMR_CLK_MASK		GENMASK(26, 24)
+#define CA_SF_TMR_CLK(clk)		(((clk) << 24) & CA_SF_TMR_CLK_MASK)
+
+#define CA_SFLASH_IND_WRITE		0
+#define CA_SFLASH_IND_READ		1
+#define CA_SFLASH_MEM_MAP		3
+#define CA_SFLASH_FIFO_TIMEOUT_US	30000
+#define CA_SFLASH_BUSY_TIMEOUT_US	40000
+
+#define CA_SF_AC_OPCODE				0x00
+#define CA_SF_AC_OPCODE_1_DATA			0x01
+#define CA_SF_AC_OPCODE_2_DATA			0x02
+#define CA_SF_AC_OPCODE_3_DATA			0x03
+#define CA_SF_AC_OPCODE_4_DATA			0x04
+#define CA_SF_AC_OPCODE_3_ADDR			0x05
+#define CA_SF_AC_OPCODE_4_ADDR			(CA_SF_AC_OPCODE_3_ADDR)
+#define CA_SF_AC_OPCODE_3_ADDR_1_DATA		0x06
+#define CA_SF_AC_OPCODE_4_ADDR_1_DATA		(CA_SF_AC_OPCODE_3_ADDR_1_DATA << 2)
+#define CA_SF_AC_OPCODE_3_ADDR_2_DATA		0x07
+#define CA_SF_AC_OPCODE_4_ADDR_2_DATA		(CA_SF_AC_OPCODE_3_ADDR_2_DATA << 2)
+#define CA_SF_AC_OPCODE_3_ADDR_3_DATA		0x08
+#define CA_SF_AC_OPCODE_4_ADDR_3_DATA		(CA_SF_AC_OPCODE_3_ADDR_3_DATA << 2)
+#define CA_SF_AC_OPCODE_3_ADDR_4_DATA		0x09
+#define CA_SF_AC_OPCODE_4_ADDR_4_DATA		(CA_SF_AC_OPCODE_3_ADDR_4_DATA << 2)
+#define CA_SF_AC_OPCODE_3_ADDR_X_1_DATA		0x0A
+#define CA_SF_AC_OPCODE_4_ADDR_X_1_DATA		(CA_SF_AC_OPCODE_3_ADDR_X_1_DATA << 2)
+#define CA_SF_AC_OPCODE_3_ADDR_X_2_DATA		0x0B
+#define CA_SF_AC_OPCODE_4_ADDR_X_2_DATA		(CA_SF_AC_OPCODE_3_ADDR_X_2_DATA << 2)
+#define CA_SF_AC_OPCODE_3_ADDR_X_3_DATA		0x0C
+#define CA_SF_AC_OPCODE_4_ADDR_X_3_DATA		(CA_SF_AC_OPCODE_3_ADDR_X_3_DATA << 2)
+#define CA_SF_AC_OPCODE_3_ADDR_X_4_DATA		0x0D
+#define CA_SF_AC_OPCODE_4_ADDR_X_4_DATA		(CA_SF_AC_OPCODE_3_ADDR_X_4_DATA << 2)
+#define CA_SF_AC_OPCODE_3_ADDR_4X_1_DATA	0x0E
+#define CA_SF_AC_OPCODE_4_ADDR_4X_1_DATA	(CA_SF_AC_OPCODE_3_ADDR_4X_1_DATA << 2)
+#define CA_SF_AC_OPCODE_EXTEND			0x0F
+
+#define CA_SF_ACCESS_MIO_SINGLE		0
+#define CA_SF_ACCESS_MIO_DUAL		1
+#define CA_SF_ACCESS_MIO_QUARD		2
+
+enum access_type {
+	RD_ACCESS,
+	WR_ACCESS,
+};
+
+struct ca_sflash_priv {
+	struct ca_sflash_regs *regs;
+	u8 rx_width;
+	u8 tx_width;
+};
+
+/*
+ * This function doesn't do anything except help with debugging
+ */
+static int ca_sflash_claim_bus(struct udevice *dev)
+{
+	debug("%s:\n", __func__);
+	return 0;
+}
+
+static int ca_sflash_release_bus(struct udevice *dev)
+{
+	debug("%s:\n", __func__);
+	return 0;
+}
+
+static int ca_sflash_set_speed(struct udevice *dev, uint speed)
+{
+	debug("%s:\n", __func__);
+	return 0;
+}
+
+static int ca_sflash_set_mode(struct udevice *dev, uint mode)
+{
+	struct ca_sflash_priv *priv = dev_get_priv(dev);
+
+	if (mode & SPI_RX_QUAD)
+		priv->rx_width = 4;
+	else if (mode & SPI_RX_DUAL)
+		priv->rx_width = 2;
+	else
+		priv->rx_width = 1;
+
+	if (mode & SPI_TX_QUAD)
+		priv->tx_width = 4;
+	else if (mode & SPI_TX_DUAL)
+		priv->tx_width = 2;
+	else
+		priv->tx_width = 1;
+
+	debug("%s: mode=%d, rx_width=%d, tx_width=%d\n",
+	      __func__, mode, priv->rx_width, priv->tx_width);
+
+	return 0;
+}
+
+static int _ca_sflash_wait_for_not_busy(struct ca_sflash_priv *priv)
+{
+	u32 asr;
+
+	if (readl_poll_timeout(&priv->regs->asr, asr,
+			       !(asr & CA_FLASH_ASR_IND_START_EN),
+			       CA_SFLASH_BUSY_TIMEOUT_US)) {
+		pr_err("busy timeout (stat:%#x)\n", asr);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int _ca_sflash_wait_cmd(struct ca_sflash_priv *priv,
+			       enum access_type type)
+{
+	if (type == WR_ACCESS) {
+		/* Enable write access and start the sflash indirect access */
+		clrsetbits_le32(&priv->regs->asr, GENMASK(31, 0),
+				CA_FLASH_ASR_WR_ACCESS_EN
+				| CA_FLASH_ASR_IND_START_EN);
+	} else if (type == RD_ACCESS) {
+		/* Start the sflash indirect access */
+		clrsetbits_le32(&priv->regs->asr, GENMASK(31, 0),
+				CA_FLASH_ASR_IND_START_EN);
+	} else {
+		printf("%s: !error access type.\n", __func__);
+		return -1;
+	}
+
+	/* Wait til the action(rd/wr) completed */
+	return _ca_sflash_wait_for_not_busy(priv);
+}
+
+static int _ca_sflash_read(struct ca_sflash_priv *priv,
+			   u8 *buf, unsigned int data_len)
+{
+	u32 reg_data;
+	int len;
+
+	len = data_len;
+	while (len >= 4) {
+		if (_ca_sflash_wait_cmd(priv, RD_ACCESS))
+			return -1;
+		reg_data = readl(&priv->regs->dr);
+		*buf++ = reg_data & 0xFF;
+		*buf++ = (reg_data >> 8) & 0xFF;
+		*buf++ = (reg_data >> 16) & 0xFF;
+		*buf++ = (reg_data >> 24) & 0xFF;
+		len -= 4;
+		debug("%s: reg_data=%#08x\n",
+		      __func__, reg_data);
+	}
+
+	if (len > 0) {
+		if (_ca_sflash_wait_cmd(priv, RD_ACCESS))
+			return -1;
+		reg_data = readl(&priv->regs->dr);
+		debug("%s: reg_data=%#08x\n",
+		      __func__, reg_data);
+	}
+
+	switch (len) {
+	case 3:
+		*buf++ = reg_data & 0xFF;
+		*buf++ = (reg_data >> 8) & 0xFF;
+		*buf++ = (reg_data >> 16) & 0xFF;
+		break;
+	case 2:
+		*buf++ = reg_data & 0xFF;
+		*buf++ = (reg_data >> 8) & 0xFF;
+		break;
+	case 1:
+		*buf++ = reg_data & 0xFF;
+		break;
+	case 0:
+		break;
+	default:
+		printf("%s: error data_length %d!\n", __func__, len);
+	}
+
+	return 0;
+}
+
+static int _ca_sflash_mio_set(struct ca_sflash_priv *priv,
+			      u8 width)
+{
+	if (width == 4) {
+		setbits_le32(&priv->regs->ar,
+			     CA_SF_AR_MIO_INF_DC
+			     | CA_SF_AR_MIO_INF(CA_SF_ACCESS_MIO_QUARD)
+			     | CA_SF_AR_FORCE_BURST);
+	} else if (width == 2) {
+		setbits_le32(&priv->regs->ar,
+			     CA_SF_AR_MIO_INF_DC
+			     | CA_SF_AR_MIO_INF(CA_SF_ACCESS_MIO_DUAL)
+			     | CA_SF_AR_FORCE_BURST);
+	} else if (width == 1) {
+		setbits_le32(&priv->regs->ar,
+			     CA_SF_AR_MIO_INF(CA_SF_ACCESS_MIO_SINGLE)
+			     | CA_SF_AR_FORCE_BURST);
+	} else {
+		printf("%s: error rx/tx width  %d!\n", __func__, width);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int _ca_sflash_write(struct ca_sflash_priv *priv,
+			    u8 *buf, unsigned int data_len)
+{
+	u32 reg_data;
+	int len;
+
+	len = data_len;
+	while (len > 0) {
+		reg_data = buf[0]
+			| (buf[1] << 8)
+			| (buf[2] << 16)
+			| (buf[3] << 24);
+
+		debug("%s: reg_data=%#08x\n",
+		      __func__, reg_data);
+		/* Fill data */
+		clrsetbits_le32(&priv->regs->dr, GENMASK(31, 0), reg_data);
+
+		if (_ca_sflash_wait_cmd(priv, WR_ACCESS))
+			return -1;
+
+		len -= 4;
+		buf += 4;
+	}
+
+	return 0;
+}
+
+static int _ca_sflash_access_data(struct ca_sflash_priv *priv,
+				  struct spi_mem_op *op)
+{
+	int total_cnt;
+	unsigned int len;
+	unsigned int data_cnt = op->data.nbytes;
+	u64 addr_offset = op->addr.val;
+	u8 addr_cnt = op->addr.nbytes;
+	u8 *data_buf = NULL;
+	u8 *buf = NULL;
+
+	if (op->data.dir == SPI_MEM_DATA_IN)
+		data_buf = (u8 *)op->data.buf.in;
+	else
+		data_buf = (u8 *)op->data.buf.out;
+
+	if (data_cnt > CA_SF_EAR_DATA_CNT_MAX)
+		buf = malloc(CA_SF_EAR_DATA_CNT_MAX);
+	else
+		buf = malloc(data_cnt);
+
+	total_cnt = data_cnt;
+	while (total_cnt > 0) {
+		/* Fill address */
+		if (addr_cnt > 0)
+			clrsetbits_le32(&priv->regs->adr,
+					GENMASK(31, 0), (u32)addr_offset);
+
+		if (total_cnt > CA_SF_EAR_DATA_CNT_MAX) {
+			len = CA_SF_EAR_DATA_CNT_MAX;
+			addr_offset += CA_SF_EAR_DATA_CNT_MAX;
+			/* Clear start bit before next bulk read */
+			clrbits_le32(&priv->regs->asr, GENMASK(31, 0));
+		} else {
+			len = total_cnt;
+		}
+
+		memset(buf, 0, len);
+		if (op->data.dir == SPI_MEM_DATA_IN) {
+			if (_ca_sflash_read(priv, buf, len))
+				break;
+			memcpy(data_buf, buf, len);
+		} else {
+			memcpy(buf, data_buf, len);
+			if (_ca_sflash_write(priv, buf, len))
+				break;
+		}
+
+		total_cnt -= len;
+		data_buf += len;
+	}
+	if (buf)
+		free(buf);
+
+	return total_cnt > 0 ? -1 : 0;
+}
+
+static int _ca_sflash_issue_cmd(struct ca_sflash_priv *priv,
+				struct spi_mem_op *op, u8 opcode)
+{
+	u8 dummy_cnt = op->dummy.nbytes;
+	u8 addr_cnt = op->addr.nbytes;
+	u8 mio_width;
+	unsigned int data_cnt = op->data.nbytes;
+	u64 addr_offset = op->addr.val;
+
+	/* Set the access register */
+	clrsetbits_le32(&priv->regs->ar,
+			GENMASK(31, 0), CA_SF_AR_ACCODE(opcode));
+
+	if (opcode == CA_SF_AC_OPCODE_EXTEND) { /* read_data, write_data */
+		if (data_cnt > 6) {
+			if (op->data.dir == SPI_MEM_DATA_IN)
+				mio_width = priv->rx_width;
+			else
+				mio_width = priv->tx_width;
+			if (_ca_sflash_mio_set(priv, mio_width))
+				return -1;
+		}
+		debug("%s: FLASH ACCESS reg=%#08x\n",
+		      __func__, readl(&priv->regs->ar));
+
+		/* Use command in extend_access register */
+		clrsetbits_le32(&priv->regs->ear,
+				GENMASK(31, 0), CA_SF_EAR_OPCODE(op->cmd.opcode)
+				| CA_SF_EAR_DUMY_CNT(dummy_cnt * 8 - 1)
+				| CA_SF_EAR_ADDR_CNT(addr_cnt - 1)
+				| CA_SF_EAR_DATA_CNT(4 - 1)
+				| CA_SF_EAR_DRD_CMD_EN);
+		debug("%s: FLASH EXT ACCESS reg=%#08x\n",
+		      __func__, readl(&priv->regs->ear));
+
+		if (_ca_sflash_access_data(priv, op))
+			return -1;
+	} else { /* reset_op, wr_enable, wr_disable */
+		setbits_le32(&priv->regs->ar,
+			     CA_SF_AR_OPCODE(op->cmd.opcode));
+		debug("%s: FLASH ACCESS reg=%#08x\n",
+		      __func__, readl(&priv->regs->ar));
+
+		if (opcode == CA_SF_AC_OPCODE_4_ADDR) { /* erase_op */
+			/* Configure address length */
+			if (addr_cnt > 3)	/* 4 Bytes address */
+				setbits_le32(&priv->regs->tr,
+					     CA_FLASH_TR_SIZE(2));
+			else				/* 3 Bytes address */
+				clrbits_le32(&priv->regs->tr,
+					     CA_FLASH_TR_SIZE_MASK);
+
+			/* Fill address */
+			if (addr_cnt > 0)
+				clrsetbits_le32(&priv->regs->adr,
+						GENMASK(31, 0),
+						(u32)addr_offset);
+		}
+
+		if (_ca_sflash_wait_cmd(priv, RD_ACCESS))
+			return -1;
+	}
+	/* elapse 10us before issuing any other command */
+	udelay(10);
+
+	return 0;
+}
+
+static int ca_sflash_exec_op(struct spi_slave *slave,
+			     const struct spi_mem_op *op)
+{
+	struct ca_sflash_priv *priv = dev_get_priv(slave->dev->parent);
+	u8 opcode;
+
+	debug("%s: cmd:%#02x addr.val:%#llx addr.len:%#x data.len:%#x data.dir:%#x\n",
+	      __func__, op->cmd.opcode, op->addr.val,
+	      op->addr.nbytes, op->data.nbytes, op->data.dir);
+
+	if (op->data.nbytes == 0 && op->addr.nbytes == 0) {
+		opcode = CA_SF_AC_OPCODE;
+	} else if (op->data.nbytes == 0 && op->addr.nbytes > 0) {
+		opcode = CA_SF_AC_OPCODE_4_ADDR;
+	} else if (op->data.nbytes > 0) {
+		opcode = CA_SF_AC_OPCODE_EXTEND;
+	} else {
+		printf("%s: can't support cmd.opcode:(%#02x) type currently!\n",
+		       __func__, op->cmd.opcode);
+		return -1;
+	}
+
+	return _ca_sflash_issue_cmd(priv, (struct spi_mem_op *)op, opcode);
+}
+
+static void ca_sflash_init(struct ca_sflash_priv *priv)
+{
+	/* Set FLASH_TYPE as serial flash, value: 0x0400*/
+	clrsetbits_le32(&priv->regs->tr,
+			GENMASK(31, 0), CA_FLASH_TR_SIZE(2));
+	debug("%s: FLASH_TYPE reg=%#x\n",
+	      __func__, readl(&priv->regs->tr));
+
+	/* Minimize flash timing, value: 0x07010101 */
+	clrsetbits_le32(&priv->regs->tmr,
+			GENMASK(31, 0),
+			CA_SF_TMR_CLK(0x07)
+			| CA_SF_TMR_SETUP(0x01)
+			| CA_SF_TMR_HOLD(0x01)
+			| CA_SF_TMR_IDLE(0x01));
+	debug("%s: FLASH_TIMING reg=%#x\n",
+	      __func__, readl(&priv->regs->tmr));
+}
+
+static int ca_sflash_probe(struct udevice *dev)
+{
+	struct ca_sflash_priv *priv = dev_get_priv(dev);
+	struct resource res;
+	int ret;
+
+	/* Map the registers */
+	ret = dev_read_resource_byname(dev, "sflash-regs", &res);
+	if (ret) {
+		dev_err(dev, "can't get regs base addresses(ret = %d)!\n", ret);
+		return ret;
+	}
+	priv->regs = devm_ioremap(dev, res.start, resource_size(&res));
+	if (IS_ERR(priv->regs))
+		return PTR_ERR(priv->regs);
+
+	ca_sflash_init(priv);
+
+	printf("SFLASH: Controller probed ready\n");
+	return 0;
+}
+
+static const struct spi_controller_mem_ops ca_sflash_mem_ops = {
+	.exec_op = ca_sflash_exec_op,
+};
+
+static const struct dm_spi_ops ca_sflash_ops = {
+	.claim_bus = ca_sflash_claim_bus,
+	.release_bus = ca_sflash_release_bus,
+	.set_speed = ca_sflash_set_speed,
+	.set_mode = ca_sflash_set_mode,
+	.mem_ops = &ca_sflash_mem_ops,
+};
+
+static const struct udevice_id ca_sflash_ids[] = {
+	{.compatible = "cortina,ca-sflash"},
+	{}
+};
+
+U_BOOT_DRIVER(ca_sflash) = {
+	.name = "ca_sflash",
+	.id = UCLASS_SPI,
+	.of_match = ca_sflash_ids,
+	.ops = &ca_sflash_ops,
+	.priv_auto_alloc_size = sizeof(struct ca_sflash_priv),
+	.probe = ca_sflash_probe,
+};
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 8/8] board: presidio-asic: Add SPI NAND and NOR support
  2020-03-20  0:57 [PATCH v2 0/8] Cortina Access Drivers Package 2 Alex Nemirovsky
                   ` (6 preceding siblings ...)
  2020-03-20  0:57 ` [PATCH v2 7/8] spi: ca_sflash: Add CAxxxx SPI Flash Controller Alex Nemirovsky
@ 2020-03-20  0:57 ` Alex Nemirovsky
  7 siblings, 0 replies; 18+ messages in thread
From: Alex Nemirovsky @ 2020-03-20  0:57 UTC (permalink / raw)
  To: u-boot

Add SPI NAND and NOR support for Cortina Access
Presidio Engineering Board

Signed-off-by: Alex Nemirovsky <alex.nemirovsky@cortina-access.com>
CC: Jagan Teki <jagan@amarulasolutions.com>
---

Changes in v3: None
Changes in v2: None

 arch/arm/dts/ca-presidio-engboard.dts            |  8 ++--
 board/cortina/presidio-asic/presidio.c           | 16 ++++++-
 configs/cortina_presidio-asic-spi-nand_defconfig | 48 +++++++++++++++++++
 configs/cortina_presidio-asic-spi-nor_defconfig  | 59 ++++++++++++++++++++++++
 4 files changed, 125 insertions(+), 6 deletions(-)
 create mode 100644 configs/cortina_presidio-asic-spi-nand_defconfig
 create mode 100644 configs/cortina_presidio-asic-spi-nor_defconfig

diff --git a/arch/arm/dts/ca-presidio-engboard.dts b/arch/arm/dts/ca-presidio-engboard.dts
index ae897e8..8c73eb6 100644
--- a/arch/arm/dts/ca-presidio-engboard.dts
+++ b/arch/arm/dts/ca-presidio-engboard.dts
@@ -55,15 +55,13 @@
 	};
 
 	sflash: sflash-controller at f4324000 {
-		#address-cells = <2>;
-		#size-cells = <1>;
 		compatible = "cortina,ca-sflash";
 		reg = <0x0 0xf4324000 0x50>;
 		reg-names = "sflash-regs";
 		flash at 0 {
-			compatible = "jedec,spi-nor";
-			spi-rx-bus-width = <1>;
-			spi-max-frequency = <108000000>;
+			compatible = "spi-nand", "jedec,spi-nor";
+			spi-rx-bus-width = <4>;
+			spi-tx-bus-width = <4>;
 		};
 	};
 
diff --git a/board/cortina/presidio-asic/presidio.c b/board/cortina/presidio-asic/presidio.c
index b4fa01f..d547b60 100644
--- a/board/cortina/presidio-asic/presidio.c
+++ b/board/cortina/presidio-asic/presidio.c
@@ -14,7 +14,7 @@
 #include <asm/psci.h>
 #include <cpu_func.h>
 #include <asm/armv8/mmu.h>
-
+#include <dm/uclass.h>
 DECLARE_GLOBAL_DATA_PTR;
 
 #define CA_PERIPH_BASE                  0xE0000000UL
@@ -70,9 +70,23 @@ static noinline int invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1,
 	return function_id;
 }
 
+#ifdef CONFIG_CORTINA_SFLASH
+static int init_sflash(void)
+{
+	struct udevice *dev;
+
+	uclass_first_device(UCLASS_SPI, &dev);
+
+	return 0;
+}
+#endif
+
 int board_early_init_r(void)
 {
 	dcache_disable();
+#ifdef CONFIG_CORTINA_SFLASH
+	init_sflash();
+#endif
 	return 0;
 }
 
diff --git a/configs/cortina_presidio-asic-spi-nand_defconfig b/configs/cortina_presidio-asic-spi-nand_defconfig
new file mode 100644
index 0000000..515ad22
--- /dev/null
+++ b/configs/cortina_presidio-asic-spi-nand_defconfig
@@ -0,0 +1,48 @@
+CONFIG_ARM=y
+# CONFIG_SYS_ARCH_TIMER is not set
+CONFIG_TARGET_PRESIDIO_ASIC=y
+CONFIG_SYS_TEXT_BASE=0x04000000
+CONFIG_ENV_SIZE=0x20000
+CONFIG_DM_GPIO=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_IDENT_STRING="Presidio-SoC"
+CONFIG_SHOW_BOOT_PROGRESS=y
+CONFIG_BOOTDELAY=3
+CONFIG_LOGLEVEL=7
+CONFIG_BOARD_EARLY_INIT_R=y
+CONFIG_SYS_PROMPT="G3#"
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_MTD=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_SF_TEST=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_WDT=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIMER=y
+CONFIG_CMD_SMC=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_LIVE=y
+CONFIG_DEFAULT_DEVICE_TREE="ca-presidio-engboard"
+# CONFIG_NET is not set
+CONFIG_DM=y
+CONFIG_CORTINA_GPIO=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_CA=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_CORTINA=y
+CONFIG_MTD=y
+CONFIG_DM_MTD=y
+CONFIG_MTD_SPI_NAND=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_DM_SERIAL=y
+CONFIG_CORTINA_UART=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_CORTINA_SFLASH=y
+CONFIG_WDT=y
+CONFIG_WDT_CORTINA=y
diff --git a/configs/cortina_presidio-asic-spi-nor_defconfig b/configs/cortina_presidio-asic-spi-nor_defconfig
new file mode 100644
index 0000000..d7ecec3
--- /dev/null
+++ b/configs/cortina_presidio-asic-spi-nor_defconfig
@@ -0,0 +1,59 @@
+CONFIG_ARM=y
+# CONFIG_SYS_ARCH_TIMER is not set
+CONFIG_TARGET_PRESIDIO_ASIC=y
+CONFIG_SYS_TEXT_BASE=0x04000000
+CONFIG_ENV_SIZE=0x20000
+CONFIG_DM_GPIO=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_IDENT_STRING="Presidio-SoC"
+CONFIG_SHOW_BOOT_PROGRESS=y
+CONFIG_BOOTDELAY=3
+CONFIG_BOARD_EARLY_INIT_R=y
+CONFIG_SYS_PROMPT="G3#"
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_MTD=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_SF_TEST=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_WDT=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIMER=y
+CONFIG_CMD_SMC=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_LIVE=y
+CONFIG_DEFAULT_DEVICE_TREE="ca-presidio-engboard"
+# CONFIG_NET is not set
+CONFIG_DM=y
+CONFIG_CORTINA_GPIO=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_CA=y
+CONFIG_LED=y
+CONFIG_LED_CORTINA=y
+CONFIG_DM_MMC=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_CORTINA=y
+CONFIG_MTD=y
+CONFIG_DM_MTD=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH_ATMEL=y
+CONFIG_SPI_FLASH_EON=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_ISSI=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_SST=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_XMC=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_DM_SERIAL=y
+CONFIG_CORTINA_UART=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_CORTINA_SFLASH=y
+CONFIG_WDT=y
+CONFIG_WDT_CORTINA=y
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 3/8] i2c: i2c-cortina: added CAxxxx I2C support
  2020-03-20  0:57 ` [PATCH v2 3/8] i2c: i2c-cortina: added CAxxxx I2C support Alex Nemirovsky
@ 2020-03-20  6:25   ` Heiko Schocher
  0 siblings, 0 replies; 18+ messages in thread
From: Heiko Schocher @ 2020-03-20  6:25 UTC (permalink / raw)
  To: u-boot

Hello Alex,

Am 20.03.2020 um 01:57 schrieb Alex Nemirovsky:
> From: Arthur Li <arthur.li@cortina-access.com>
> 
> Add I2C controller support for Cortina Access CAxxxx SoCs
> 
> Signed-off-by: Arthur Li <arthur.li@cortina-access.com>
> Signed-off-by: Alex Nemirovsky <alex.nemirovsky@cortina-access.com>
> CC: Heiko Schocher <hs@denx.de>
> ---
> 
> Changes in v3: None
> Changes in v2: None
> 
>   MAINTAINERS               |   4 +
>   drivers/i2c/Kconfig       |   7 +
>   drivers/i2c/Makefile      |   1 +
>   drivers/i2c/i2c-cortina.c | 346 ++++++++++++++++++++++++++++++++++++++++++++++
>   drivers/i2c/i2c-cortina.h |  92 ++++++++++++
>   5 files changed, 450 insertions(+)
>   create mode 100644 drivers/i2c/i2c-cortina.c
>   create mode 100644 drivers/i2c/i2c-cortina.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index bb45d3c..b147faa 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -181,6 +181,8 @@ F:	drivers/gpio/cortina_gpio.c
>   F:	drivers/watchdog/cortina_wdt.c
>   F:	drivers/serial/serial_cortina.c
>   F:	drivers/mmc/ca_dw_mmc.c
> +F:	drivers/i2c/i2c-cortina.c
> +F:	drivers/i2c/i2c-cortina.h
>   
>   ARM/CZ.NIC TURRIS MOX SUPPORT
>   M:	Marek Behun <marek.behun@nic.cz>
> @@ -672,6 +674,8 @@ F:	drivers/gpio/cortina_gpio.c
>   F:	drivers/watchdog/cortina_wdt.c
>   F:	drivers/serial/serial_cortina.c
>   F:	drivers/mmc/ca_dw_mmc.c
> +F:	drivers/i2c/i2c-cortina.c
> +F:	drivers/i2c/i2c-cortina.h
>   
>   MIPS MSCC
>   M:	Gregory CLEMENT <gregory.clement@bootlin.com>
> diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
> index 03d2fed..b98a4aa 100644
> --- a/drivers/i2c/Kconfig
> +++ b/drivers/i2c/Kconfig
> @@ -85,6 +85,13 @@ config SYS_I2C_CADENCE
>   	  Say yes here to select Cadence I2C Host Controller. This controller is
>   	  e.g. used by Xilinx Zynq.
>   
> +config SYS_I2C_CA
> +	tristate "Cortina-Access I2C Controller"
> +	depends on DM_I2C && CORTINA_PLATFORM
> +	default n
> +	help
> +	  Say yes here to select Cortina-Access I2C Host Controller.
> +
>   config SYS_I2C_DAVINCI
>   	bool "Davinci I2C Controller"
>   	depends on (ARCH_KEYSTONE || ARCH_DAVINCI)
> diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
> index f5a471f..5d18cf7 100644
> --- a/drivers/i2c/Makefile
> +++ b/drivers/i2c/Makefile
> @@ -12,6 +12,7 @@ obj-$(CONFIG_SYS_I2C) += i2c_core.o
>   obj-$(CONFIG_SYS_I2C_ASPEED) += ast_i2c.o
>   obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o
>   obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
> +obj-$(CONFIG_SYS_I2C_CA) += i2c-cortina.o
>   obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
>   obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
>   ifdef CONFIG_DM_PCI
> diff --git a/drivers/i2c/i2c-cortina.c b/drivers/i2c/i2c-cortina.c
> new file mode 100644
> index 0000000..99c63f3
> --- /dev/null
> +++ b/drivers/i2c/i2c-cortina.c
> @@ -0,0 +1,346 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2020
> + * Arthur Li, Cortina Access, arthur.li at cortina-access.com.
> + */
> +
> +#include <common.h>
> +#include <i2c.h>
> +#include <asm/io.h>
> +#include <dm.h>
> +#include <mapmem.h>
> +#include "i2c-cortina.h"
> +
> +static void set_speed(struct i2c_regs *regs, int i2c_spd)
> +{
> +	union ca_biw_cfg i2c_cfg;
> +
> +	i2c_cfg.wrd = readl(&regs->i2c_cfg);
> +	i2c_cfg.bf.core_en = 0;
> +	writel(i2c_cfg.wrd, &regs->i2c_cfg);
> +
> +	switch (i2c_spd) {
> +	case IC_SPEED_MODE_MAX:
> +		i2c_cfg.bf.prer =
> +			CORTINA_PER_IO_FREQ / (5 * I2C_MAX_SPEED) - 1;
> +		break;
> +
> +	case IC_SPEED_MODE_STANDARD:
> +		i2c_cfg.bf.prer =
> +			CORTINA_PER_IO_FREQ / (5 * I2C_STANDARD_SPEED) - 1;
> +		break;
> +
> +	case IC_SPEED_MODE_FAST:
> +	default:
> +		i2c_cfg.bf.prer =
> +			CORTINA_PER_IO_FREQ / (5 * I2C_FAST_SPEED) - 1;
> +		break;
> +	}
> +
> +	i2c_cfg.bf.core_en = 1;
> +	writel(i2c_cfg.wrd, &regs->i2c_cfg);
> +}
> +
> +static int ca_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
> +{
> +	struct ca_i2c *priv = dev_get_priv(bus);
> +	int i2c_spd;
> +
> +	if (speed >= I2C_MAX_SPEED) {
> +		i2c_spd = IC_SPEED_MODE_MAX;
> +		priv->speed = I2C_MAX_SPEED;
> +	} else if (speed >= I2C_FAST_SPEED) {
> +		i2c_spd = IC_SPEED_MODE_FAST;
> +		priv->speed = I2C_FAST_SPEED;
> +	} else {
> +		i2c_spd = IC_SPEED_MODE_STANDARD;
> +		priv->speed = I2C_STANDARD_SPEED;
> +	}
> +
> +	set_speed(priv->regs, i2c_spd);
> +
> +	return 0;
> +}
> +
> +static int ca_i2c_get_bus_speed(struct udevice *bus)
> +{
> +	struct ca_i2c *priv = dev_get_priv(bus);
> +
> +	return priv->speed;
> +}
> +
> +static void ca_i2c_init(struct i2c_regs *regs)
> +{
> +	union ca_biw_cfg i2c_cfg;
> +
> +	i2c_cfg.wrd = readl(&regs->i2c_cfg);
> +	i2c_cfg.bf.core_en = 0;
> +	i2c_cfg.bf.biw_soft_reset = 1;
> +	writel(i2c_cfg.wrd, &regs->i2c_cfg);
> +	mdelay(10);
> +	i2c_cfg.bf.biw_soft_reset = 0;
> +	writel(i2c_cfg.wrd, &regs->i2c_cfg);
> +
> +	set_speed(regs, IC_SPEED_MODE_STANDARD);
> +
> +	i2c_cfg.wrd = readl(&regs->i2c_cfg);
> +	i2c_cfg.bf.core_en = 1;
> +	writel(i2c_cfg.wrd, &regs->i2c_cfg);
> +}
> +
> +static int i2c_wait_complete(struct i2c_regs *regs)
> +{
> +	union ca_biw_ctrl i2c_ctrl;
> +	unsigned long start_time_bb = get_timer(0);
> +
> +	i2c_ctrl.wrd = readl(&regs->i2c_ctrl);
> +
> +	while (i2c_ctrl.bf.biwdone == 0) {
> +		i2c_ctrl.wrd = readl(&regs->i2c_ctrl);
> +
> +		if (get_timer(start_time_bb) >
> +		   (unsigned long)(I2C_BYTE_TO_BB)) {
> +			printf("%s not done!!!\n", __func__);
> +			return 1;

Please use -ETIMEDOUT

> +		}
> +	}
> +
> +	/* Clear done bit */
> +	writel(i2c_ctrl.wrd, &regs->i2c_ctrl);
> +
> +	return 0;
> +}
> +
> +static void i2c_setaddress(struct i2c_regs *regs, unsigned int i2c_addr,
> +			   int write_read)
> +{
> +	writel(i2c_addr | write_read, &regs->i2c_txr);
> +
> +	writel(BIW_CTRL_START | BIW_CTRL_WRITE,
> +	       &regs->i2c_ctrl);
> +
> +	i2c_wait_complete(regs);
> +}
> +
> +static int i2c_wait_for_bus_busy(struct i2c_regs *regs)
> +{
> +	union ca_biw_ack i2c_ack;
> +	unsigned long start_time_bb = get_timer(0);
> +
> +	i2c_ack.wrd = readl(&regs->i2c_ack);
> +
> +	while (i2c_ack.bf.biw_busy) {
> +		i2c_ack.wrd = readl(&regs->i2c_ack);
> +
> +		if (get_timer(start_time_bb) >
> +		   (unsigned long)(I2C_BYTE_TO_BB)) {
> +			printf("%s: timeout!\n", __func__);
> +			return 1;

Here too.

> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int i2c_xfer_init(struct i2c_regs *regs, uint8_t chip, uint addr,
> +			 int alen, int write_read)
> +{
> +	int addr_len = alen;
> +
> +	if (i2c_wait_for_bus_busy(regs))
> +		return 1;

Add a blank line please

> +	/* First cycle must write addr + offset */
> +	chip = ((chip & 0x7F) << 1);
> +	if (alen == 0 && write_read == I2C_CMD_RD)
> +		i2c_setaddress(regs, chip, I2C_CMD_RD);
> +	else
> +		i2c_setaddress(regs, chip, I2C_CMD_WT);
> +
> +	while (alen) {
> +		alen--;
> +		writel(addr, &regs->i2c_txr);
> +		if (write_read == I2C_CMD_RD)
> +			writel(BIW_CTRL_WRITE | BIW_CTRL_STOP,
> +			       &regs->i2c_ctrl);
> +		else
> +			writel(BIW_CTRL_WRITE, &regs->i2c_ctrl);
> +		i2c_wait_complete(regs);
> +	}
> +
> +	/* Send address again with Read flag if it's read command */
> +	if (write_read == I2C_CMD_RD && addr_len > 0)
> +		i2c_setaddress(regs, chip, I2C_CMD_RD);
> +
> +	return 0;
> +}
> +
> +static int i2c_xfer_finish(struct i2c_regs *regs)
> +{
> +	/* Dummy read makes bus free */
> +	writel(BIW_CTRL_READ | BIW_CTRL_STOP, &regs->i2c_ctrl);
> +	i2c_wait_complete(regs);
> +
> +	if (i2c_wait_for_bus_busy(regs)) {
> +		printf("Timed out waiting for bus\n");
> +		return 1;

return -ETIMEDOUT

> +	}
> +
> +	return 0;
> +}
> +
> +static int ca_i2c_read(struct i2c_regs *regs, uint8_t chip, uint addr,
> +		       int alen, uint8_t *buffer, int len)
> +{
> +	unsigned long start_time_rx;
> +	int rc = 0;
> +
> +	if (i2c_xfer_init(regs, chip, addr, alen, I2C_CMD_RD))
> +		return 1;

please return the return value from i2c_xfer_init()

> +
> +	start_time_rx = get_timer(0);
> +	while (len) {
> +		/* ACK_IN is ack value to send during read.
> +		 * ack high only on the very last byte!
> +		 */
> +		if (len == 1) {
> +			writel(BIW_CTRL_READ | BIW_CTRL_ACK_IN | BIW_CTRL_STOP,
> +			       &regs->i2c_ctrl);
> +		} else {
> +			writel(BIW_CTRL_READ, &regs->i2c_ctrl);
> +		}

remove the brackets, they are not needed.

> +
> +		rc = i2c_wait_complete(regs);
> +		udelay(1);
> +
> +		if (rc == 0) {
> +			*buffer++ =
> +				(uchar) readl(&regs->i2c_rxr);
> +			len--;
> +			start_time_rx = get_timer(0);
> +
> +		} else if (get_timer(start_time_rx) > I2C_BYTE_TO) {
> +			return 1;

return -ETIMEDOUT

> +		}
> +	}
> +	i2c_xfer_finish(regs);
> +	return rc;
> +}
> +
> +static int ca_i2c_write(struct i2c_regs *regs, uint8_t chip, uint addr,
> +			int alen, uint8_t *buffer, int len)
> +{
> +	int rc, nb = len;
> +	unsigned long start_time_tx;
> +
> +	if (i2c_xfer_init(regs, chip, addr, alen, I2C_CMD_WT))
> +		return 1;

please return the return value from i2c_xfer_init

> +
> +	start_time_tx = get_timer(0);
> +	while (len) {
> +		writel(*buffer, &regs->i2c_txr);
> +		if (len == 1) {
> +			writel(BIW_CTRL_WRITE | BIW_CTRL_STOP,
> +			       &regs->i2c_ctrl);
> +		} else {
> +			writel(BIW_CTRL_WRITE, &regs->i2c_ctrl);
> +		}

also here, the brackets are not needed.

> +
> +		rc = i2c_wait_complete(regs);
> +
> +		if (rc == 0) {
> +			len--;
> +			buffer++;
> +			start_time_tx = get_timer(0);
> +		} else if (get_timer(start_time_tx) > (nb * I2C_BYTE_TO)) {
> +			printf("Timed out. i2c write Failed\n");
> +			return 1;

return -ETIMEDOUT

> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int ca_i2c_probe_chip(struct udevice *bus, uint chip_addr,
> +			     uint chip_flags)
> +{
> +	struct ca_i2c *priv = dev_get_priv(bus);
> +	int ret;
> +	u32 tmp;
> +
> +	/* Try to read the first location of the chip */
> +	ret = ca_i2c_read(priv->regs, chip_addr, 0, 1, (uchar *)&tmp, 1);
> +	if (ret)
> +		ca_i2c_init(priv->regs);
> +
> +	return ret;
> +}
> +
> +static int ca_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
> +{
> +	struct ca_i2c *priv = dev_get_priv(bus);
> +	int ret;
> +
> +	debug("i2c_xfer: %d messages\n", nmsgs);
> +	for (; nmsgs > 0; nmsgs--, msg++) {
> +		debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
> +		if (msg->flags & I2C_M_RD) {
> +			ret = ca_i2c_read(priv->regs, msg->addr, 0, 0,
> +					  msg->buf, msg->len);
> +		} else {
> +			ret = ca_i2c_write(priv->regs, msg->addr, 0, 0,
> +					   msg->buf, msg->len);
> +		}

here too, brackets are not needed.

> +
> +		if (ret) {
> +			debug("i2c_write: error sending\n");

wrong printf when you did a read.

> +			return -EREMOTEIO;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct dm_i2c_ops ca_i2c_ops = {
> +	.xfer		= ca_i2c_xfer,
> +	.probe_chip	= ca_i2c_probe_chip,
> +	.set_bus_speed	= ca_i2c_set_bus_speed,
> +	.get_bus_speed	= ca_i2c_get_bus_speed,
> +};
> +
> +static const struct udevice_id ca_i2c_ids[] = {
> +	{ .compatible = "cortina,ca-i2c", },
> +	{ }
> +};
> +
> +static int ca_i2c_probe(struct udevice *bus)
> +{
> +	struct ca_i2c *priv = dev_get_priv(bus);
> +
> +	ca_i2c_init(priv->regs);
> +
> +	return 0;
> +}
> +
> +static int ca_i2c_ofdata_to_platdata(struct udevice *bus)
> +{
> +	struct ca_i2c *priv = dev_get_priv(bus);
> +
> +	priv->regs = map_sysmem(dev_read_addr(bus), sizeof(struct i2c_regs));
> +	if (!priv->regs) {
> +		printf("I2C: base address is invalid\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +U_BOOT_DRIVER(i2c_cortina) = {
> +	.name	= "i2c_cortina",
> +	.id	= UCLASS_I2C,
> +	.of_match = ca_i2c_ids,
> +	.ofdata_to_platdata = ca_i2c_ofdata_to_platdata,
> +	.probe	= ca_i2c_probe,
> +	.priv_auto_alloc_size = sizeof(struct ca_i2c),
> +	.ops	= &ca_i2c_ops,
> +	.flags  = DM_FLAG_PRE_RELOC,
> +};
> diff --git a/drivers/i2c/i2c-cortina.h b/drivers/i2c/i2c-cortina.h
> new file mode 100644
> index 0000000..f1c3dc7
> --- /dev/null
> +++ b/drivers/i2c/i2c-cortina.h
> @@ -0,0 +1,92 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2019
> + * Cortina Access, <www.cortina-access.com>
> + */
> +
> +#ifndef __CA_I2C_H_
> +#define __CA_I2C_H_
> +
> +#if !defined(__ASSEMBLER__) && !defined(__ASSEMBLY__)
> +struct i2c_regs {
> +	u32 i2c_cfg;
> +	u32 i2c_ctrl;
> +	u32 i2c_txr;
> +	u32 i2c_rxr;
> +	u32 i2c_ack;
> +	u32 i2c_ie0;
> +	u32 i2c_int0;
> +	u32 i2c_ie1;
> +	u32 i2c_int1;
> +	u32 i2c_stat;
> +};
> +
> +union ca_biw_cfg {
> +	struct biw_cfg {
> +		u32 core_en		: 1;
> +		u32 biw_soft_reset	: 1;
> +		u32 busywait_en		: 1;
> +		u32 stretch_en		: 1;
> +		u32 arb_en		: 1;
> +		u32 clksync_en		: 1;
> +		u32 rsrvd1		: 2;
> +		u32 spike_cnt		: 4;
> +		u32 rsrvd2		: 4;
> +		u32 prer		: 16;
> +	} bf;
> +	unsigned int wrd;
> +};
> +
> +union ca_biw_ctrl {
> +	struct biw_ctrl {
> +		u32 biwdone	: 1;
> +		u32 rsrvd1	: 2;
> +		u32 ack_in	: 1;
> +		u32 write	: 1;
> +		u32 read	: 1;
> +		u32 stop	: 1;
> +		u32 start	: 1;
> +		u32 rsrvd2	: 24;
> +	} bf;
> +	unsigned int wrd;
> +};
> +
> +union ca_biw_ack {
> +	struct biw_ack {
> +		u32 al		:1;
> +		u32 biw_busy	:1;
> +		u32 ack_out	:1;
> +		u32 rsrvd1	:29;
> +	} bf;
> +	unsigned int wrd;
> +};
> +#endif /* !__ASSEMBLER__*/
> +
> +struct ca_i2c {
> +	struct i2c_regs *regs;
> +	unsigned int speed;
> +};
> +
> +#define I2C_CMD_WT			0
> +#define I2C_CMD_RD			1
> +
> +#define BIW_CTRL_DONE		BIT(0)
> +#define BIW_CTRL_ACK_IN		BIT(3)
> +#define BIW_CTRL_WRITE		BIT(4)
> +#define BIW_CTRL_READ		BIT(5)
> +#define BIW_CTRL_STOP		BIT(6)
> +#define BIW_CTRL_START		BIT(7)
> +
> +#define I2C_BYTE_TO		(CONFIG_SYS_HZ / 500)
> +#define I2C_STOPDET_TO		(CONFIG_SYS_HZ / 500)
> +#define I2C_BYTE_TO_BB		(10)
> +
> +#define IC_SPEED_MODE_STANDARD	1
> +#define IC_SPEED_MODE_FAST	2
> +#define IC_SPEED_MODE_MAX	3
> +
> +#define I2C_MAX_SPEED		1000000
> +#define I2C_FAST_SPEED		400000
> +#define I2C_STANDARD_SPEED	100000
> +

Not needed, could you please use:

https://gitlab.denx.de/u-boot/u-boot/-/blob/master/include/i2c.h#L44

> +#endif							/* __CA_I2C_H_ */
> 

Thanks!

bye,
Heiko
-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs at denx.de

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v2 5/8] led: led_cortina: Add CAxxx LED support
  2020-03-20  0:57 ` [PATCH v2 5/8] led: led_cortina: Add CAxxx LED support Alex Nemirovsky
@ 2020-03-23 15:37   ` Simon Glass
  0 siblings, 0 replies; 18+ messages in thread
From: Simon Glass @ 2020-03-23 15:37 UTC (permalink / raw)
  To: u-boot

Hi Alex,

On Thu, 19 Mar 2020 at 18:57, Alex Nemirovsky
<alex.nemirovsky@cortina-access.com> wrote:
>
> From: Jway Lin <jway.lin@cortina-access.com>
>
> Add Cortina Access LED controller support for CAxxxx SOCs
>
> Signed-off-by: Jway Lin <jway.lin@cortina-access.com>
> Signed-off-by: Alex Nemirovsky <alex.nemirovsky@cortina-access.com>
> CC: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  MAINTAINERS               |   2 +
>  drivers/led/Kconfig       |   8 ++
>  drivers/led/Makefile      |   1 +
>  drivers/led/led_cortina.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 319 insertions(+)
>  create mode 100644 drivers/led/led_cortina.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index b147faa..24a2655 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -183,6 +183,7 @@ F:  drivers/serial/serial_cortina.c
>  F:     drivers/mmc/ca_dw_mmc.c
>  F:     drivers/i2c/i2c-cortina.c
>  F:     drivers/i2c/i2c-cortina.h
> +F:     drivers/led/led_cortina.c
>
>  ARM/CZ.NIC TURRIS MOX SUPPORT
>  M:     Marek Behun <marek.behun@nic.cz>
> @@ -676,6 +677,7 @@ F:  drivers/serial/serial_cortina.c
>  F:     drivers/mmc/ca_dw_mmc.c
>  F:     drivers/i2c/i2c-cortina.c
>  F:     drivers/i2c/i2c-cortina.h
> +F:     drivers/led/led_cortina.c
>
>  MIPS MSCC
>  M:     Gregory CLEMENT <gregory.clement@bootlin.com>
> diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig
> index 6675934..cc87fbf 100644
> --- a/drivers/led/Kconfig
> +++ b/drivers/led/Kconfig
> @@ -35,6 +35,14 @@ config LED_BCM6858
>           This option enables support for LEDs connected to the BCM6858
>           HW has blinking capabilities and up to 32 LEDs can be controlled.
>
> +config LED_CORTINA
> +       bool "LED Support for Cortina Access CAxxxx SoCs"
> +       depends on LED && (CORTINA_PLATFORM)
> +       help
> +         This option enables support for LEDs connected to the Cortina
> +         Access CAxxxx SOCs.
> +
> +
>  config LED_BLINK
>         bool "Support LED blinking"
>         depends on LED
> diff --git a/drivers/led/Makefile b/drivers/led/Makefile
> index 3654dd3..8e3ae7f 100644
> --- a/drivers/led/Makefile
> +++ b/drivers/led/Makefile
> @@ -8,3 +8,4 @@ obj-$(CONFIG_LED_BCM6328) += led_bcm6328.o
>  obj-$(CONFIG_LED_BCM6358) += led_bcm6358.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_cortina.c b/drivers/led/led_cortina.c
> new file mode 100644
> index 0000000..53435e8
> --- /dev/null
> +++ b/drivers/led/led_cortina.c
> @@ -0,0 +1,308 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +
> +/*
> + * Copyright (C) 2020 Cortina-Access
> + * Author: Jway Lin <jway.lin@cortina-access.com>
> + *
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <led.h>
> +#include <asm/io.h>
> +#include <dm/lists.h>
> +#include <linux/compat.h>
> +
> +#define CORTINA_LED_NUM        16
> +
> +#define BIT(nr)                        (1UL << (nr))

That is already defined somewhere

> +
> +#define cortina_LED_CONTROL                    0x00

Drop the cortina_ prefix if you can.. It should be upper case. Since
this is local to the file it just adds code.

> +#define cortina_LED_CONFIG_0           0x04
> +#define cortina_LED_CONFIG_1           0x08
> +#define cortina_LED_CONFIG_2           0x0c
> +#define cortina_LED_CONFIG_3           0x10
> +#define cortina_LED_CONFIG_4           0x14
> +#define cortina_LED_CONFIG_5           0x18
> +#define cortina_LED_CONFIG_6           0x1c
> +#define cortina_LED_CONFIG_7           0x20
> +#define cortina_LED_CONFIG_8           0x24
> +#define cortina_LED_CONFIG_9           0x28
> +#define cortina_LED_CONFIG_10          0x2c
> +#define cortina_LED_CONFIG_11          0x30
> +#define cortina_LED_CONFIG_12          0x34
> +#define cortina_LED_CONFIG_13          0x38
> +#define cortina_LED_CONFIG_14          0x3c
> +#define cortina_LED_CONFIG_15          0x40

What are all those used for?

> +
> +#define cortina_LED_MAX_HW_BLINK               127
> +#define cortina_LED_MAX_COUNT          CORTINA_LED_NUM
> +#define cortina_LED_MAX_PORT           8
> +
> +/* LED_CONTROL fields */
> +#define cortina_LED_BLINK_RATE1_OFFSET 0
> +#define cortina_LED_BLINK_RATE1_MASK   0xFF

Lower-case hex

> +#define cortina_LED_BLINK_RATE2_OFFSET 8
> +#define cortina_LED_BLINK_RATE2_MASK   0xFF
> +#define cortina_LED_CLK_TEST           BIT(16)
> +#define cortina_LED_CLK_POLARITY               BIT(17)
> +#define cortina_LED_CLK_TEST_MODE      BIT(16)
> +#define cortina_LED_CLK_TEST_RX_TEST   BIT(30)
> +#define cortina_LED_CLK_TEST_TX_TEST   BIT(31)
> +
> +/* LED_CONFIG fields */
> +#define cortina_LED_EVENT_ON_OFFSET    0
> +#define cortina_LED_EVENT_ON_MASK      0x7
> +#define cortina_LED_EVENT_BLINK_OFFSET 3
> +#define cortina_LED_EVENT_BLINK_MASK   0x7
> +#define cortina_LED_EVENT_OFF_OFFSET   6
> +#define cortina_LED_EVENT_OFF_MASK     0x7
> +#define cortina_LED_OFF_ON_OFFSET      9
> +#define cortina_LED_OFF_ON_MASK                0x3
> +#define cortina_LED_PORT_OFFSET                11
> +#define cortina_LED_PORT_MASK          0x7
> +#define cortina_LED_OFF_VAL            BIT(14)
> +#define cortina_LED_SW_EVENT           BIT(15)
> +#define cortina_LED_BLINK_SEL          BIT(16)
> +

Need a struct comment

> +struct cortina_led_cfg {
> +       void __iomem *regs;
> +       spinlock_t *lock;       /* protect LED resource access */
> +       int idx;
> +       bool active_low;
> +
> +       int off_event;
> +       int blink_event;
> +       int on_event;
> +       int port;
> +       int blink;
> +       int enable;
> +};
> +
> +struct cortina_led_top_cfg {

here too

> +       void __iomem *regs;
> +       u16 blink_rate1;
> +       u16 blink_rate2;
> +};
> +
> +static struct cortina_led_top_cfg glb_led_ctrl;

You are not allowed to use BSS in driver model. It's not clear why you
have two structures as there are no comments. Can you not combine
them?



> +
> +static void cortina_led_write(void __iomem *reg, unsigned long data)
> +{
> +       writel(data, reg);
> +}
> +
> +static unsigned long cortina_led_read(void __iomem *reg)
> +{
> +       return readl(reg);
> +}
> +
> +static enum led_state_t cortina_led_get_state(struct udevice *dev)
> +{
> +       struct cortina_led_cfg *priv = dev_get_priv(dev);
> +       enum led_state_t state = LEDST_OFF;
> +       u32 val;
> +
> +       val = readl(priv->regs);
> +
> +       if (val & cortina_LED_SW_EVENT)
> +               state = LEDST_ON;
> +
> +       return state;
> +}
> +
> +static int cortina_led_set_state(struct udevice *dev, enum led_state_t state)
> +{
> +       u32 val;
> +       struct cortina_led_cfg *priv = dev_get_priv(dev);
> +
> +       val = readl(priv->regs);
> +
> +       switch (state) {
> +       case LEDST_OFF:
> +               val &= ~cortina_LED_SW_EVENT;
> +               val &= ~(cortina_LED_OFF_ON_MASK << cortina_LED_OFF_ON_OFFSET);
> +               val |= 0x3 << cortina_LED_OFF_ON_OFFSET;
> +               cortina_led_write(priv->regs, val);
> +               break;
> +       case LEDST_ON:
> +               val |= cortina_LED_SW_EVENT;
> +               val &= ~(cortina_LED_OFF_ON_MASK << cortina_LED_OFF_ON_OFFSET);
> +               val |= 0x1 << cortina_LED_OFF_ON_OFFSET;
> +               cortina_led_write(priv->regs, val);
> +               break;
> +       case LEDST_TOGGLE:
> +               if (cortina_led_get_state(dev) == LEDST_OFF)
> +                       return cortina_led_set_state(dev, LEDST_ON);
> +               else
> +                       return cortina_led_set_state(dev, LEDST_OFF);
> +               break;
> +
> +       default:
> +               return -EINVAL;
> +       }
> +
> +       return 0;
> +}
> +
> +static const struct led_ops cortina_led_ops = {
> +       .get_state = cortina_led_get_state,
> +       .set_state = cortina_led_set_state,
> +};
> +
> +static int cortina_led_probe(struct udevice *dev)
> +{
> +       struct led_uc_plat *uc_plat = dev_get_uclass_platdata(dev);
> +       void __iomem *regs;
> +       u32 reg_value, val;
> +       u16 rate1, rate2;
> +       struct cortina_led_cfg *priv = dev_get_priv(dev);
> +       unsigned int pin;
> +       u32 blink, port, off_event, blink_event, on_event;
> +
> +       /* Top-level LED node */
> +       if (!uc_plat->label) {
> +               regs = dev_remap_addr(dev);
> +
> +       if (!regs)
> +               return -EINVAL;
> +
> +       glb_led_ctrl.regs = regs;
> +
> +       reg_value = 0;
> +       reg_value |= cortina_LED_CLK_POLARITY;
> +
> +       rate1 = dev_read_u32_default(dev, "cortina, blink_rate1", 256);
> +       rate2 = dev_read_u32_default(dev, "cortina, blink_rate2", 512);

Strictly speaking you should read your platdata into a plat struct in
your ofdata_to_platdata method.

Also do you have a binding file for this? I think we sholld use hyphen
for properties instead of underscore.

> +
> +       val = rate1 / 16 - 1;
> +       glb_led_ctrl.blink_rate1 = val > cortina_LED_MAX_HW_BLINK ?
> +                           cortina_LED_MAX_HW_BLINK : val;
> +       reg_value |= (glb_led_ctrl.blink_rate1 & cortina_LED_BLINK_RATE1_MASK)
> +                       << cortina_LED_BLINK_RATE1_OFFSET;
> +
> +       val = rate2 / 16 - 1;
> +       glb_led_ctrl.blink_rate2 = val > cortina_LED_MAX_HW_BLINK ?
> +                               cortina_LED_MAX_HW_BLINK : val;
> +       reg_value |= (glb_led_ctrl.blink_rate2 & cortina_LED_BLINK_RATE2_MASK)
> +                       << cortina_LED_BLINK_RATE2_OFFSET;
> +
> +       cortina_led_write(glb_led_ctrl.regs, reg_value);
> +       } else {
> +               regs = dev_remap_addr(dev_get_parent(dev));
> +
> +       if (!regs)
> +               return -EINVAL;
> +
> +       pin = dev_read_u32_default(dev, "pin", cortina_LED_MAX_COUNT);
> +
> +       if (pin >= cortina_LED_MAX_COUNT)
> +               return -EINVAL;
> +
> +       priv->regs = regs + 4 + (pin * 4);
> +
> +       val = cortina_led_read(priv->regs);
> +
> +       if (dev_read_bool(dev, "active-low")) {
> +               priv->active_low = true;
> +               val |= cortina_LED_OFF_VAL;
> +       } else {
> +               priv->active_low = false;
> +               val &= ~cortina_LED_OFF_VAL;
> +       }
> +
> +       blink = dev_read_u32_default(dev, "blink-sel", 0);
> +
> +       if (blink == 0) {
> +               priv->blink = 0;
> +               val &= ~cortina_LED_BLINK_SEL;
> +       } else if (blink == 1) {
> +               priv->blink = 1;
> +               val |= cortina_LED_BLINK_SEL;
> +       }
> +
> +       //Todo : cortina_led_config();
> +       off_event = dev_read_u32_default(dev, "off-event", 3);
> +       val &= ~(cortina_LED_EVENT_OFF_MASK << cortina_LED_EVENT_OFF_OFFSET);
> +       if (off_event != 3) {
> +               priv->off_event = off_event;
> +               val |= BIT(off_event) << cortina_LED_EVENT_OFF_OFFSET;
> +       }
> +
> +       blink_event = dev_read_u32_default(dev, "blink-event", 3);
> +       val &= ~(cortina_LED_EVENT_BLINK_MASK <<
> +                cortina_LED_EVENT_BLINK_OFFSET);
> +
> +       if (blink_event != 3) {
> +               priv->blink_event = blink_event;
> +               val |= BIT(blink_event) << cortina_LED_EVENT_BLINK_OFFSET;
> +       }
> +
> +       on_event = dev_read_u32_default(dev, "on-event", 3);
> +       val &= ~(cortina_LED_EVENT_ON_MASK << cortina_LED_EVENT_ON_OFFSET);
> +       if (on_event != 3) {
> +               priv->on_event = on_event;
> +               val |= BIT(on_event) << cortina_LED_EVENT_ON_OFFSET;
> +       }
> +
> +       port = dev_read_u32_default(dev, "port", 0);
> +       priv->port = port;
> +       val &= ~(cortina_LED_PORT_MASK << cortina_LED_PORT_OFFSET);
> +       val |= port << cortina_LED_PORT_OFFSET;
> +
> +       priv->enable = 0;
> +
> +       /* force off */
> +       val &= ~(cortina_LED_OFF_ON_MASK << cortina_LED_OFF_ON_OFFSET);
> +       val |= 0x3 << cortina_LED_OFF_ON_OFFSET;
> +
> +       cortina_led_write(priv->regs, val);
> +       }

funny indent?

> +
> +       return 0;
> +}
> +
> +static int cortina_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, "ca-leds",
> +                                                ofnode_get_name(node),
> +                                                node, &dev);

Does device_bind_ofnode() help here?

> +               if (ret)
> +                       return ret;
> +               uc_plat = dev_get_uclass_platdata(dev);
> +               uc_plat->label = label;
> +       }
> +
> +       return 0;
> +}
> +
> +static const struct udevice_id ca_led_ids[] = {
> +       { .compatible = "cortina,ca-leds" },
> +       { /* sentinel */ }
> +};
> +
> +U_BOOT_DRIVER(cortina_led) = {
> +       .name = "ca-leds",
> +       .id = UCLASS_LED,
> +       .of_match = ca_led_ids,
> +       .bind = cortina_led_bind,
> +       .probe = cortina_led_probe,
> +       .priv_auto_alloc_size = sizeof(struct cortina_led_cfg),
> +       .ops = &cortina_led_ops,
> +};
> --
> 2.7.4
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v2 6/8] board: presidio: add LED support
  2020-03-20  0:57 ` [PATCH v2 6/8] board: presidio: add " Alex Nemirovsky
@ 2020-03-23 15:37   ` Simon Glass
  0 siblings, 0 replies; 18+ messages in thread
From: Simon Glass @ 2020-03-23 15:37 UTC (permalink / raw)
  To: u-boot

On Thu, 19 Mar 2020 at 18:57, Alex Nemirovsky
<alex.nemirovsky@cortina-access.com> wrote:
>
> From: Jway Lin <jway.lin@cortina-access.com>
>
> Add LED support for Cortina Access Presidio Engineering Board
>
> Signed-off-by: Jway Lin <jway.lin@cortina-access.com>
> Signed-off-by: Alex Nemirovsky <alex.nemirovsky@cortina-access.com>
> CC: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/arm/dts/ca-presidio-engboard.dts        | 31 ++++++++++++++++++++++++++++
>  configs/cortina_presidio-asic-emmc_defconfig |  2 ++
>  2 files changed, 33 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v2 1/8] mmc: ca_dw_mmc: add DesignWare based DM support for CAxxxx SoCs
  2020-03-20  0:57 ` [PATCH v2 1/8] mmc: ca_dw_mmc: add DesignWare based DM support for CAxxxx SoCs Alex Nemirovsky
@ 2020-03-24  7:16   ` Jaehoon Chung
  2020-03-24 21:18     ` Alex Nemirovsky
  0 siblings, 1 reply; 18+ messages in thread
From: Jaehoon Chung @ 2020-03-24  7:16 UTC (permalink / raw)
  To: u-boot

Hi,

On 3/20/20 9:57 AM, Alex Nemirovsky wrote:
> From: Arthur Li <arthur.li@cortina-access.com>
> 
> Initial DesignWare based DM support for Cortina Access CAxxxx SoCs.
> 
> Signed-off-by: Arthur Li <arthur.li@cortina-access.com>
> Signed-off-by: Alex Nemirovsky <alex.nemirovsky@cortina-access.com>
> CC: Peng Fan <peng.fan@nxp.com>

I didn't receive any reply about my previous comments.
And Is there patch v3 or v2? Subject is v2..but change log is v3.
What is correct version?

Best Regards,
Jaehoon Chung

> 
> ---
> 
> Changes in v3: None
> Changes in v2:
> - Add I2C controller
> - Add LED controller
> - Add SPI NAND and NOR controller
> 
>  MAINTAINERS             |   2 +
>  drivers/mmc/Kconfig     |  11 +++
>  drivers/mmc/Makefile    |   1 +
>  drivers/mmc/ca_dw_mmc.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 195 insertions(+)
>  create mode 100644 drivers/mmc/ca_dw_mmc.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 82e4159..bb45d3c 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -180,6 +180,7 @@ F:	board/cortina/common/
>  F:	drivers/gpio/cortina_gpio.c
>  F:	drivers/watchdog/cortina_wdt.c
>  F:	drivers/serial/serial_cortina.c
> +F:	drivers/mmc/ca_dw_mmc.c
>  
>  ARM/CZ.NIC TURRIS MOX SUPPORT
>  M:	Marek Behun <marek.behun@nic.cz>
> @@ -670,6 +671,7 @@ F:	board/cortina/common/
>  F:	drivers/gpio/cortina_gpio.c
>  F:	drivers/watchdog/cortina_wdt.c
>  F:	drivers/serial/serial_cortina.c
> +F:	drivers/mmc/ca_dw_mmc.c
>  
>  MIPS MSCC
>  M:	Gregory CLEMENT <gregory.clement@bootlin.com>
> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
> index 2f0eedc..bb38787 100644
> --- a/drivers/mmc/Kconfig
> +++ b/drivers/mmc/Kconfig
> @@ -205,6 +205,17 @@ config MMC_DW
>  	  block, this provides host support for SD and MMC interfaces, in both
>  	  PIO, internal DMA mode and external DMA mode.
>  
> +config MMC_DW_CORTINA
> +	bool "Cortina specific extensions for Synopsys DW Memory Card Interface"
> +	depends on DM_MMC
> +	depends on MMC_DW
> +	depends on BLK
> +	default n
> +	help
> +	  This selects support for Cortina SoC specific extensions to the
> +	  Synopsys DesignWare Memory Card Interface driver. Select this option
> +	  for platforms based on Cortina CAxxxx Soc's.
> +
>  config MMC_DW_EXYNOS
>  	bool "Exynos specific extensions for Synopsys DW Memory Card Interface"
>  	depends on ARCH_EXYNOS
> diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
> index 9c1f8e5..615b724 100644
> --- a/drivers/mmc/Makefile
> +++ b/drivers/mmc/Makefile
> @@ -20,6 +20,7 @@ endif
>  obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o
>  obj-$(CONFIG_MMC_DAVINCI)		+= davinci_mmc.o
>  obj-$(CONFIG_MMC_DW)			+= dw_mmc.o
> +obj-$(CONFIG_MMC_DW_CORTINA)		+= ca_dw_mmc.o
>  obj-$(CONFIG_MMC_DW_EXYNOS)		+= exynos_dw_mmc.o
>  obj-$(CONFIG_MMC_DW_K3)			+= hi6220_dw_mmc.o
>  obj-$(CONFIG_MMC_DW_ROCKCHIP)		+= rockchip_dw_mmc.o
> diff --git a/drivers/mmc/ca_dw_mmc.c b/drivers/mmc/ca_dw_mmc.c
> new file mode 100644
> index 0000000..acbc850
> --- /dev/null
> +++ b/drivers/mmc/ca_dw_mmc.c
> @@ -0,0 +1,181 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2019 Cortina Access
> + * Arthur Li <arthur.li@cortina-access.com>
> + */
> +
> +#include <common.h>
> +#include <dwmmc.h>
> +#include <fdtdec.h>
> +#include <linux/libfdt.h>
> +#include <malloc.h>
> +#include <errno.h>
> +#include <dm.h>
> +#include <mapmem.h>
> +
> +#define SD_CLK_SEL_MASK (0x3)
> +#define SD_DLL_DEFAULT  (0x143000)
> +#define SD_SCLK_MAX (200000000)
> +
> +#define SD_CLK_SEL_200MHZ (0x2)
> +#define SD_CLK_SEL_100MHZ (0x1)
> +
> +#define IO_DRV_SD_DS_OFFSET (16)
> +#define IO_DRV_SD_DS_MASK   (0xff << IO_DRV_SD_DS_OFFSET)
> +
> +#define MIN_FREQ (400000)
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct ca_mmc_plat {
> +	struct mmc_config cfg;
> +	struct mmc mmc;
> +};
> +
> +struct ca_dwmmc_priv_data {
> +	struct dwmci_host host;
> +	void __iomem *sd_dll_reg;
> +	void __iomem *io_drv_reg;
> +	u8 ds;
> +};
> +
> +static void ca_dwmci_clksel(struct dwmci_host *host)
> +{
> +	struct ca_dwmmc_priv_data *priv = host->priv;
> +	u32 val = readl(priv->sd_dll_reg);
> +
> +	if (host->bus_hz >= 200000000) {
> +		val &= ~SD_CLK_SEL_MASK;
> +		val |= SD_CLK_SEL_200MHZ;
> +	} else if (host->bus_hz >= 100000000) {
> +		val &= ~SD_CLK_SEL_MASK;
> +		val |= SD_CLK_SEL_100MHZ;
> +	} else {
> +		val &= ~SD_CLK_SEL_MASK;
> +	}
> +
> +	writel(val, priv->sd_dll_reg);
> +}
> +
> +static void ca_dwmci_board_init(struct dwmci_host *host)
> +{
> +	struct ca_dwmmc_priv_data *priv = host->priv;
> +	u32 val = readl(priv->io_drv_reg);
> +
> +	writel(SD_DLL_DEFAULT, priv->sd_dll_reg);
> +
> +	val &= ~IO_DRV_SD_DS_MASK;
> +	if (priv && priv->ds)
> +		val |= priv->ds << IO_DRV_SD_DS_OFFSET;
> +	writel(val, priv->io_drv_reg);
> +}
> +
> +unsigned int ca_dwmci_get_mmc_clock(struct dwmci_host *host, uint freq)
> +{
> +	struct ca_dwmmc_priv_data *priv = host->priv;
> +	u8 sd_clk_sel = readl(priv->sd_dll_reg) & SD_CLK_SEL_MASK;
> +	u8 clk_div;
> +
> +	switch (sd_clk_sel) {
> +	case 2:
> +		clk_div = 1;
> +		break;
> +	case 1:
> +		clk_div = 2;
> +		break;
> +	default:
> +		clk_div = 4;
> +	}
> +
> +	return SD_SCLK_MAX / clk_div / (host->div + 1);
> +}
> +
> +static int ca_dwmmc_ofdata_to_platdata(struct udevice *dev)
> +{
> +	struct ca_dwmmc_priv_data *priv = dev_get_priv(dev);
> +	struct dwmci_host *host = &priv->host;
> +	u32 tmp;
> +
> +	host->name = dev->name;
> +	host->dev_index = 0;
> +
> +	host->buswidth = dev_read_u32_default(dev, "bus-width", 1);
> +	if (host->buswidth != 1 && host->buswidth != 4)
> +		return -EINVAL;
> +
> +	host->bus_hz = dev_read_u32_default(dev, "max-frequency", 50000000);
> +	priv->ds = dev_read_u32_default(dev, "io_ds", 0x33);
> +	host->fifo_mode = dev_read_bool(dev, "fifo-mode");
> +
> +	dev_read_u32(dev, "sd_dll_ctrl", &tmp);
> +	priv->sd_dll_reg = map_sysmem((uintptr_t)tmp, sizeof(uintptr_t));
> +	if (!priv->sd_dll_reg)
> +		return -EINVAL;
> +
> +	dev_read_u32(dev, "io_drv_ctrl", &tmp);
> +	priv->io_drv_reg = map_sysmem((uintptr_t)tmp, sizeof(uintptr_t));
> +	if (!priv->io_drv_reg)
> +		return -EINVAL;
> +
> +	host->ioaddr = dev_read_addr_ptr(dev);
> +	if (host->ioaddr == (void *)FDT_ADDR_T_NONE) {
> +		printf("DWMMC: base address is invalid\n");
> +		return -EINVAL;
> +	}
> +
> +	host->priv = priv;
> +
> +	return 0;
> +}
> +
> +struct dm_mmc_ops ca_dwmci_dm_ops;
> +
> +static int ca_dwmmc_probe(struct udevice *dev)
> +{
> +	struct ca_mmc_plat *plat = dev_get_platdata(dev);
> +	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
> +	struct ca_dwmmc_priv_data *priv = dev_get_priv(dev);
> +	struct dwmci_host *host = &priv->host;
> +
> +	memcpy(&ca_dwmci_dm_ops, &dm_dwmci_ops, sizeof(struct dm_mmc_ops));
> +
> +	dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, MIN_FREQ);
> +	if (host->buswidth == 1) {
> +		(&plat->cfg)->host_caps &= ~MMC_MODE_8BIT;
> +		(&plat->cfg)->host_caps &= ~MMC_MODE_4BIT;
> +	}
> +
> +	host->mmc = &plat->mmc;
> +	host->mmc->priv = &priv->host;
> +	upriv->mmc = host->mmc;
> +	host->mmc->dev = dev;
> +	host->clksel = ca_dwmci_clksel;
> +	host->board_init = ca_dwmci_board_init;
> +	host->get_mmc_clk = ca_dwmci_get_mmc_clock;
> +
> +	return dwmci_probe(dev);
> +}
> +
> +static int ca_dwmmc_bind(struct udevice *dev)
> +{
> +	struct ca_mmc_plat *plat = dev_get_platdata(dev);
> +
> +	return dwmci_bind(dev, &plat->mmc, &plat->cfg);
> +}
> +
> +static const struct udevice_id ca_dwmmc_ids[] = {
> +	{ .compatible = "snps,dw-cortina" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(ca_dwmmc_drv) = {
> +	.name		= "cortina_dwmmc",
> +	.id		= UCLASS_MMC,
> +	.of_match	= ca_dwmmc_ids,
> +	.ofdata_to_platdata = ca_dwmmc_ofdata_to_platdata,
> +	.bind		= ca_dwmmc_bind,
> +	.ops		= &ca_dwmci_dm_ops,
> +	.probe		= ca_dwmmc_probe,
> +	.priv_auto_alloc_size	= sizeof(struct ca_dwmmc_priv_data),
> +	.platdata_auto_alloc_size = sizeof(struct ca_mmc_plat),
> +};
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v2 1/8] mmc: ca_dw_mmc: add DesignWare based DM support for CAxxxx SoCs
  2020-03-24  7:16   ` Jaehoon Chung
@ 2020-03-24 21:18     ` Alex Nemirovsky
  0 siblings, 0 replies; 18+ messages in thread
From: Alex Nemirovsky @ 2020-03-24 21:18 UTC (permalink / raw)
  To: u-boot

Hi Jaehoon,
We incorporated your comments locally.  We will release the next series as v4 once all feedback is received
for the rest of the patches in the series. Thank you for your feedback.

-BR
AN

> On Mar 24, 2020, at 12:16 AM, Jaehoon Chung <jh80.chung@samsung.com> wrote:
> 
> Hi,
> 
> On 3/20/20 9:57 AM, Alex Nemirovsky wrote:
>> From: Arthur Li <arthur.li@cortina-access.com>
>> 
>> Initial DesignWare based DM support for Cortina Access CAxxxx SoCs.
>> 
>> Signed-off-by: Arthur Li <arthur.li@cortina-access.com>
>> Signed-off-by: Alex Nemirovsky <alex.nemirovsky@cortina-access.com>
>> CC: Peng Fan <peng.fan@nxp.com>
> 
> I didn't receive any reply about my previous comments.
> And Is there patch v3 or v2? Subject is v2..but change log is v3.
> What is correct version?
> 
> Best Regards,
> Jaehoon Chung
> 
>> 
>> ---
>> 
>> Changes in v3: None
>> Changes in v2:
>> - Add I2C controller
>> - Add LED controller
>> - Add SPI NAND and NOR controller
>> 
>> MAINTAINERS             |   2 +
>> drivers/mmc/Kconfig     |  11 +++
>> drivers/mmc/Makefile    |   1 +
>> drivers/mmc/ca_dw_mmc.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++
>> 4 files changed, 195 insertions(+)
>> create mode 100644 drivers/mmc/ca_dw_mmc.c
>> 
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 82e4159..bb45d3c 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -180,6 +180,7 @@ F:	board/cortina/common/
>> F:	drivers/gpio/cortina_gpio.c
>> F:	drivers/watchdog/cortina_wdt.c
>> F:	drivers/serial/serial_cortina.c
>> +F:	drivers/mmc/ca_dw_mmc.c
>> 
>> ARM/CZ.NIC TURRIS MOX SUPPORT
>> M:	Marek Behun <marek.behun@nic.cz>
>> @@ -670,6 +671,7 @@ F:	board/cortina/common/
>> F:	drivers/gpio/cortina_gpio.c
>> F:	drivers/watchdog/cortina_wdt.c
>> F:	drivers/serial/serial_cortina.c
>> +F:	drivers/mmc/ca_dw_mmc.c
>> 
>> MIPS MSCC
>> M:	Gregory CLEMENT <gregory.clement@bootlin.com>
>> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
>> index 2f0eedc..bb38787 100644
>> --- a/drivers/mmc/Kconfig
>> +++ b/drivers/mmc/Kconfig
>> @@ -205,6 +205,17 @@ config MMC_DW
>> 	  block, this provides host support for SD and MMC interfaces, in both
>> 	  PIO, internal DMA mode and external DMA mode.
>> 
>> +config MMC_DW_CORTINA
>> +	bool "Cortina specific extensions for Synopsys DW Memory Card Interface"
>> +	depends on DM_MMC
>> +	depends on MMC_DW
>> +	depends on BLK
>> +	default n
>> +	help
>> +	  This selects support for Cortina SoC specific extensions to the
>> +	  Synopsys DesignWare Memory Card Interface driver. Select this option
>> +	  for platforms based on Cortina CAxxxx Soc's.
>> +
>> config MMC_DW_EXYNOS
>> 	bool "Exynos specific extensions for Synopsys DW Memory Card Interface"
>> 	depends on ARCH_EXYNOS
>> diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
>> index 9c1f8e5..615b724 100644
>> --- a/drivers/mmc/Makefile
>> +++ b/drivers/mmc/Makefile
>> @@ -20,6 +20,7 @@ endif
>> obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o
>> obj-$(CONFIG_MMC_DAVINCI)		+= davinci_mmc.o
>> obj-$(CONFIG_MMC_DW)			+= dw_mmc.o
>> +obj-$(CONFIG_MMC_DW_CORTINA)		+= ca_dw_mmc.o
>> obj-$(CONFIG_MMC_DW_EXYNOS)		+= exynos_dw_mmc.o
>> obj-$(CONFIG_MMC_DW_K3)			+= hi6220_dw_mmc.o
>> obj-$(CONFIG_MMC_DW_ROCKCHIP)		+= rockchip_dw_mmc.o
>> diff --git a/drivers/mmc/ca_dw_mmc.c b/drivers/mmc/ca_dw_mmc.c
>> new file mode 100644
>> index 0000000..acbc850
>> --- /dev/null
>> +++ b/drivers/mmc/ca_dw_mmc.c
>> @@ -0,0 +1,181 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * (C) Copyright 2019 Cortina Access
>> + * Arthur Li <arthur.li@cortina-access.com>
>> + */
>> +
>> +#include <common.h>
>> +#include <dwmmc.h>
>> +#include <fdtdec.h>
>> +#include <linux/libfdt.h>
>> +#include <malloc.h>
>> +#include <errno.h>
>> +#include <dm.h>
>> +#include <mapmem.h>
>> +
>> +#define SD_CLK_SEL_MASK (0x3)
>> +#define SD_DLL_DEFAULT  (0x143000)
>> +#define SD_SCLK_MAX (200000000)
>> +
>> +#define SD_CLK_SEL_200MHZ (0x2)
>> +#define SD_CLK_SEL_100MHZ (0x1)
>> +
>> +#define IO_DRV_SD_DS_OFFSET (16)
>> +#define IO_DRV_SD_DS_MASK   (0xff << IO_DRV_SD_DS_OFFSET)
>> +
>> +#define MIN_FREQ (400000)
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +struct ca_mmc_plat {
>> +	struct mmc_config cfg;
>> +	struct mmc mmc;
>> +};
>> +
>> +struct ca_dwmmc_priv_data {
>> +	struct dwmci_host host;
>> +	void __iomem *sd_dll_reg;
>> +	void __iomem *io_drv_reg;
>> +	u8 ds;
>> +};
>> +
>> +static void ca_dwmci_clksel(struct dwmci_host *host)
>> +{
>> +	struct ca_dwmmc_priv_data *priv = host->priv;
>> +	u32 val = readl(priv->sd_dll_reg);
>> +
>> +	if (host->bus_hz >= 200000000) {
>> +		val &= ~SD_CLK_SEL_MASK;
>> +		val |= SD_CLK_SEL_200MHZ;
>> +	} else if (host->bus_hz >= 100000000) {
>> +		val &= ~SD_CLK_SEL_MASK;
>> +		val |= SD_CLK_SEL_100MHZ;
>> +	} else {
>> +		val &= ~SD_CLK_SEL_MASK;
>> +	}
>> +
>> +	writel(val, priv->sd_dll_reg);
>> +}
>> +
>> +static void ca_dwmci_board_init(struct dwmci_host *host)
>> +{
>> +	struct ca_dwmmc_priv_data *priv = host->priv;
>> +	u32 val = readl(priv->io_drv_reg);
>> +
>> +	writel(SD_DLL_DEFAULT, priv->sd_dll_reg);
>> +
>> +	val &= ~IO_DRV_SD_DS_MASK;
>> +	if (priv && priv->ds)
>> +		val |= priv->ds << IO_DRV_SD_DS_OFFSET;
>> +	writel(val, priv->io_drv_reg);
>> +}
>> +
>> +unsigned int ca_dwmci_get_mmc_clock(struct dwmci_host *host, uint freq)
>> +{
>> +	struct ca_dwmmc_priv_data *priv = host->priv;
>> +	u8 sd_clk_sel = readl(priv->sd_dll_reg) & SD_CLK_SEL_MASK;
>> +	u8 clk_div;
>> +
>> +	switch (sd_clk_sel) {
>> +	case 2:
>> +		clk_div = 1;
>> +		break;
>> +	case 1:
>> +		clk_div = 2;
>> +		break;
>> +	default:
>> +		clk_div = 4;
>> +	}
>> +
>> +	return SD_SCLK_MAX / clk_div / (host->div + 1);
>> +}
>> +
>> +static int ca_dwmmc_ofdata_to_platdata(struct udevice *dev)
>> +{
>> +	struct ca_dwmmc_priv_data *priv = dev_get_priv(dev);
>> +	struct dwmci_host *host = &priv->host;
>> +	u32 tmp;
>> +
>> +	host->name = dev->name;
>> +	host->dev_index = 0;
>> +
>> +	host->buswidth = dev_read_u32_default(dev, "bus-width", 1);
>> +	if (host->buswidth != 1 && host->buswidth != 4)
>> +		return -EINVAL;
>> +
>> +	host->bus_hz = dev_read_u32_default(dev, "max-frequency", 50000000);
>> +	priv->ds = dev_read_u32_default(dev, "io_ds", 0x33);
>> +	host->fifo_mode = dev_read_bool(dev, "fifo-mode");
>> +
>> +	dev_read_u32(dev, "sd_dll_ctrl", &tmp);
>> +	priv->sd_dll_reg = map_sysmem((uintptr_t)tmp, sizeof(uintptr_t));
>> +	if (!priv->sd_dll_reg)
>> +		return -EINVAL;
>> +
>> +	dev_read_u32(dev, "io_drv_ctrl", &tmp);
>> +	priv->io_drv_reg = map_sysmem((uintptr_t)tmp, sizeof(uintptr_t));
>> +	if (!priv->io_drv_reg)
>> +		return -EINVAL;
>> +
>> +	host->ioaddr = dev_read_addr_ptr(dev);
>> +	if (host->ioaddr == (void *)FDT_ADDR_T_NONE) {
>> +		printf("DWMMC: base address is invalid\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	host->priv = priv;
>> +
>> +	return 0;
>> +}
>> +
>> +struct dm_mmc_ops ca_dwmci_dm_ops;
>> +
>> +static int ca_dwmmc_probe(struct udevice *dev)
>> +{
>> +	struct ca_mmc_plat *plat = dev_get_platdata(dev);
>> +	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
>> +	struct ca_dwmmc_priv_data *priv = dev_get_priv(dev);
>> +	struct dwmci_host *host = &priv->host;
>> +
>> +	memcpy(&ca_dwmci_dm_ops, &dm_dwmci_ops, sizeof(struct dm_mmc_ops));
>> +
>> +	dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, MIN_FREQ);
>> +	if (host->buswidth == 1) {
>> +		(&plat->cfg)->host_caps &= ~MMC_MODE_8BIT;
>> +		(&plat->cfg)->host_caps &= ~MMC_MODE_4BIT;
>> +	}
>> +
>> +	host->mmc = &plat->mmc;
>> +	host->mmc->priv = &priv->host;
>> +	upriv->mmc = host->mmc;
>> +	host->mmc->dev = dev;
>> +	host->clksel = ca_dwmci_clksel;
>> +	host->board_init = ca_dwmci_board_init;
>> +	host->get_mmc_clk = ca_dwmci_get_mmc_clock;
>> +
>> +	return dwmci_probe(dev);
>> +}
>> +
>> +static int ca_dwmmc_bind(struct udevice *dev)
>> +{
>> +	struct ca_mmc_plat *plat = dev_get_platdata(dev);
>> +
>> +	return dwmci_bind(dev, &plat->mmc, &plat->cfg);
>> +}
>> +
>> +static const struct udevice_id ca_dwmmc_ids[] = {
>> +	{ .compatible = "snps,dw-cortina" },
>> +	{ }
>> +};
>> +
>> +U_BOOT_DRIVER(ca_dwmmc_drv) = {
>> +	.name		= "cortina_dwmmc",
>> +	.id		= UCLASS_MMC,
>> +	.of_match	= ca_dwmmc_ids,
>> +	.ofdata_to_platdata = ca_dwmmc_ofdata_to_platdata,
>> +	.bind		= ca_dwmmc_bind,
>> +	.ops		= &ca_dwmci_dm_ops,
>> +	.probe		= ca_dwmmc_probe,
>> +	.priv_auto_alloc_size	= sizeof(struct ca_dwmmc_priv_data),
>> +	.platdata_auto_alloc_size = sizeof(struct ca_mmc_plat),
>> +};
>> 
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v2 0/8] Cortina Access Drivers Package 2
  2020-03-19  0:16 ` Alex Nemirovsky
@ 2020-03-19 10:16   ` Daniel Schwierzeck
  0 siblings, 0 replies; 18+ messages in thread
From: Daniel Schwierzeck @ 2020-03-19 10:16 UTC (permalink / raw)
  To: u-boot

Hi Alex,

you should always CC the maintainers of the affected sub-systems or
architecture. Otherwise it's random if a maintainer reads through the
list and discovers your patches ;)

You can find out with get_maintainers.pl like this:

$ ./scripts/get_maintainer.pl drivers/i2c/
Heiko Schocher <hs@denx.de> (maintainer:I2C)
u-boot at lists.denx.de (open list)


Am 19.03.20 um 01:16 schrieb Alex Nemirovsky:
> Hi Tom,
> Are we still blocked on this set until the upcoming 2020.4 release?  
> 
>> On Feb 26, 2020, at 11:58 PM, Alex Nemirovsky <alex.nemirovsky@cortina-access.com> wrote:
>>
>>
>> This release adds the following drivers and
>> integrates support  into the Cortina Access
>> Presidio Engineering Board:
>>
>> CAxxxx SoC eMMC/SD controller
>> CAxxxx SoC I2C controller
>> CAxxxx Soc LED controller
>> CAxxxx SPI NAND and NOR controller
>>
>> Changes in v2:
>> - Add I2C controller
>> - Add LED controller
>> - Add SPI NAND and NOR controller
>>
>> Alex Nemirovsky (3):
>>  board: presidio-asic: Add eMMC board support
>>  board: presidio-asic: Add I2C support
>>  board: presidio-asic: Add SPI NAND and NOR support
>>
>> Arthur Li (2):
>>  mmc: ca_dw_mmc: add DesignWare based DM support for CAxxxx SoCs
>>  i2c: i2c-cortina: added CAxxxx I2C support
>>
>> Jway Lin (2):
>>  led: led_cortina: Add CAxxx LED support
>>  board: presidio: add LED support
>>
>> Pengpeng Chen (1):
>>  spi: ca_sflash: Add CAxxxx SPI Flash Controller
>>
>> MAINTAINERS                                      |  10 +
>> arch/arm/dts/ca-presidio-engboard.dts            |  39 +-
>> board/cortina/presidio-asic/presidio.c           |  16 +-
>> configs/cortina_presidio-asic-emmc_defconfig     |  38 ++
>> configs/cortina_presidio-asic-spi-nand_defconfig |  48 ++
>> configs/cortina_presidio-asic-spi-nor_defconfig  |  59 +++
>> drivers/i2c/Kconfig                              |   7 +
>> drivers/i2c/Makefile                             |   1 +
>> drivers/i2c/i2c-cortina.c                        | 346 ++++++++++++++
>> drivers/i2c/i2c-cortina.h                        |  92 ++++
>> drivers/led/Kconfig                              |   8 +
>> drivers/led/Makefile                             |   1 +
>> drivers/led/led_cortina.c                        | 308 ++++++++++++
>> drivers/mmc/Kconfig                              |  11 +
>> drivers/mmc/Makefile                             |   1 +
>> drivers/mmc/ca_dw_mmc.c                          | 181 +++++++
>> drivers/spi/Kconfig                              |   8 +
>> drivers/spi/Makefile                             |   1 +
>> drivers/spi/ca_sflash.c                          | 575 +++++++++++++++++++++++
>> 19 files changed, 1744 insertions(+), 6 deletions(-)
>> create mode 100644 configs/cortina_presidio-asic-emmc_defconfig
>> create mode 100644 configs/cortina_presidio-asic-spi-nand_defconfig
>> create mode 100644 configs/cortina_presidio-asic-spi-nor_defconfig
>> create mode 100644 drivers/i2c/i2c-cortina.c
>> create mode 100644 drivers/i2c/i2c-cortina.h
>> create mode 100644 drivers/led/led_cortina.c
>> create mode 100644 drivers/mmc/ca_dw_mmc.c
>> create mode 100644 drivers/spi/ca_sflash.c
>>
>> -- 
>> 2.7.4
>>
> 

-- 
- Daniel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v2 0/8] Cortina Access Drivers Package 2
@ 2020-03-19  1:52 Alex Nemirovsky
  0 siblings, 0 replies; 18+ messages in thread
From: Alex Nemirovsky @ 2020-03-19  1:52 UTC (permalink / raw)
  To: u-boot


This release adds the following drivers and
integrates support  into the Cortina Access
Presidio Engineering Board:

CAxxxx SoC eMMC/SD controller
CAxxxx SoC I2C controller
CAxxxx Soc LED controller
CAxxxx SPI NAND and NOR controller

Changes in v3:
- Fixup syntax issues related to checkpatch.pl cleanup

Changes in v2:
- Add I2C controller
- Add LED controller
- Add SPI NAND and NOR controller

Alex Nemirovsky (3):
  board: presidio-asic: Add eMMC board support
  board: presidio-asic: Add I2C support
  board: presidio-asic: Add SPI NAND and NOR support

Arthur Li (2):
  mmc: ca_dw_mmc: add DesignWare based DM support for CAxxxx SoCs
  i2c: i2c-cortina: added CAxxxx I2C support

Jway Lin (2):
  led: led_cortina: Add CAxxx LED support
  board: presidio: add LED support

Pengpeng Chen (1):
  spi: ca_sflash: Add CAxxxx SPI Flash Controller

 MAINTAINERS                                      |  10 +
 arch/arm/dts/ca-presidio-engboard.dts            |  39 +-
 board/cortina/presidio-asic/presidio.c           |  16 +-
 configs/cortina_presidio-asic-emmc_defconfig     |  38 ++
 configs/cortina_presidio-asic-spi-nand_defconfig |  48 ++
 configs/cortina_presidio-asic-spi-nor_defconfig  |  59 +++
 drivers/i2c/Kconfig                              |   7 +
 drivers/i2c/Makefile                             |   1 +
 drivers/i2c/i2c-cortina.c                        | 346 ++++++++++++++
 drivers/i2c/i2c-cortina.h                        |  92 ++++
 drivers/led/Kconfig                              |   8 +
 drivers/led/Makefile                             |   1 +
 drivers/led/led_cortina.c                        | 308 ++++++++++++
 drivers/mmc/Kconfig                              |  11 +
 drivers/mmc/Makefile                             |   1 +
 drivers/mmc/ca_dw_mmc.c                          | 181 +++++++
 drivers/spi/Kconfig                              |   8 +
 drivers/spi/Makefile                             |   1 +
 drivers/spi/ca_sflash.c                          | 576 +++++++++++++++++++++++
 19 files changed, 1745 insertions(+), 6 deletions(-)
 create mode 100644 configs/cortina_presidio-asic-emmc_defconfig
 create mode 100644 configs/cortina_presidio-asic-spi-nand_defconfig
 create mode 100644 configs/cortina_presidio-asic-spi-nor_defconfig
 create mode 100644 drivers/i2c/i2c-cortina.c
 create mode 100644 drivers/i2c/i2c-cortina.h
 create mode 100644 drivers/led/led_cortina.c
 create mode 100644 drivers/mmc/ca_dw_mmc.c
 create mode 100644 drivers/spi/ca_sflash.c

-- 
2.7.4

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v2 0/8] Cortina Access Drivers Package 2
  2020-02-27  7:58 Alex Nemirovsky
@ 2020-03-19  0:16 ` Alex Nemirovsky
  2020-03-19 10:16   ` Daniel Schwierzeck
  0 siblings, 1 reply; 18+ messages in thread
From: Alex Nemirovsky @ 2020-03-19  0:16 UTC (permalink / raw)
  To: u-boot

Hi Tom,
Are we still blocked on this set until the upcoming 2020.4 release?  

> On Feb 26, 2020, at 11:58 PM, Alex Nemirovsky <alex.nemirovsky@cortina-access.com> wrote:
> 
> 
> This release adds the following drivers and
> integrates support  into the Cortina Access
> Presidio Engineering Board:
> 
> CAxxxx SoC eMMC/SD controller
> CAxxxx SoC I2C controller
> CAxxxx Soc LED controller
> CAxxxx SPI NAND and NOR controller
> 
> Changes in v2:
> - Add I2C controller
> - Add LED controller
> - Add SPI NAND and NOR controller
> 
> Alex Nemirovsky (3):
>  board: presidio-asic: Add eMMC board support
>  board: presidio-asic: Add I2C support
>  board: presidio-asic: Add SPI NAND and NOR support
> 
> Arthur Li (2):
>  mmc: ca_dw_mmc: add DesignWare based DM support for CAxxxx SoCs
>  i2c: i2c-cortina: added CAxxxx I2C support
> 
> Jway Lin (2):
>  led: led_cortina: Add CAxxx LED support
>  board: presidio: add LED support
> 
> Pengpeng Chen (1):
>  spi: ca_sflash: Add CAxxxx SPI Flash Controller
> 
> MAINTAINERS                                      |  10 +
> arch/arm/dts/ca-presidio-engboard.dts            |  39 +-
> board/cortina/presidio-asic/presidio.c           |  16 +-
> configs/cortina_presidio-asic-emmc_defconfig     |  38 ++
> configs/cortina_presidio-asic-spi-nand_defconfig |  48 ++
> configs/cortina_presidio-asic-spi-nor_defconfig  |  59 +++
> drivers/i2c/Kconfig                              |   7 +
> drivers/i2c/Makefile                             |   1 +
> drivers/i2c/i2c-cortina.c                        | 346 ++++++++++++++
> drivers/i2c/i2c-cortina.h                        |  92 ++++
> drivers/led/Kconfig                              |   8 +
> drivers/led/Makefile                             |   1 +
> drivers/led/led_cortina.c                        | 308 ++++++++++++
> drivers/mmc/Kconfig                              |  11 +
> drivers/mmc/Makefile                             |   1 +
> drivers/mmc/ca_dw_mmc.c                          | 181 +++++++
> drivers/spi/Kconfig                              |   8 +
> drivers/spi/Makefile                             |   1 +
> drivers/spi/ca_sflash.c                          | 575 +++++++++++++++++++++++
> 19 files changed, 1744 insertions(+), 6 deletions(-)
> create mode 100644 configs/cortina_presidio-asic-emmc_defconfig
> create mode 100644 configs/cortina_presidio-asic-spi-nand_defconfig
> create mode 100644 configs/cortina_presidio-asic-spi-nor_defconfig
> create mode 100644 drivers/i2c/i2c-cortina.c
> create mode 100644 drivers/i2c/i2c-cortina.h
> create mode 100644 drivers/led/led_cortina.c
> create mode 100644 drivers/mmc/ca_dw_mmc.c
> create mode 100644 drivers/spi/ca_sflash.c
> 
> -- 
> 2.7.4
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v2 0/8] Cortina Access Drivers Package 2
@ 2020-02-27  7:58 Alex Nemirovsky
  2020-03-19  0:16 ` Alex Nemirovsky
  0 siblings, 1 reply; 18+ messages in thread
From: Alex Nemirovsky @ 2020-02-27  7:58 UTC (permalink / raw)
  To: u-boot


This release adds the following drivers and
integrates support  into the Cortina Access
Presidio Engineering Board:

CAxxxx SoC eMMC/SD controller
CAxxxx SoC I2C controller
CAxxxx Soc LED controller
CAxxxx SPI NAND and NOR controller

Changes in v2:
- Add I2C controller
- Add LED controller
- Add SPI NAND and NOR controller

Alex Nemirovsky (3):
  board: presidio-asic: Add eMMC board support
  board: presidio-asic: Add I2C support
  board: presidio-asic: Add SPI NAND and NOR support

Arthur Li (2):
  mmc: ca_dw_mmc: add DesignWare based DM support for CAxxxx SoCs
  i2c: i2c-cortina: added CAxxxx I2C support

Jway Lin (2):
  led: led_cortina: Add CAxxx LED support
  board: presidio: add LED support

Pengpeng Chen (1):
  spi: ca_sflash: Add CAxxxx SPI Flash Controller

 MAINTAINERS                                      |  10 +
 arch/arm/dts/ca-presidio-engboard.dts            |  39 +-
 board/cortina/presidio-asic/presidio.c           |  16 +-
 configs/cortina_presidio-asic-emmc_defconfig     |  38 ++
 configs/cortina_presidio-asic-spi-nand_defconfig |  48 ++
 configs/cortina_presidio-asic-spi-nor_defconfig  |  59 +++
 drivers/i2c/Kconfig                              |   7 +
 drivers/i2c/Makefile                             |   1 +
 drivers/i2c/i2c-cortina.c                        | 346 ++++++++++++++
 drivers/i2c/i2c-cortina.h                        |  92 ++++
 drivers/led/Kconfig                              |   8 +
 drivers/led/Makefile                             |   1 +
 drivers/led/led_cortina.c                        | 308 ++++++++++++
 drivers/mmc/Kconfig                              |  11 +
 drivers/mmc/Makefile                             |   1 +
 drivers/mmc/ca_dw_mmc.c                          | 181 +++++++
 drivers/spi/Kconfig                              |   8 +
 drivers/spi/Makefile                             |   1 +
 drivers/spi/ca_sflash.c                          | 575 +++++++++++++++++++++++
 19 files changed, 1744 insertions(+), 6 deletions(-)
 create mode 100644 configs/cortina_presidio-asic-emmc_defconfig
 create mode 100644 configs/cortina_presidio-asic-spi-nand_defconfig
 create mode 100644 configs/cortina_presidio-asic-spi-nor_defconfig
 create mode 100644 drivers/i2c/i2c-cortina.c
 create mode 100644 drivers/i2c/i2c-cortina.h
 create mode 100644 drivers/led/led_cortina.c
 create mode 100644 drivers/mmc/ca_dw_mmc.c
 create mode 100644 drivers/spi/ca_sflash.c

-- 
2.7.4

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2020-03-24 21:18 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-20  0:57 [PATCH v2 0/8] Cortina Access Drivers Package 2 Alex Nemirovsky
2020-03-20  0:57 ` [PATCH v2 1/8] mmc: ca_dw_mmc: add DesignWare based DM support for CAxxxx SoCs Alex Nemirovsky
2020-03-24  7:16   ` Jaehoon Chung
2020-03-24 21:18     ` Alex Nemirovsky
2020-03-20  0:57 ` [PATCH v2 2/8] board: presidio-asic: Add eMMC board support Alex Nemirovsky
2020-03-20  0:57 ` [PATCH v2 3/8] i2c: i2c-cortina: added CAxxxx I2C support Alex Nemirovsky
2020-03-20  6:25   ` Heiko Schocher
2020-03-20  0:57 ` [PATCH v2 4/8] board: presidio-asic: Add " Alex Nemirovsky
2020-03-20  0:57 ` [PATCH v2 5/8] led: led_cortina: Add CAxxx LED support Alex Nemirovsky
2020-03-23 15:37   ` Simon Glass
2020-03-20  0:57 ` [PATCH v2 6/8] board: presidio: add " Alex Nemirovsky
2020-03-23 15:37   ` Simon Glass
2020-03-20  0:57 ` [PATCH v2 7/8] spi: ca_sflash: Add CAxxxx SPI Flash Controller Alex Nemirovsky
2020-03-20  0:57 ` [PATCH v2 8/8] board: presidio-asic: Add SPI NAND and NOR support Alex Nemirovsky
  -- strict thread matches above, loose matches on Subject: below --
2020-03-19  1:52 [PATCH v2 0/8] Cortina Access Drivers Package 2 Alex Nemirovsky
2020-02-27  7:58 Alex Nemirovsky
2020-03-19  0:16 ` Alex Nemirovsky
2020-03-19 10:16   ` Daniel Schwierzeck

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.