All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v7 0/8] Cortina Access Drivers Package 2
@ 2020-05-14 20:11 Alex Nemirovsky
  2020-05-14 20:11 ` [PATCH v7 1/8] mmc: ca_dw_mmc: Misc cleanup of driver Alex Nemirovsky
                   ` (7 more replies)
  0 siblings, 8 replies; 13+ messages in thread
From: Alex Nemirovsky @ 2020-05-14 20:11 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 v7:
- Cleanup typos in commit subject line and description
- Added additional description info in I2C KConfig
- rename OFFSET to SHIFT from macros
- add additinal struct comments
- Reading the DT should really happen in the ofdata_to_platdata method
- Replace substring "OPCODE" with "OP" in MACROs to help
reduce code line lengths
- Replace substring "_MASK" with "_MSK" in MACROs to help
reduce code line lengths

Changes in v6:
- Add I2C DT binding document

Changes in v5:
- Rebase code basis on v2020.04-rc5 which has
  already incorporated CAxxxx eMMC initial baseline
- Rebase on codebase basis v2020.04-rc5 which already incorporated
 initial baseline of eMMC DT information
- NAND support removed from presidio-asic board DT.

Changes in v4:
- Rename DT compatible name
- Remove uneccessary if-statement to support 8-bit buswidth
- Remove redundant error msg
- Use symbolic constants in switch statement
- Change DT compatiblity name to match change in driver's name
- Remove unused io_ds and fifo_mode fields from DT
- Utilize standard I2C macros from <i2c.h>
- Return ETIMEDOUT in funcs that can timeout
- Return i2c_xfer_init() result to caller of i2c_read() if it
	fails within i2c_read() execution
- Fix misc. style guide conformance issues
- Use printf() to report i2c_xfer() runtime errors
	instead of debug()
- remove unused macros
- remove cortina prefix from macros
- remove use BSS variable
- further cleanup to meet code style guidelines
- add additinal struct comments
- rename DT blink rate symbol
- rename DT blink rate symbol

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: update eMMC DT information
  board: presidio-asic: Add I2C support
  board: presidio-asic: Add SPI NOR support

Arthur Li (2):
  mmc: ca_dw_mmc: Misc cleanup of driver
  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                                      |   8 +
 arch/arm/dts/ca-presidio-engboard.dts            |  41 +-
 board/cortina/presidio-asic/presidio.c           |  16 +-
 configs/cortina_presidio-asic-emmc_defconfig     |   5 +
 configs/cortina_presidio-asic-spi-nand_defconfig |  48 ++
 configs/cortina_presidio-asic-spi-nor_defconfig  |  59 +++
 doc/device-tree-bindings/i2c/i2c-cortina.txt     |  18 +
 drivers/i2c/Kconfig                              |   8 +
 drivers/i2c/Makefile                             |   1 +
 drivers/i2c/i2c-cortina.c                        | 346 ++++++++++++++
 drivers/i2c/i2c-cortina.h                        |  84 ++++
 drivers/led/Kconfig                              |   8 +
 drivers/led/Makefile                             |   1 +
 drivers/led/led_cortina.c                        | 305 ++++++++++++
 drivers/mmc/ca_dw_mmc.c                          |  34 +-
 drivers/spi/Kconfig                              |   8 +
 drivers/spi/Makefile                             |   1 +
 drivers/spi/ca_sflash.c                          | 576 +++++++++++++++++++++++
 18 files changed, 1537 insertions(+), 30 deletions(-)
 create mode 100644 configs/cortina_presidio-asic-spi-nand_defconfig
 create mode 100644 configs/cortina_presidio-asic-spi-nor_defconfig
 create mode 100644 doc/device-tree-bindings/i2c/i2c-cortina.txt
 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/spi/ca_sflash.c

-- 
2.7.4

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

* [PATCH v7 1/8] mmc: ca_dw_mmc: Misc cleanup of driver
  2020-05-14 20:11 [PATCH v7 0/8] Cortina Access Drivers Package 2 Alex Nemirovsky
@ 2020-05-14 20:11 ` Alex Nemirovsky
  2020-05-15  9:33   ` Jaehoon Chung
  2020-05-14 20:11 ` [PATCH v7 2/8] board: presidio-asic: update eMMC DT information Alex Nemirovsky
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 13+ messages in thread
From: Alex Nemirovsky @ 2020-05-14 20:11 UTC (permalink / raw)
  To: u-boot

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

- Rename DT compatible name
- Remove uneccessary if-statement to support 8-bit buswidth
- Remove redundant error msg
- Use symbolic constants in switch statement

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 v7: None
Changes in v6: None
Changes in v5:
- Rebase code basis on v2020.04-rc5 which has
  already incorporated CAxxxx eMMC initial baseline

Changes in v4:
- Rename DT compatible name
- Remove uneccessary if-statement to support 8-bit buswidth
- Remove redundant error msg
- Use symbolic constants in switch statement

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

 drivers/mmc/ca_dw_mmc.c | 34 ++++++++++++----------------------
 1 file changed, 12 insertions(+), 22 deletions(-)

diff --git a/drivers/mmc/ca_dw_mmc.c b/drivers/mmc/ca_dw_mmc.c
index acbc850..198c41f 100644
--- a/drivers/mmc/ca_dw_mmc.c
+++ b/drivers/mmc/ca_dw_mmc.c
@@ -19,6 +19,7 @@
 
 #define SD_CLK_SEL_200MHZ (0x2)
 #define SD_CLK_SEL_100MHZ (0x1)
+#define SD_CLK_SEL_50MHZ (0x0)
 
 #define IO_DRV_SD_DS_OFFSET (16)
 #define IO_DRV_SD_DS_MASK   (0xff << IO_DRV_SD_DS_OFFSET)
@@ -44,15 +45,11 @@ 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_MASK;
+	if (host->bus_hz >= 200000000)
 		val |= SD_CLK_SEL_200MHZ;
-	} else if (host->bus_hz >= 100000000) {
-		val &= ~SD_CLK_SEL_MASK;
+	else if (host->bus_hz >= 100000000)
 		val |= SD_CLK_SEL_100MHZ;
-	} else {
-		val &= ~SD_CLK_SEL_MASK;
-	}
 
 	writel(val, priv->sd_dll_reg);
 }
@@ -77,14 +74,14 @@ unsigned int ca_dwmci_get_mmc_clock(struct dwmci_host *host, uint freq)
 	u8 clk_div;
 
 	switch (sd_clk_sel) {
-	case 2:
-		clk_div = 1;
+	case SD_CLK_SEL_50MHZ:
+		clk_div = 4;
 		break;
-	case 1:
+	case SD_CLK_SEL_100MHZ:
 		clk_div = 2;
 		break;
 	default:
-		clk_div = 4;
+		clk_div = 1;
 	}
 
 	return SD_SCLK_MAX / clk_div / (host->div + 1);
@@ -100,9 +97,6 @@ static int ca_dwmmc_ofdata_to_platdata(struct udevice *dev)
 	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");
@@ -118,10 +112,8 @@ static int ca_dwmmc_ofdata_to_platdata(struct udevice *dev)
 		return -EINVAL;
 
 	host->ioaddr = dev_read_addr_ptr(dev);
-	if (host->ioaddr == (void *)FDT_ADDR_T_NONE) {
-		printf("DWMMC: base address is invalid\n");
+	if (!host->ioaddr)
 		return -EINVAL;
-	}
 
 	host->priv = priv;
 
@@ -140,10 +132,8 @@ static int ca_dwmmc_probe(struct udevice *dev)
 	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;
-	}
+	if (host->buswidth == 1)
+		(&plat->cfg)->host_caps &= ~(MMC_MODE_8BIT | MMC_MODE_4BIT);
 
 	host->mmc = &plat->mmc;
 	host->mmc->priv = &priv->host;
@@ -164,7 +154,7 @@ static int ca_dwmmc_bind(struct udevice *dev)
 }
 
 static const struct udevice_id ca_dwmmc_ids[] = {
-	{ .compatible = "snps,dw-cortina" },
+	{ .compatible = "cortina,ca-mmc" },
 	{ }
 };
 
-- 
2.7.4

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

* [PATCH v7 2/8] board: presidio-asic: update eMMC DT information
  2020-05-14 20:11 [PATCH v7 0/8] Cortina Access Drivers Package 2 Alex Nemirovsky
  2020-05-14 20:11 ` [PATCH v7 1/8] mmc: ca_dw_mmc: Misc cleanup of driver Alex Nemirovsky
@ 2020-05-14 20:11 ` Alex Nemirovsky
  2020-05-14 20:11 ` [PATCH v7 3/8] i2c: i2c-cortina: added CAxxxx I2C support Alex Nemirovsky
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Alex Nemirovsky @ 2020-05-14 20:11 UTC (permalink / raw)
  To: u-boot

Change DT compatibility name to match change in driver's name.
Remove unused io_ds and fifo_mode fields from DT.

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

---

Changes in v7:
- Cleanup typos in commit subject line and description

Changes in v6: None
Changes in v5:
- Rebase on codebase basis v2020.04-rc5 which already incorporated
 initial baseline of eMMC DT information

Changes in v4:
- Change DT compatiblity name to match change in driver's name
- Remove unused io_ds and fifo_mode fields from DT

Changes in v3: None
Changes in v2: None

 arch/arm/dts/ca-presidio-engboard.dts | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/arch/arm/dts/ca-presidio-engboard.dts b/arch/arm/dts/ca-presidio-engboard.dts
index c03dacc..40c93d7 100644
--- a/arch/arm/dts/ca-presidio-engboard.dts
+++ b/arch/arm/dts/ca-presidio-engboard.dts
@@ -10,11 +10,9 @@
    #size-cells = <1>;
 
 	mmc0: mmc at f4400000 {
-		compatible = "snps,dw-cortina";
+		compatible = "cortina,ca-mmc";
 		reg = <0x0 0xf4400000 0x1000>;
 		bus-width = <4>;
-		io_ds = <0x77>;
-		fifo-mode;
 		sd_dll_ctrl = <0xf43200e8>;
 		io_drv_ctrl = <0xf432004c>;
 	};
-- 
2.7.4

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

* [PATCH v7 3/8] i2c: i2c-cortina: added CAxxxx I2C support
  2020-05-14 20:11 [PATCH v7 0/8] Cortina Access Drivers Package 2 Alex Nemirovsky
  2020-05-14 20:11 ` [PATCH v7 1/8] mmc: ca_dw_mmc: Misc cleanup of driver Alex Nemirovsky
  2020-05-14 20:11 ` [PATCH v7 2/8] board: presidio-asic: update eMMC DT information Alex Nemirovsky
@ 2020-05-14 20:11 ` Alex Nemirovsky
  2020-05-19  5:45   ` Heiko Schocher
  2020-05-28  9:28   ` Heiko Schocher
  2020-05-14 20:11 ` [PATCH v7 4/8] board: presidio-asic: Add " Alex Nemirovsky
                   ` (4 subsequent siblings)
  7 siblings, 2 replies; 13+ messages in thread
From: Alex Nemirovsky @ 2020-05-14 20:11 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>

CA_I2C: DT binding for I2C controller

DT binding document for Cortina I2C driver

---

Changes in v7:
- Added additional description info in I2C KConfig

Changes in v6:
- Add I2C DT binding document

Changes in v5: None
Changes in v4:
- Utilize standard I2C macros from <i2c.h>
- Return ETIMEDOUT in funcs that can timeout
- Return i2c_xfer_init() result to caller of i2c_read() if it
	fails within i2c_read() execution
- Fix misc. style guide conformance issues
- Use printf() to report i2c_xfer() runtime errors
	instead of debug()

Changes in v3: None
Changes in v2: None

 MAINTAINERS                                  |   4 +
 doc/device-tree-bindings/i2c/i2c-cortina.txt |  18 ++
 drivers/i2c/Kconfig                          |   8 +
 drivers/i2c/Makefile                         |   1 +
 drivers/i2c/i2c-cortina.c                    | 346 +++++++++++++++++++++++++++
 drivers/i2c/i2c-cortina.h                    |  84 +++++++
 6 files changed, 461 insertions(+)
 create mode 100644 doc/device-tree-bindings/i2c/i2c-cortina.txt
 create mode 100644 drivers/i2c/i2c-cortina.c
 create mode 100644 drivers/i2c/i2c-cortina.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 66f0b07..ec17a37 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>
@@ -723,6 +725,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/doc/device-tree-bindings/i2c/i2c-cortina.txt b/doc/device-tree-bindings/i2c/i2c-cortina.txt
new file mode 100644
index 0000000..59d5235
--- /dev/null
+++ b/doc/device-tree-bindings/i2c/i2c-cortina.txt
@@ -0,0 +1,18 @@
+* I2C for Cortina platforms
+
+Required properties :
+- compatible : Must be "cortina,ca-i2c"
+- reg : Offset and length of the register set for the device
+
+Recommended properties :
+- clock-frequency : desired I2C bus clock frequency in Hz. If not specified,
+		    default value is 100000. Possible values are 100000,
+		    400000 and 1000000.
+
+Examples :
+
+	i2c: i2c at f4329120 {
+		compatible = "cortina,ca-i2c";
+		reg = <0x0 0xf4329120 0x28>;
+		clock-frequency = <400000>;
+	};
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index e42b651..215d872 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -93,6 +93,14 @@ 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
+	  Add support for the Cortina Access I2C host controller.
+	  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 62935b7..d2b07ce 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..08b812a
--- /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_FAST_PLUS:
+		i2c_cfg.bf.prer = CORTINA_PER_IO_FREQ /
+				  (5 * I2C_SPEED_FAST_PLUS_RATE) - 1;
+		break;
+
+	case IC_SPEED_MODE_STANDARD:
+		i2c_cfg.bf.prer = CORTINA_PER_IO_FREQ /
+				  (5 * I2C_SPEED_STANDARD_RATE) - 1;
+		break;
+
+	case IC_SPEED_MODE_FAST:
+	default:
+		i2c_cfg.bf.prer = CORTINA_PER_IO_FREQ /
+				  (5 * I2C_SPEED_FAST_RATE) - 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_SPEED_FAST_PLUS_RATE) {
+		i2c_spd = IC_SPEED_MODE_FAST_PLUS;
+		priv->speed = I2C_SPEED_FAST_PLUS_RATE;
+	} else if (speed >= I2C_SPEED_FAST_RATE) {
+		i2c_spd = IC_SPEED_MODE_FAST;
+		priv->speed = I2C_SPEED_FAST_RATE;
+	} else {
+		i2c_spd = IC_SPEED_MODE_STANDARD;
+		priv->speed = I2C_SPEED_STANDARD_RATE;
+	}
+
+	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 -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 -ETIMEDOUT;
+		}
+	}
+
+	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 -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;
+
+	rc = i2c_xfer_init(regs, chip, addr, alen, I2C_CMD_RD);
+	if (rc)
+		return rc;
+
+	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 -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;
+
+	rc = i2c_xfer_init(regs, chip, addr, alen, I2C_CMD_WT);
+	if (rc)
+		return rc;
+
+	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)) {
+			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);
+
+		if (ret) {
+			printf("i2c_xfer: %s error\n",
+			       msg->flags & I2C_M_RD ? "read" : "write");
+			return ret;
+		}
+	}
+
+	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..2d46c4f
--- /dev/null
+++ b/drivers/i2c/i2c-cortina.h
@@ -0,0 +1,84 @@
+/* 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)
+
+#endif							/* __CA_I2C_H_ */
-- 
2.7.4

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

* [PATCH v7 4/8] board: presidio-asic: Add I2C support
  2020-05-14 20:11 [PATCH v7 0/8] Cortina Access Drivers Package 2 Alex Nemirovsky
                   ` (2 preceding siblings ...)
  2020-05-14 20:11 ` [PATCH v7 3/8] i2c: i2c-cortina: added CAxxxx I2C support Alex Nemirovsky
@ 2020-05-14 20:11 ` Alex Nemirovsky
  2020-05-19  5:46   ` Heiko Schocher
  2020-05-14 20:11 ` [PATCH v7 5/8] led: led_cortina: Add CAxxx LED support Alex Nemirovsky
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 13+ messages in thread
From: Alex Nemirovsky @ 2020-05-14 20:11 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 v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
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] 13+ messages in thread

* [PATCH v7 5/8] led: led_cortina: Add CAxxx LED support
  2020-05-14 20:11 [PATCH v7 0/8] Cortina Access Drivers Package 2 Alex Nemirovsky
                   ` (3 preceding siblings ...)
  2020-05-14 20:11 ` [PATCH v7 4/8] board: presidio-asic: Add " Alex Nemirovsky
@ 2020-05-14 20:11 ` Alex Nemirovsky
  2020-05-14 20:11 ` [PATCH v7 6/8] board: presidio: add " Alex Nemirovsky
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 13+ messages in thread
From: Alex Nemirovsky @ 2020-05-14 20:11 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 v7:
- rename OFFSET to SHIFT from macros
- add additinal struct comments
- Reading the DT should really happen in the ofdata_to_platdata method

Changes in v6: None
Changes in v5: None
Changes in v4:
- remove unused macros
- remove cortina prefix from macros
- remove use BSS variable
- further cleanup to meet code style guidelines
- add additinal struct comments
- rename DT blink rate symbol

Changes in v3: None
Changes in v2: None

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

diff --git a/MAINTAINERS b/MAINTAINERS
index ec17a37..93aff29 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>
@@ -727,6 +728,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..a6d9159
--- /dev/null
+++ b/drivers/led/led_cortina.c
@@ -0,0 +1,305 @@
+// 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>
+
+#define LED_MAX_HW_BLINK		127
+#define LED_MAX_COUNT			16
+
+/* LED_CONTROL fields */
+#define LED_BLINK_RATE1_SHIFT	0
+#define LED_BLINK_RATE1_MASK	0xff
+#define LED_BLINK_RATE2_SHIFT	8
+#define LED_BLINK_RATE2_MASK	0xff
+#define LED_CLK_TEST			BIT(16)
+#define LED_CLK_POLARITY		BIT(17)
+#define LED_CLK_TEST_MODE		BIT(16)
+#define LED_CLK_TEST_RX_TEST	BIT(30)
+#define LED_CLK_TEST_TX_TEST	BIT(31)
+
+/* LED_CONFIG fields */
+#define LED_EVENT_ON_SHIFT		0
+#define LED_EVENT_ON_MASK		0x7
+#define LED_EVENT_BLINK_SHIFT	3
+#define LED_EVENT_BLINK_MASK	0x7
+#define LED_EVENT_OFF_SHIFT	6
+#define LED_EVENT_OFF_MASK		0x7
+#define LED_OFF_ON_SHIFT		9
+#define LED_OFF_ON_MASK			0x3
+#define LED_PORT_SHIFT			11
+#define LED_PORT_MASK			0x7
+#define LED_OFF_VAL				BIT(14)
+#define LED_SW_EVENT			BIT(15)
+#define LED_BLINK_SEL			BIT(16)
+
+/* LED_CONFIG structures */
+struct cortina_led_cfg {
+	void __iomem *regs;
+	u32 pin;			/* LED pin nubmer */
+	bool active_low;	/*Active-High or Active-Low*/
+	u32 off_event;		/* set led off event (RX,TX,SW)*/
+	u32 blink_event;	/* set led blink event (RX,TX,SW)*/
+	u32 on_event;	/* set led on event (RX,TX,SW)*/
+	u32 port;		/* corresponding ethernet port */
+	int blink_sel;		/* select blink-rate1 or blink-rate2  */
+};
+
+/* LED_control structures */
+struct cortina_led_platdata {
+	void __iomem *ctrl_regs;
+	u16 rate1;	/* blink rate setting 0 */
+	u16 rate2;	/* blink rate setting 1 */
+};
+
+enum ca_led_state_t {
+	CA_EVENT_MODE = 0,
+	CA_LED_ON = 1,
+	CA_LED_OFF,
+};
+
+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 & 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);
+	val &= ~(LED_OFF_ON_MASK << LED_OFF_ON_SHIFT);
+
+	switch (state) {
+	case LEDST_OFF:
+		val &= ~LED_SW_EVENT;
+		val |= CA_LED_OFF << LED_OFF_ON_SHIFT;
+		cortina_led_write(priv->regs, val);
+		break;
+	case LEDST_ON:
+		val |= LED_SW_EVENT;
+		val |= CA_LED_ON << LED_OFF_ON_SHIFT;
+		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;
+#ifdef CONFIG_LED_BLINK
+	case LEDST_BLINK:
+		val &= ~LED_SW_EVENT;
+		val |= CA_LED_OFF << LED_OFF_ON_SHIFT;
+		val |= LED_EVENT_BLINK_MASK << LED_EVENT_BLINK_SHIFT;
+		cortina_led_write(priv->regs, val);
+		break;
+#endif
+
+	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 ca_led_ofdata_to_platdata(struct udevice *dev)
+{
+	struct led_uc_plat *uc_plat = dev_get_uclass_platdata(dev);
+
+	/* Top-level LED node */
+	if (!uc_plat->label) {
+		struct cortina_led_platdata *plt = dev_get_platdata(dev);
+
+		plt->rate1 =
+			dev_read_u32_default(dev, "Cortina,blink-rate1", 256);
+		plt->rate2 =
+			dev_read_u32_default(dev, "Cortina,blink-rate2", 512);
+		plt->ctrl_regs = dev_remap_addr(dev);
+	} else {
+		struct cortina_led_cfg *priv = dev_get_priv(dev);
+
+		priv->regs = dev_remap_addr(dev_get_parent(dev));
+		priv->pin = dev_read_u32_default(dev, "pin", LED_MAX_COUNT);
+		priv->blink_sel = dev_read_u32_default(dev, "blink-sel", 0);
+		priv->off_event = dev_read_u32_default(dev, "off-event", 0);
+		priv->blink_event = dev_read_u32_default(dev, "blink-event", 0);
+		priv->on_event = dev_read_u32_default(dev, "on-event", 0);
+		priv->port = dev_read_u32_default(dev, "port", 0);
+
+		if (dev_read_bool(dev, "active-low"))
+			priv->active_low = true;
+		else
+			priv->active_low = false;
+	}
+
+	return 0;
+}
+
+static int cortina_led_probe(struct udevice *dev)
+{
+	struct led_uc_plat *uc_plat = dev_get_uclass_platdata(dev);
+
+	/* Top-level LED node */
+	if (!uc_plat->label) {
+		struct cortina_led_platdata *platdata = dev_get_platdata(dev);
+		u32 reg_value, val;
+		u16 rate1, rate2;
+
+		if (!platdata->ctrl_regs)
+			return -EINVAL;
+
+		reg_value = 0;
+		reg_value |= LED_CLK_POLARITY;
+
+		rate1 = platdata->rate1;
+		rate2 = platdata->rate2;
+
+		val = rate1 / 16 - 1;
+		rate1 = val > LED_MAX_HW_BLINK ?
+					LED_MAX_HW_BLINK : val;
+		reg_value |= (rate1 & LED_BLINK_RATE1_MASK) <<
+					LED_BLINK_RATE1_SHIFT;
+
+		val = rate2 / 16 - 1;
+		rate2 = val > LED_MAX_HW_BLINK ?
+					LED_MAX_HW_BLINK : val;
+		reg_value |= (rate2 & LED_BLINK_RATE2_MASK) <<
+					LED_BLINK_RATE2_SHIFT;
+
+		cortina_led_write(platdata->ctrl_regs, reg_value);
+
+	} else {
+		struct cortina_led_cfg *priv = dev_get_priv(dev);
+		void __iomem *regs;
+		u32 val, port, off_event, blink_event, on_event;
+
+		regs = priv->regs;
+		if (!regs)
+			return -EINVAL;
+
+		if (priv->pin >= LED_MAX_COUNT)
+			return -EINVAL;
+
+		priv->regs = regs + 4 + priv->pin * 4;
+
+		val = cortina_led_read(priv->regs);
+
+		if (priv->active_low)
+			val |= LED_OFF_VAL;
+		else
+			val &= ~LED_OFF_VAL;
+
+		if (priv->blink_sel == 0)
+			val &= ~LED_BLINK_SEL;
+		else if (priv->blink_sel == 1)
+			val |= LED_BLINK_SEL;
+
+		off_event = priv->off_event;
+		val &= ~(LED_EVENT_OFF_MASK << LED_EVENT_OFF_SHIFT);
+		if (off_event != 0)
+			val |= BIT(off_event) << LED_EVENT_OFF_SHIFT;
+
+		blink_event =  priv->blink_event;
+		val &= ~(LED_EVENT_BLINK_MASK << LED_EVENT_BLINK_SHIFT);
+		if (blink_event != 0)
+			val |= BIT(blink_event) << LED_EVENT_BLINK_SHIFT;
+
+		on_event = priv->on_event;
+		val &= ~(LED_EVENT_ON_MASK << LED_EVENT_ON_SHIFT);
+		if (on_event != 0)
+			val |= BIT(on_event) << LED_EVENT_ON_SHIFT;
+
+		port = priv->port;
+		val &= ~(LED_PORT_MASK << LED_PORT_SHIFT);
+		val |= port << LED_PORT_SHIFT;
+
+		/* force off */
+		val &= ~(LED_OFF_ON_MASK << LED_OFF_ON_SHIFT);
+		val |= CA_LED_OFF << LED_OFF_ON_SHIFT;
+
+		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,
+	.ofdata_to_platdata = ca_led_ofdata_to_platdata,
+	.bind = cortina_led_bind,
+	.probe = cortina_led_probe,
+	.platdata_auto_alloc_size = sizeof(struct cortina_led_platdata),
+	.priv_auto_alloc_size = sizeof(struct cortina_led_cfg),
+	.ops = &cortina_led_ops,
+};
-- 
2.7.4

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

* [PATCH v7 6/8] board: presidio: add LED support
  2020-05-14 20:11 [PATCH v7 0/8] Cortina Access Drivers Package 2 Alex Nemirovsky
                   ` (4 preceding siblings ...)
  2020-05-14 20:11 ` [PATCH v7 5/8] led: led_cortina: Add CAxxx LED support Alex Nemirovsky
@ 2020-05-14 20:11 ` Alex Nemirovsky
  2020-05-14 20:11 ` [PATCH v7 7/8] spi: ca_sflash: Add CAxxxx SPI Flash Controller Alex Nemirovsky
  2020-05-14 20:11 ` [PATCH v7 8/8] board: presidio-asic: Add SPI NOR support Alex Nemirovsky
  7 siblings, 0 replies; 13+ messages in thread
From: Alex Nemirovsky @ 2020-05-14 20:11 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>
Reviewed-by: Simon Glass <sjg@chromium.org>

CC: Simon Glass <sjg@chromium.org>

---

Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4:
- rename DT blink rate symbol

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 40c93d7..eef433e 100644
--- a/arch/arm/dts/ca-presidio-engboard.dts
+++ b/arch/arm/dts/ca-presidio-engboard.dts
@@ -64,4 +64,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] 13+ messages in thread

* [PATCH v7 7/8] spi: ca_sflash: Add CAxxxx SPI Flash Controller
  2020-05-14 20:11 [PATCH v7 0/8] Cortina Access Drivers Package 2 Alex Nemirovsky
                   ` (5 preceding siblings ...)
  2020-05-14 20:11 ` [PATCH v7 6/8] board: presidio: add " Alex Nemirovsky
@ 2020-05-14 20:11 ` Alex Nemirovsky
  2020-05-14 20:11 ` [PATCH v7 8/8] board: presidio-asic: Add SPI NOR support Alex Nemirovsky
  7 siblings, 0 replies; 13+ messages in thread
From: Alex Nemirovsky @ 2020-05-14 20:11 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>
CC: Vignesh R <vigneshr@ti.com>

ca slfash fixup

---

Changes in v7:
- Replace substring "OPCODE" with "OP" in MACROs to help
reduce code line lengths
- Replace substring "_MASK" with "_MSK" in MACROs to help
reduce code line lengths

Changes in v6: None
Changes in v5: None
Changes in v4: None
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 93aff29..0b91f4f 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>
@@ -729,6 +730,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..00af6bf
--- /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_MSK		GENMASK(14, 12)
+#define CA_FLASH_TR_TYPE(tp)		(((tp) << 12) & CA_FLASH_TR_TYPE_MSK)
+#define CA_FLASH_TR_WIDTH			BIT(11)
+#define CA_FLASH_TR_SIZE_MSK		GENMASK(10, 9)
+#define CA_FLASH_TR_SIZE(sz)		(((sz) << 9) & CA_FLASH_TR_SIZE_MSK)
+
+/*
+ * 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_OP_MSK		GENMASK(7, 0)
+#define CA_SF_AR_OP(op)		((op) << 0 & CA_SF_AR_OP_MSK)
+#define CA_SF_AR_ACCODE_MSK		GENMASK(11, 8)
+#define CA_SF_AR_ACCODE(ac)		(((ac) << 8) & CA_SF_AR_ACCODE_MSK)
+#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_MSK		GENMASK(29, 28)
+#define CA_SF_AR_DDR(ddr)		(((ddr) << 28) & CA_SF_AR_DDR_MSK)
+#define CA_SF_AR_MIO_INF_MSK		GENMASK(31, 30)
+#define CA_SF_AR_MIO_INF(io)		(((io) << 30) & CA_SF_AR_MIO_INF_MSK)
+
+/*
+ * FLASH_SF_EXT_ACCESS
+ */
+#define CA_SF_EAR_OP_MSK		GENMASK(7, 0)
+#define CA_SF_EAR_OP(op)		(((op) << 0) & CA_SF_EAR_OP_MSK)
+#define CA_SF_EAR_DATA_CNT_MSK		GENMASK(20, 8)
+#define CA_SF_EAR_DATA_CNT(cnt)		(((cnt) << 8) & CA_SF_EAR_DATA_CNT_MSK)
+#define CA_SF_EAR_DATA_CNT_MAX		(4096)
+#define CA_SF_EAR_ADDR_CNT_MSK		GENMASK(23, 21)
+#define CA_SF_EAR_ADDR_CNT(cnt)		(((cnt) << 21) & CA_SF_EAR_ADDR_CNT_MSK)
+#define CA_SF_EAR_ADDR_CNT_MAX		(5)
+#define CA_SF_EAR_DUMY_CNT_MSK		GENMASK(29, 24)
+#define CA_SF_EAR_DUMY_CNT(cnt)		(((cnt) << 24) & CA_SF_EAR_DUMY_CNT_MSK)
+#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_MSK		GENMASK(31, 0)
+#define CA_SF_ADR_REG(addr)		(((addr) << 0) & CA_SF_ADR_REG_MSK)
+
+/*
+ * FLASH_SF_DATA
+ */
+#define CA_SF_DR_REG_MSK		GENMASK(31, 0)
+#define CA_SF_DR_REG(addr)		(((addr) << 0) & CA_SF_DR_REG_MSK)
+
+/*
+ * FLASH_SF_TIMING
+ */
+#define CA_SF_TMR_IDLE_MSK		GENMASK(7, 0)
+#define CA_SF_TMR_IDLE(idle)		(((idle) << 0) & CA_SF_TMR_IDLE_MSK)
+#define CA_SF_TMR_HOLD_MSK		GENMASK(15, 8)
+#define CA_SF_TMR_HOLD(hold)		(((hold) << 8) & CA_SF_TMR_HOLD_MSK)
+#define CA_SF_TMR_SETUP_MSK		GENMASK(23, 16)
+#define CA_SF_TMR_SETUP(setup)		(((setup) << 16) & CA_SF_TMR_SETUP_MSK)
+#define CA_SF_TMR_CLK_MSK		GENMASK(26, 24)
+#define CA_SF_TMR_CLK(clk)		(((clk) << 24) & CA_SF_TMR_CLK_MSK)
+
+#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_OP			0x00
+#define CA_SF_AC_OP_1_DATA		0x01
+#define CA_SF_AC_OP_2_DATA		0x02
+#define CA_SF_AC_OP_3_DATA		0x03
+#define CA_SF_AC_OP_4_DATA		0x04
+#define CA_SF_AC_OP_3_ADDR		0x05
+#define CA_SF_AC_OP_4_ADDR		(CA_SF_AC_OP_3_ADDR)
+#define CA_SF_AC_OP_3_ADDR_1_DATA	0x06
+#define CA_SF_AC_OP_4_ADDR_1_DATA	(CA_SF_AC_OP_3_ADDR_1_DATA << 2)
+#define CA_SF_AC_OP_3_ADDR_2_DATA	0x07
+#define CA_SF_AC_OP_4_ADDR_2_DATA	(CA_SF_AC_OP_3_ADDR_2_DATA << 2)
+#define CA_SF_AC_OP_3_ADDR_3_DATA	0x08
+#define CA_SF_AC_OP_4_ADDR_3_DATA	(CA_SF_AC_OP_3_ADDR_3_DATA << 2)
+#define CA_SF_AC_OP_3_ADDR_4_DATA	0x09
+#define CA_SF_AC_OP_4_ADDR_4_DATA	(CA_SF_AC_OP_3_ADDR_4_DATA << 2)
+#define CA_SF_AC_OP_3_ADDR_X_1_DATA	0x0A
+#define CA_SF_AC_OP_4_ADDR_X_1_DATA	(CA_SF_AC_OP_3_ADDR_X_1_DATA << 2)
+#define CA_SF_AC_OP_3_ADDR_X_2_DATA	0x0B
+#define CA_SF_AC_OP_4_ADDR_X_2_DATA	(CA_SF_AC_OP_3_ADDR_X_2_DATA << 2)
+#define CA_SF_AC_OP_3_ADDR_X_3_DATA	0x0C
+#define CA_SF_AC_OP_4_ADDR_X_3_DATA	(CA_SF_AC_OP_3_ADDR_X_3_DATA << 2)
+#define CA_SF_AC_OP_3_ADDR_X_4_DATA	0x0D
+#define CA_SF_AC_OP_4_ADDR_X_4_DATA	(CA_SF_AC_OP_3_ADDR_X_4_DATA << 2)
+#define CA_SF_AC_OP_3_ADDR_4X_1_DATA	0x0E
+#define CA_SF_AC_OP_4_ADDR_4X_1_DATA	(CA_SF_AC_OP_3_ADDR_4X_1_DATA << 2)
+#define CA_SF_AC_OP_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_OP_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_OP(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_OP(op->cmd.opcode));
+		debug("%s: FLASH ACCESS reg=%#08x\n",
+		      __func__, readl(&priv->regs->ar));
+
+		if (opcode == CA_SF_AC_OP_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_MSK);
+
+			/* 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_OP;
+	} else if (op->data.nbytes == 0 && op->addr.nbytes > 0) {
+		opcode = CA_SF_AC_OP_4_ADDR;
+	} else if (op->data.nbytes > 0) {
+		opcode = CA_SF_AC_OP_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] 13+ messages in thread

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

Add SPI NOR support for Cortina Access
Presidio Engineering Board

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

---

Changes in v7: None
Changes in v6: None
Changes in v5:
- NAND support removed from presidio-asic board DT.

Changes in v4: None
Changes in v3: None
Changes in v2: None

 arch/arm/dts/ca-presidio-engboard.dts            |  6 +--
 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, 124 insertions(+), 5 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 eef433e..cc7c888 100644
--- a/arch/arm/dts/ca-presidio-engboard.dts
+++ b/arch/arm/dts/ca-presidio-engboard.dts
@@ -53,15 +53,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>;
+			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] 13+ messages in thread

* [PATCH v7 1/8] mmc: ca_dw_mmc: Misc cleanup of driver
  2020-05-14 20:11 ` [PATCH v7 1/8] mmc: ca_dw_mmc: Misc cleanup of driver Alex Nemirovsky
@ 2020-05-15  9:33   ` Jaehoon Chung
  0 siblings, 0 replies; 13+ messages in thread
From: Jaehoon Chung @ 2020-05-15  9:33 UTC (permalink / raw)
  To: u-boot

On 5/15/20 5:11 AM, Alex Nemirovsky wrote:
> From: Arthur Li <arthur.li@cortina-access.com>
> 
> - Rename DT compatible name
> - Remove uneccessary if-statement to support 8-bit buswidth
> - Remove redundant error msg
> - Use symbolic constants in switch statement
> 
> 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 v7: None
> Changes in v6: None
> Changes in v5:
> - Rebase code basis on v2020.04-rc5 which has
>   already incorporated CAxxxx eMMC initial baseline
> 
> Changes in v4:
> - Rename DT compatible name
> - Remove uneccessary if-statement to support 8-bit buswidth
> - Remove redundant error msg
> - Use symbolic constants in switch statement
> 
> Changes in v3: None
> Changes in v2:
> - Add I2C controller
> - Add LED controller
> - Add SPI NAND and NOR controller
> 
>  drivers/mmc/ca_dw_mmc.c | 34 ++++++++++++----------------------
>  1 file changed, 12 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/mmc/ca_dw_mmc.c b/drivers/mmc/ca_dw_mmc.c
> index acbc850..198c41f 100644
> --- a/drivers/mmc/ca_dw_mmc.c
> +++ b/drivers/mmc/ca_dw_mmc.c
> @@ -19,6 +19,7 @@
>  
>  #define SD_CLK_SEL_200MHZ (0x2)
>  #define SD_CLK_SEL_100MHZ (0x1)
> +#define SD_CLK_SEL_50MHZ (0x0)
>  
>  #define IO_DRV_SD_DS_OFFSET (16)
>  #define IO_DRV_SD_DS_MASK   (0xff << IO_DRV_SD_DS_OFFSET)
> @@ -44,15 +45,11 @@ 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_MASK;
> +	if (host->bus_hz >= 200000000)
>  		val |= SD_CLK_SEL_200MHZ;
> -	} else if (host->bus_hz >= 100000000) {
> -		val &= ~SD_CLK_SEL_MASK;
> +	else if (host->bus_hz >= 100000000)
>  		val |= SD_CLK_SEL_100MHZ;
> -	} else {
> -		val &= ~SD_CLK_SEL_MASK;
> -	}
>  
>  	writel(val, priv->sd_dll_reg);
>  }
> @@ -77,14 +74,14 @@ unsigned int ca_dwmci_get_mmc_clock(struct dwmci_host *host, uint freq)
>  	u8 clk_div;
>  
>  	switch (sd_clk_sel) {
> -	case 2:
> -		clk_div = 1;
> +	case SD_CLK_SEL_50MHZ:
> +		clk_div = 4;
>  		break;
> -	case 1:
> +	case SD_CLK_SEL_100MHZ:
>  		clk_div = 2;
>  		break;
>  	default:
> -		clk_div = 4;
> +		clk_div = 1;
>  	}
>  
>  	return SD_SCLK_MAX / clk_div / (host->div + 1);
> @@ -100,9 +97,6 @@ static int ca_dwmmc_ofdata_to_platdata(struct udevice *dev)
>  	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");
> @@ -118,10 +112,8 @@ static int ca_dwmmc_ofdata_to_platdata(struct udevice *dev)
>  		return -EINVAL;
>  
>  	host->ioaddr = dev_read_addr_ptr(dev);
> -	if (host->ioaddr == (void *)FDT_ADDR_T_NONE) {
> -		printf("DWMMC: base address is invalid\n");
> +	if (!host->ioaddr)
>  		return -EINVAL;
> -	}
>  
>  	host->priv = priv;
>  
> @@ -140,10 +132,8 @@ static int ca_dwmmc_probe(struct udevice *dev)
>  	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;
> -	}
> +	if (host->buswidth == 1)
> +		(&plat->cfg)->host_caps &= ~(MMC_MODE_8BIT | MMC_MODE_4BIT);
>  
>  	host->mmc = &plat->mmc;
>  	host->mmc->priv = &priv->host;
> @@ -164,7 +154,7 @@ static int ca_dwmmc_bind(struct udevice *dev)
>  }
>  
>  static const struct udevice_id ca_dwmmc_ids[] = {
> -	{ .compatible = "snps,dw-cortina" },
> +	{ .compatible = "cortina,ca-mmc" },

Well, i didn't know entire history why changed from "snps,dw-cortina" to "cortina,ca-mmc".
is there any special reason?

Best Regards,
Jaehoon Chung

>  	{ }
>  };
>  
> 

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

* [PATCH v7 3/8] i2c: i2c-cortina: added CAxxxx I2C support
  2020-05-14 20:11 ` [PATCH v7 3/8] i2c: i2c-cortina: added CAxxxx I2C support Alex Nemirovsky
@ 2020-05-19  5:45   ` Heiko Schocher
  2020-05-28  9:28   ` Heiko Schocher
  1 sibling, 0 replies; 13+ messages in thread
From: Heiko Schocher @ 2020-05-19  5:45 UTC (permalink / raw)
  To: u-boot

Hello Alex,

Am 14.05.2020 um 22:11 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>
> 
> CA_I2C: DT binding for I2C controller
> 
> DT binding document for Cortina I2C driver
> 
> ---
> 
> Changes in v7:
> - Added additional description info in I2C KConfig
> 
> Changes in v6:
> - Add I2C DT binding document
> 
> Changes in v5: None
> Changes in v4:
> - Utilize standard I2C macros from <i2c.h>
> - Return ETIMEDOUT in funcs that can timeout
> - Return i2c_xfer_init() result to caller of i2c_read() if it
> 	fails within i2c_read() execution
> - Fix misc. style guide conformance issues
> - Use printf() to report i2c_xfer() runtime errors
> 	instead of debug()
> 
> Changes in v3: None
> Changes in v2: None
> 
>   MAINTAINERS                                  |   4 +
>   doc/device-tree-bindings/i2c/i2c-cortina.txt |  18 ++
>   drivers/i2c/Kconfig                          |   8 +
>   drivers/i2c/Makefile                         |   1 +
>   drivers/i2c/i2c-cortina.c                    | 346 +++++++++++++++++++++++++++
>   drivers/i2c/i2c-cortina.h                    |  84 +++++++
>   6 files changed, 461 insertions(+)
>   create mode 100644 doc/device-tree-bindings/i2c/i2c-cortina.txt
>   create mode 100644 drivers/i2c/i2c-cortina.c
>   create mode 100644 drivers/i2c/i2c-cortina.h

Reviewed-by: Heiko Schocher <hs@denx.de>

Nitpick only ...

[...]
> diff --git a/drivers/i2c/i2c-cortina.c b/drivers/i2c/i2c-cortina.c
> new file mode 100644
> index 0000000..08b812a
> --- /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_FAST_PLUS:
> +		i2c_cfg.bf.prer = CORTINA_PER_IO_FREQ /
> +				  (5 * I2C_SPEED_FAST_PLUS_RATE) - 1;
> +		break;
> +
> +	case IC_SPEED_MODE_STANDARD:
> +		i2c_cfg.bf.prer = CORTINA_PER_IO_FREQ /
> +				  (5 * I2C_SPEED_STANDARD_RATE) - 1;
> +		break;
> +
> +	case IC_SPEED_MODE_FAST:
> +	default:
> +		i2c_cfg.bf.prer = CORTINA_PER_IO_FREQ /
> +				  (5 * I2C_SPEED_FAST_RATE) - 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_SPEED_FAST_PLUS_RATE) {
> +		i2c_spd = IC_SPEED_MODE_FAST_PLUS;
> +		priv->speed = I2C_SPEED_FAST_PLUS_RATE;
> +	} else if (speed >= I2C_SPEED_FAST_RATE) {
> +		i2c_spd = IC_SPEED_MODE_FAST;
> +		priv->speed = I2C_SPEED_FAST_RATE;
> +	} else {
> +		i2c_spd = IC_SPEED_MODE_STANDARD;
> +		priv->speed = I2C_SPEED_STANDARD_RATE;
> +	}

you could set only one vairable in the if paths (and drop {)
and set the other variable later ...
[...]

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] 13+ messages in thread

* [PATCH v7 4/8] board: presidio-asic: Add I2C support
  2020-05-14 20:11 ` [PATCH v7 4/8] board: presidio-asic: Add " Alex Nemirovsky
@ 2020-05-19  5:46   ` Heiko Schocher
  0 siblings, 0 replies; 13+ messages in thread
From: Heiko Schocher @ 2020-05-19  5:46 UTC (permalink / raw)
  To: u-boot

Hello Alex,

Am 14.05.2020 um 22:11 schrieb Alex Nemirovsky:
> 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 v7: None
> Changes in v6: None
> Changes in v5: None
> Changes in v4: None
> Changes in v3: None
> Changes in v2: None

Reviewed-by: Heiko Schocher <hs@denx.de>

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] 13+ messages in thread

* [PATCH v7 3/8] i2c: i2c-cortina: added CAxxxx I2C support
  2020-05-14 20:11 ` [PATCH v7 3/8] i2c: i2c-cortina: added CAxxxx I2C support Alex Nemirovsky
  2020-05-19  5:45   ` Heiko Schocher
@ 2020-05-28  9:28   ` Heiko Schocher
  1 sibling, 0 replies; 13+ messages in thread
From: Heiko Schocher @ 2020-05-28  9:28 UTC (permalink / raw)
  To: u-boot

Hello Alex,

Am 14.05.2020 um 22:11 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>
> 
> CA_I2C: DT binding for I2C controller
> 
> DT binding document for Cortina I2C driver
> 
> ---
> 
> Changes in v7:
> - Added additional description info in I2C KConfig
> 
> Changes in v6:
> - Add I2C DT binding document
> 
> Changes in v5: None
> Changes in v4:
> - Utilize standard I2C macros from <i2c.h>
> - Return ETIMEDOUT in funcs that can timeout
> - Return i2c_xfer_init() result to caller of i2c_read() if it
> 	fails within i2c_read() execution
> - Fix misc. style guide conformance issues
> - Use printf() to report i2c_xfer() runtime errors
> 	instead of debug()
> 
> Changes in v3: None
> Changes in v2: None
> 
>   MAINTAINERS                                  |   4 +
>   doc/device-tree-bindings/i2c/i2c-cortina.txt |  18 ++
>   drivers/i2c/Kconfig                          |   8 +
>   drivers/i2c/Makefile                         |   1 +
>   drivers/i2c/i2c-cortina.c                    | 346 +++++++++++++++++++++++++++
>   drivers/i2c/i2c-cortina.h                    |  84 +++++++
>   6 files changed, 461 insertions(+)
>   create mode 100644 doc/device-tree-bindings/i2c/i2c-cortina.txt
>   create mode 100644 drivers/i2c/i2c-cortina.c
>   create mode 100644 drivers/i2c/i2c-cortina.h

This patch breaks travis build, see:

https://travis-ci.org/github/hsdenx/u-boot-i2c/jobs/692023084#L1313

Kann you please send a v3 which fixes this? 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] 13+ messages in thread

end of thread, other threads:[~2020-05-28  9:28 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-14 20:11 [PATCH v7 0/8] Cortina Access Drivers Package 2 Alex Nemirovsky
2020-05-14 20:11 ` [PATCH v7 1/8] mmc: ca_dw_mmc: Misc cleanup of driver Alex Nemirovsky
2020-05-15  9:33   ` Jaehoon Chung
2020-05-14 20:11 ` [PATCH v7 2/8] board: presidio-asic: update eMMC DT information Alex Nemirovsky
2020-05-14 20:11 ` [PATCH v7 3/8] i2c: i2c-cortina: added CAxxxx I2C support Alex Nemirovsky
2020-05-19  5:45   ` Heiko Schocher
2020-05-28  9:28   ` Heiko Schocher
2020-05-14 20:11 ` [PATCH v7 4/8] board: presidio-asic: Add " Alex Nemirovsky
2020-05-19  5:46   ` Heiko Schocher
2020-05-14 20:11 ` [PATCH v7 5/8] led: led_cortina: Add CAxxx LED support Alex Nemirovsky
2020-05-14 20:11 ` [PATCH v7 6/8] board: presidio: add " Alex Nemirovsky
2020-05-14 20:11 ` [PATCH v7 7/8] spi: ca_sflash: Add CAxxxx SPI Flash Controller Alex Nemirovsky
2020-05-14 20:11 ` [PATCH v7 8/8] board: presidio-asic: Add SPI NOR support Alex Nemirovsky

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.