All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v1 00/16] Add support for 96boards Dragonboard410C board
@ 2016-01-06 18:21 Mateusz Kulikowski
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 01/16] serial: Add support for Qualcomm serial port Mateusz Kulikowski
                   ` (15 more replies)
  0 siblings, 16 replies; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-06 18:21 UTC (permalink / raw)
  To: u-boot

Hi All,

I finally managed to cleanup RFC for submission. I've included changes in
each patch, there is a bit of them, but all are needed :)

This series requires wait_for_bit patch that I send few days ago:
https://patchwork.ozlabs.org/patch/561185/

Best Regards,
Mateusz

Changes in v1:
- Added (better) help to KConfig
- Added dt binding documentation
- Fixed include ordering
- Reworked msm_serial_getc
- Added error handling to msm_uart_clk_init (that is ignored later for now)
- Dropped unneeded DM_FLAG_PRE_RELOC
- Added dt binding documentation
- Added help to KConfig
- Use clrsetbits() to switch direction
- Fixed include order
- Added #defines for registers/register fields
- Added secondary compatible string
- Added commit message
- Added DT binding documentation
- Added Kconfig help
- Reordered includes
- Dropped redundant fields from msm_sdhc
- Cleaned up clock init code (+ added error handling)
- Dropped mdelay - use wait_for_bit instead in reset code
- Added missing newline after declarations
- Added error handling if "reg" is missing
- Converted base address to pointer
- No changes, just added Acked-by, Reviewed-by
- Reordered header files
- Removed braces around constant
- Added more verbose help to KConfig
- Added ULPI dependency to Kconfig
- Drop register #defines - use ehci-ci.h instead
- Create fixed ulpi viewport for device
- Use setbits/clearbits where possible
- Use wait_for_bit to reset controller
- Add dt binding documents
- Reorder includes
- Add read/write arguments documentation
- add binding documentation and better Kconfig help
- Changed a bit mapping
- Change include order
- Use clrsetbits* where possible
- Add one more supported dts id
- Handle missing fields in dt properly
- Added dt bindings
- Reoder includes
- Replaced extract_* macros with ordinary shift/mask
- Added error checking and whitespaces in probe
- Add binding doc
- Fixed inlcude ordering
- Merged direction_input and direction_output functions
- gpio_get: use switch instead of stacked if
- use pmic_clrsetbits
- add possibility to change prwkey bank name
- Handle invalid bindings
- Sanity HW check (i.e. check type/subtype registers)
- Fix include order
- Cleanup defines (added spaces for readibility)
- Base address is integer to avoid casting
- Use setbits_* family where possible
- Drop unneded comments, added newlines where needed
- Check return value of dev_get_addr
- Add binding for apq8016
- Cleaned up divider calculation
- Drop most of gpio.h (only empty file is needed)
- Add better help for dragonboard
- Move static structures to board_prepare_usb
- Add DM_SPMI to defconfig

Mateusz Kulikowski (16):
  serial: Add support for Qualcomm serial port
  gpio: Add support for Qualcomm gpio controller
  mmc: Add support for Qualcomm SDHCI controller
  ehci-hcd: Add init_after_reset
  usb: ulpi: Add Kconfig options for ULPI
  usb: Rename ehci-fsl.h to ehci-ci.h
  usb: ehci-ci: Add missing registers.
  ehci-ci.h: drop generic USBCMD fields
  ehci: Add support for Qualcomm EHCI
  drivers: Add SPMI bus uclass
  spmi: Add sandbox test driver
  drivers: spmi: Add support for Qualcomm SPMI bus driver
  pmic: Add support for Qualcomm PM8916 PMIC
  gpio: Add support for Qualcomm PM8916 gpios
  arm: Add support for Qualcomm Snapdragon family
  board: Add Qualcomm Dragonboard 410C support

 arch/arm/Kconfig                                   |  12 +
 arch/arm/Makefile                                  |   1 +
 arch/arm/dts/Makefile                              |   2 +
 arch/arm/dts/dragonboard410c.dts                   | 154 +++++++++++
 arch/arm/mach-snapdragon/Kconfig                   |  26 ++
 arch/arm/mach-snapdragon/Makefile                  |   8 +
 arch/arm/mach-snapdragon/clock-apq8016.c           | 262 ++++++++++++++++++
 arch/arm/mach-snapdragon/include/mach/gpio.h       |   9 +
 .../mach-snapdragon/include/mach/sysmap-apq8016.h  |  14 +
 arch/arm/mach-snapdragon/reset.c                   |  40 +++
 arch/sandbox/dts/sandbox.dts                       |  20 ++
 board/qualcomm/dragonboard410c/Kconfig             |  15 +
 board/qualcomm/dragonboard410c/Makefile            |   8 +
 board/qualcomm/dragonboard410c/dragonboard410c.c   | 111 ++++++++
 board/qualcomm/dragonboard410c/head.S              |  20 ++
 board/qualcomm/dragonboard410c/readme.txt          |  40 +++
 board/qualcomm/dragonboard410c/u-boot.lds          |  90 ++++++
 configs/dragonboard410c_defconfig                  |  30 ++
 configs/sandbox_defconfig                          |   4 +
 doc/device-tree-bindings/gpio/gpio-msm.txt         |  22 ++
 doc/device-tree-bindings/gpio/pm8916_gpio.txt      |  48 ++++
 doc/device-tree-bindings/mmc/msm_sdhci.txt         |  25 ++
 doc/device-tree-bindings/pmic/pm8916.txt           |  18 ++
 doc/device-tree-bindings/serial/msm-serial.txt     |   6 +
 doc/device-tree-bindings/spmi/spmi-msm.txt         |  26 ++
 doc/device-tree-bindings/spmi/spmi-sandbox.txt     |  34 +++
 doc/device-tree-bindings/usb/ehci-msm.txt          |  10 +
 drivers/Kconfig                                    |   2 +
 drivers/Makefile                                   |   1 +
 drivers/gpio/Kconfig                               |  24 ++
 drivers/gpio/Makefile                              |   3 +-
 drivers/gpio/msm_gpio.c                            | 129 +++++++++
 drivers/gpio/pm8916_gpio.c                         | 302 +++++++++++++++++++++
 drivers/mmc/Kconfig                                |   9 +
 drivers/mmc/Makefile                               |   1 +
 drivers/mmc/msm_sdhci.c                            | 180 ++++++++++++
 drivers/power/pmic/Kconfig                         |  14 +
 drivers/power/pmic/Makefile                        |   1 +
 drivers/power/pmic/pm8916.c                        |  96 +++++++
 drivers/serial/Kconfig                             |   8 +
 drivers/serial/Makefile                            |   1 +
 drivers/serial/serial_msm.c                        | 206 ++++++++++++++
 drivers/spmi/Kconfig                               |  23 ++
 drivers/spmi/Makefile                              |   9 +
 drivers/spmi/spmi-msm.c                            | 188 +++++++++++++
 drivers/spmi/spmi-sandbox.c                        | 157 +++++++++++
 drivers/spmi/spmi-uclass.c                         |  48 ++++
 drivers/usb/Kconfig                                |   2 +
 drivers/usb/host/Kconfig                           |  11 +
 drivers/usb/host/Makefile                          |   1 +
 drivers/usb/host/ehci-fsl.c                        |   2 +-
 drivers/usb/host/ehci-hcd.c                        |   6 +
 drivers/usb/host/ehci-mpc512x.c                    |   6 +-
 drivers/usb/host/ehci-msm.c                        | 179 ++++++++++++
 drivers/usb/host/ehci-mx5.c                        |   2 +-
 drivers/usb/host/ehci-mx6.c                        |   2 +-
 drivers/usb/host/ehci-mxc.c                        |   2 +-
 drivers/usb/host/ehci-vf.c                         |   2 +-
 drivers/usb/host/ehci-zynq.c                       |   2 +-
 drivers/usb/host/ehci.h                            |   1 +
 drivers/usb/ulpi/Kconfig                           |  10 +
 include/configs/dragonboard410c.h                  | 182 +++++++++++++
 include/dm/uclass-id.h                             |   1 +
 include/spmi/spmi.h                                |  47 ++++
 include/usb/{ehci-fsl.h => ehci-ci.h}              |  16 +-
 test/dm/Makefile                                   |   1 +
 test/dm/spmi.c                                     | 115 ++++++++
 67 files changed, 3029 insertions(+), 18 deletions(-)
 create mode 100644 arch/arm/dts/dragonboard410c.dts
 create mode 100644 arch/arm/mach-snapdragon/Kconfig
 create mode 100644 arch/arm/mach-snapdragon/Makefile
 create mode 100644 arch/arm/mach-snapdragon/clock-apq8016.c
 create mode 100644 arch/arm/mach-snapdragon/include/mach/gpio.h
 create mode 100644 arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h
 create mode 100644 arch/arm/mach-snapdragon/reset.c
 create mode 100644 board/qualcomm/dragonboard410c/Kconfig
 create mode 100644 board/qualcomm/dragonboard410c/Makefile
 create mode 100644 board/qualcomm/dragonboard410c/dragonboard410c.c
 create mode 100644 board/qualcomm/dragonboard410c/head.S
 create mode 100644 board/qualcomm/dragonboard410c/readme.txt
 create mode 100644 board/qualcomm/dragonboard410c/u-boot.lds
 create mode 100644 configs/dragonboard410c_defconfig
 create mode 100644 doc/device-tree-bindings/gpio/gpio-msm.txt
 create mode 100644 doc/device-tree-bindings/gpio/pm8916_gpio.txt
 create mode 100644 doc/device-tree-bindings/mmc/msm_sdhci.txt
 create mode 100644 doc/device-tree-bindings/pmic/pm8916.txt
 create mode 100644 doc/device-tree-bindings/serial/msm-serial.txt
 create mode 100644 doc/device-tree-bindings/spmi/spmi-msm.txt
 create mode 100644 doc/device-tree-bindings/spmi/spmi-sandbox.txt
 create mode 100644 doc/device-tree-bindings/usb/ehci-msm.txt
 create mode 100644 drivers/gpio/msm_gpio.c
 create mode 100644 drivers/gpio/pm8916_gpio.c
 create mode 100644 drivers/mmc/msm_sdhci.c
 create mode 100644 drivers/power/pmic/pm8916.c
 create mode 100644 drivers/serial/serial_msm.c
 create mode 100644 drivers/spmi/Kconfig
 create mode 100644 drivers/spmi/Makefile
 create mode 100644 drivers/spmi/spmi-msm.c
 create mode 100644 drivers/spmi/spmi-sandbox.c
 create mode 100644 drivers/spmi/spmi-uclass.c
 create mode 100644 drivers/usb/host/ehci-msm.c
 create mode 100644 drivers/usb/ulpi/Kconfig
 create mode 100644 include/configs/dragonboard410c.h
 create mode 100644 include/spmi/spmi.h
 rename include/usb/{ehci-fsl.h => ehci-ci.h} (96%)
 create mode 100644 test/dm/spmi.c

-- 
2.5.0

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

* [U-Boot] [PATCH v1 01/16] serial: Add support for Qualcomm serial port
  2016-01-06 18:21 [U-Boot] [PATCH v1 00/16] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
@ 2016-01-06 18:21 ` Mateusz Kulikowski
  2016-01-11 16:57   ` Simon Glass
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 02/16] gpio: Add support for Qualcomm gpio controller Mateusz Kulikowski
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-06 18:21 UTC (permalink / raw)
  To: u-boot

This driver works in "new" Data Mover UART mode, so
will be compatible with modern Qualcomm chips only.

Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
---

Changes in v1:
- Added (better) help to KConfig
- Added dt binding documentation
- Fixed include ordering
- Reworked msm_serial_getc
- Added error handling to msm_uart_clk_init (that is ignored later for now)
- Dropped unneeded DM_FLAG_PRE_RELOC

 doc/device-tree-bindings/serial/msm-serial.txt |   6 +
 drivers/serial/Kconfig                         |   8 +
 drivers/serial/Makefile                        |   1 +
 drivers/serial/serial_msm.c                    | 206 +++++++++++++++++++++++++
 4 files changed, 221 insertions(+)
 create mode 100644 doc/device-tree-bindings/serial/msm-serial.txt
 create mode 100644 drivers/serial/serial_msm.c

diff --git a/doc/device-tree-bindings/serial/msm-serial.txt b/doc/device-tree-bindings/serial/msm-serial.txt
new file mode 100644
index 0000000..48b8428
--- /dev/null
+++ b/doc/device-tree-bindings/serial/msm-serial.txt
@@ -0,0 +1,6 @@
+Qualcomm UART (Data Mover mode)
+
+Required properties:
+- compatible: must be "qcom,msm-uartdm-v1.4"
+- reg: start address and size of the registers
+- clock: interface clock (must accept baudrate as a frequency)
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 1fc287e..56d7b76 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -223,4 +223,12 @@ config UNIPHIER_SERIAL
 	  If you have a UniPhier based board and want to use the on-chip
 	  serial ports, say Y to this option. If unsure, say N.
 
+config MSM_SERIAL
+	bool "Qualcomm on-chip UART"
+	depends on DM_SERIAL
+	help
+	  Support Data Mover UART used on Qualcomm Snapdragon SoCs.
+	  It should support all Qualcomm devices with UARTDM version 1.4,
+	  for example APQ8016 and MSM8916.
+	  Single baudrate is supported in current implementation (115200).
 endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index dd87147..d052175 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_MXS_AUART) += mxs_auart.o
 obj-$(CONFIG_ARC_SERIAL) += serial_arc.o
 obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o
 obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o
+obj-$(CONFIG_MSM_SERIAL) += serial_msm.o
 
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_USB_TTY) += usbtty.o
diff --git a/drivers/serial/serial_msm.c b/drivers/serial/serial_msm.c
new file mode 100644
index 0000000..344f254
--- /dev/null
+++ b/drivers/serial/serial_msm.c
@@ -0,0 +1,206 @@
+/*
+ * Qualcomm UART driver
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * UART will work in Data Mover mode.
+ * Based on Linux driver.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <serial.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <linux/compiler.h>
+
+/* Serial registers - this driver works in uartdm mode*/
+
+#define UARTDM_DMRX             0x34 /* Max RX transfer length */
+#define UARTDM_NCF_TX           0x40 /* Number of chars to TX */
+
+#define UARTDM_RXFS             0x50 /* RX channel status register */
+#define UARTDM_RXFS_BUF_SHIFT   0x7  /* Number of bytes in the packing buffer */
+#define UARTDM_RXFS_BUF_MASK    0x7
+
+#define UARTDM_SR                0xA4 /* Status register */
+#define UARTDM_SR_RX_READY       (1 << 0) /* Word is the receiver FIFO */
+#define UARTDM_SR_TX_EMPTY       (1 << 3) /* Transmitter underrun */
+#define UARTDM_SR_UART_OVERRUN   (1 << 4) /* Receive overrun */
+
+#define UARTDM_CR                         0xA8 /* Command register */
+#define UARTDM_CR_CMD_RESET_ERR           (3 << 4) /* Clear overrun error */
+#define UARTDM_CR_CMD_RESET_STALE_INT     (8 << 4) /* Clears stale irq */
+#define UARTDM_CR_CMD_RESET_TX_READY      (3 << 8) /* Clears TX Ready irq*/
+#define UARTDM_CR_CMD_FORCE_STALE         (4 << 8) /* Causes stale event */
+#define UARTDM_CR_CMD_STALE_EVENT_DISABLE (6 << 8) /* Disable stale event */
+
+#define UARTDM_IMR                0xB0 /* Interrupt mask register */
+#define UARTDM_ISR                0xB4 /* Interrupt status register */
+#define UARTDM_ISR_TX_READY       0x80 /* TX FIFO empty */
+
+#define UARTDM_TF               0x100 /* UART Transmit FIFO register */
+#define UARTDM_RF               0x140 /* UART Receive FIFO register */
+
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct msm_serial_data {
+	phys_addr_t base;
+	unsigned chars_cnt; /* number of buffered chars */
+	uint32_t chars_buf; /* buffered chars */
+};
+
+static int msm_serial_getc(struct udevice *dev)
+{
+	struct msm_serial_data *p = dev_get_priv(dev);
+	char c;
+	unsigned sr;
+
+	if (!p->chars_buf) {
+		/* Clear error in case of buffer overrun */
+		if (readl(p->base + UARTDM_SR) & UARTDM_SR_UART_OVERRUN)
+			writel(UARTDM_CR_CMD_RESET_ERR, p->base + UARTDM_CR);
+
+		/* We need to fetch new character */
+		sr = readl(p->base + UARTDM_SR);
+
+		if (sr & UARTDM_SR_RX_READY) {
+			/* There are at least 4 bytes in fifo */
+			p->chars_buf = readl(p->base + UARTDM_RF);
+			p->chars_cnt = 4;
+		} else {
+			/* Check if there is anything in fifo */
+			p->chars_cnt = readl(p->base + UARTDM_RXFS);
+			/* Extract number of characters in UART packing buffer*/
+			p->chars_cnt = (p->chars_cnt >> UARTDM_RXFS_BUF_SHIFT) &
+				       UARTDM_RXFS_BUF_MASK;
+			if (!p->chars_cnt)
+				return -EAGAIN;
+
+			/* There is at least one charcter, move it to fifo */
+			writel(UARTDM_CR_CMD_FORCE_STALE, p->base + UARTDM_CR);
+
+			p->chars_buf = readl(p->base + UARTDM_RF);
+			writel(UARTDM_CR_CMD_RESET_STALE_INT,
+			       p->base + UARTDM_CR);
+			writel(0xFFFFFF, p->base + UARTDM_DMRX);
+		}
+	}
+
+	c = p->chars_buf & 0xFF;
+	p->chars_buf >>= 8;
+	p->chars_cnt--;
+
+	return c;
+}
+
+static int msm_serial_putc(struct udevice *dev, const char ch)
+{
+	struct msm_serial_data *p = dev_get_priv(dev);
+
+	if (!(readl(p->base + UARTDM_SR) & UARTDM_SR_TX_EMPTY) &&
+	    !(readl(p->base + UARTDM_ISR) & UARTDM_ISR_TX_READY))
+		return -EAGAIN;
+
+	writel(UARTDM_CR_CMD_RESET_TX_READY, p->base + UARTDM_CR);
+
+	writel(1, p->base + UARTDM_NCF_TX);
+	writel(ch, p->base + UARTDM_TF);
+	return 0;
+}
+
+static int msm_serial_pending(struct udevice *dev, bool input)
+{
+	struct msm_serial_data *p = dev_get_priv(dev);
+
+	if (input) {
+		if (p->chars_cnt)
+			return 1;
+		if (readl(p->base + UARTDM_SR) & UARTDM_SR_RX_READY)
+			return 1;
+		if (readl(p->base + UARTDM_RXFS))
+			return 1;
+	}
+	return 0;
+}
+
+static const struct dm_serial_ops msm_serial_ops = {
+	.putc = msm_serial_putc,
+	.pending = msm_serial_pending,
+	.getc = msm_serial_getc,
+};
+
+static int msm_uart_clk_init(struct udevice *dev)
+{
+	uint clk_rate = fdtdec_get_uint(gd->fdt_blob, dev->of_offset,
+					"clock-frequency", 115200);
+	uint clkd[2]; /* clk_id and clk_no */
+	int clk_offset;
+	struct udevice *clk;
+	int ret;
+
+	ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "clock", clkd,
+				   2);
+	if (ret)
+		return ret;
+
+	clk_offset = fdt_node_offset_by_phandle(gd->fdt_blob, clkd[0]);
+	if (clk_offset < 0)
+		return clk_offset;
+
+	ret = uclass_get_device_by_of_offset(UCLASS_CLK, clk_offset, &clk);
+	if (ret)
+		return ret;
+
+	ret = clk_set_periph_rate(clk, clkd[1], clk_rate);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int msm_serial_probe(struct udevice *dev)
+{
+	struct msm_serial_data *p = dev_get_priv(dev);
+
+	msm_uart_clk_init(dev); /* Ignore return value and hope clock was
+				  properly initialized by earlier loaders */
+
+	if (readl(p->base + UARTDM_SR) & UARTDM_SR_UART_OVERRUN)
+		writel(UARTDM_CR_CMD_RESET_ERR, p->base + UARTDM_CR);
+
+	writel(0, p->base + UARTDM_IMR);
+	writel(UARTDM_CR_CMD_STALE_EVENT_DISABLE, p->base + UARTDM_CR);
+	writel(0xFFFFFF, p->base + UARTDM_DMRX);
+	return 0;
+}
+
+static int msm_serial_ofdata_to_platdata(struct udevice *dev)
+{
+	struct msm_serial_data *p = dev_get_priv(dev);
+
+	p->base = dev_get_addr(dev);
+	if (p->base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+	return 0;
+}
+
+static const struct udevice_id msm_serial_ids[] = {
+	{ .compatible = "qcom,msm-uartdm-v1.4" },
+	{ }
+};
+
+U_BOOT_DRIVER(serial_msm) = {
+	.name	= "serial_msm",
+	.id	= UCLASS_SERIAL,
+	.of_match = msm_serial_ids,
+	.ofdata_to_platdata = msm_serial_ofdata_to_platdata,
+	.priv_auto_alloc_size = sizeof(struct msm_serial_data),
+	.probe = msm_serial_probe,
+	.ops	= &msm_serial_ops,
+};
-- 
2.5.0

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

* [U-Boot] [PATCH v1 02/16] gpio: Add support for Qualcomm gpio controller
  2016-01-06 18:21 [U-Boot] [PATCH v1 00/16] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 01/16] serial: Add support for Qualcomm serial port Mateusz Kulikowski
@ 2016-01-06 18:21 ` Mateusz Kulikowski
  2016-01-11 16:57   ` Simon Glass
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 03/16] mmc: Add support for Qualcomm SDHCI controller Mateusz Kulikowski
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-06 18:21 UTC (permalink / raw)
  To: u-boot

Add support for gpio controllers on Qualcomm Snapdragon devices.
This devices are usually called Top Level Mode Multiplexing in
Qualcomm documentation.

Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
---

Changes in v1:
- Added dt binding documentation
- Added help to KConfig
- Use clrsetbits() to switch direction
- Fixed include order
- Added #defines for registers/register fields
- Added secondary compatible string

 doc/device-tree-bindings/gpio/gpio-msm.txt |  22 +++++
 drivers/gpio/Kconfig                       |  14 ++++
 drivers/gpio/Makefile                      |   2 +-
 drivers/gpio/msm_gpio.c                    | 129 +++++++++++++++++++++++++++++
 4 files changed, 166 insertions(+), 1 deletion(-)
 create mode 100644 doc/device-tree-bindings/gpio/gpio-msm.txt
 create mode 100644 drivers/gpio/msm_gpio.c

diff --git a/doc/device-tree-bindings/gpio/gpio-msm.txt b/doc/device-tree-bindings/gpio/gpio-msm.txt
new file mode 100644
index 0000000..966ce0a
--- /dev/null
+++ b/doc/device-tree-bindings/gpio/gpio-msm.txt
@@ -0,0 +1,22 @@
+Qualcomm Snapdragon GPIO controller
+
+Required properties:
+- compatible : "qcom,msm8916-pinctrl" or "qcom,apq8016-pinctrl"
+- reg : Physical base address and length of the controller's registers.
+	This controller is called "Top Level Mode Multiplexing" in
+	Qualcomm documentation.
+- #gpio-cells : Should be one (pin number).
+- gpio-controller : Marks the device node as a GPIO controller.
+- gpio-count: Number of GPIO pins.
+- gpio-bank-name: (optional) name of gpio bank. As default "soc" is used.
+
+Example:
+
+soc_gpios: pinctrl at 1000000 {
+	compatible = "qcom,msm8916-pinctrl";
+	reg = <0x1000000 0x300000>;
+	gpio-controller;
+	gpio-count = <122>;
+	gpio-bank-name="soc";
+	#gpio-cells = <1>;
+};
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index e60e9fd..3d112b9 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -46,6 +46,20 @@ config LPC32XX_GPIO
 	help
 	  Support for the LPC32XX GPIO driver.
 
+config MSM_GPIO
+	bool "Qualcomm GPIO driver"
+	depends on DM_GPIO
+	default n
+	help
+	  Support GPIO controllers on Qualcomm Snapdragon family of SoCs.
+	  This controller have single bank (default name "soc"), every
+	  gpio has it's own set of registers.
+	  Only simple GPIO operations are supported (get/set, change of
+	  direction and checking pin function).
+	  Supported devices:
+	  - APQ8016
+	  - MSM8916
+
 config ROCKCHIP_GPIO
 	bool "Rockchip GPIO driver"
 	depends on DM_GPIO
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index fb4fd25..9520b1e 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -46,4 +46,4 @@ obj-$(CONFIG_STM32_GPIO)	+= stm32_gpio.o
 obj-$(CONFIG_ZYNQ_GPIO)		+= zynq_gpio.o
 obj-$(CONFIG_VYBRID_GPIO)	+= vybrid_gpio.o
 obj-$(CONFIG_HIKEY_GPIO)	+= hi6220_gpio.o
-
+obj-$(CONFIG_MSM_GPIO)		+= msm_gpio.o
diff --git a/drivers/gpio/msm_gpio.c b/drivers/gpio/msm_gpio.c
new file mode 100644
index 0000000..173c526
--- /dev/null
+++ b/drivers/gpio/msm_gpio.c
@@ -0,0 +1,129 @@
+/*
+ * Qualcomm GPIO driver
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Register offsets */
+#define GPIO_CONFIG_OFF(no)         ((no) * 0x1000)
+#define GPIO_IN_OUT_OFF(no)         ((no) * 0x1000 + 0x4)
+
+/* OE */
+#define GPIO_OE_DISABLE  (0x0 << 9)
+#define GPIO_OE_ENABLE   (0x1 << 9)
+#define GPIO_OE_MASK     (0x1 << 9)
+
+/* GPIO_IN_OUT register shifts. */
+#define GPIO_IN          0
+#define GPIO_OUT         1
+
+struct msm_gpio_bank {
+	phys_addr_t base;
+};
+
+static int msm_gpio_direction_input(struct udevice *dev, unsigned int gpio)
+{
+	struct msm_gpio_bank *priv = dev_get_priv(dev);
+	phys_addr_t reg = priv->base + GPIO_CONFIG_OFF(gpio);
+
+	/* Disable OE bit */
+	clrsetbits_le32(reg, GPIO_OE_MASK, GPIO_OE_DISABLE);
+	return 0;
+}
+
+static int msm_gpio_set_value(struct udevice *dev, unsigned gpio, int value)
+{
+	struct msm_gpio_bank *priv = dev_get_priv(dev);
+
+	value = !!value;
+	/* set value */
+	writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_OFF(gpio));
+	return 0;
+}
+
+static int msm_gpio_direction_output(struct udevice *dev, unsigned gpio,
+				     int value)
+{
+	struct msm_gpio_bank *priv = dev_get_priv(dev);
+	phys_addr_t reg = priv->base + GPIO_CONFIG_OFF(gpio);
+
+	value = !!value;
+	/* set value */
+	writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_OFF(gpio));
+	/* switch direction */
+	clrsetbits_le32(reg, GPIO_OE_MASK, GPIO_OE_ENABLE);
+	return 0;
+}
+
+static int msm_gpio_get_value(struct udevice *dev, unsigned gpio)
+{
+	struct msm_gpio_bank *priv = dev_get_priv(dev);
+
+	return !!(readl(priv->base + GPIO_IN_OUT_OFF(gpio)) >> GPIO_IN);
+}
+
+static int msm_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+	struct msm_gpio_bank *priv = dev_get_priv(dev);
+
+	if (readl(priv->base + GPIO_CONFIG_OFF(offset)) & GPIO_OE_ENABLE)
+		return GPIOF_OUTPUT;
+	return GPIOF_INPUT;
+}
+
+static const struct dm_gpio_ops gpio_msm_ops = {
+	.direction_input	= msm_gpio_direction_input,
+	.direction_output	= msm_gpio_direction_output,
+	.get_value		= msm_gpio_get_value,
+	.set_value		= msm_gpio_set_value,
+	.get_function		= msm_gpio_get_function,
+};
+
+static int msm_gpio_probe(struct udevice *dev)
+{
+	struct msm_gpio_bank *priv = dev_get_priv(dev);
+
+	priv->base = dev_get_addr(dev);
+	return priv->base == FDT_ADDR_T_NONE;
+}
+
+static int msm_gpio_ofdata_to_platdata(struct udevice *dev)
+{
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	uc_priv->gpio_count = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+					     "gpio-count", 0);
+	uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev->of_offset,
+					 "gpio-bank-name", NULL);
+	if (uc_priv->bank_name == NULL)
+		uc_priv->bank_name = "soc";
+	return 0;
+}
+
+static const struct udevice_id msm_gpio_ids[] = {
+	{ .compatible = "qcom,msm8916-pinctrl" },
+	{ .compatible = "qcom,apq8016-pinctrl" },
+	{ }
+};
+
+U_BOOT_DRIVER(gpio_msm) = {
+	.name	= "gpio_msm",
+	.id	= UCLASS_GPIO,
+	.of_match = msm_gpio_ids,
+	.ofdata_to_platdata = msm_gpio_ofdata_to_platdata,
+	.probe	= msm_gpio_probe,
+	.ops	= &gpio_msm_ops,
+	.priv_auto_alloc_size = sizeof(struct msm_gpio_bank),
+};
+
+
-- 
2.5.0

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

* [U-Boot] [PATCH v1 03/16] mmc: Add support for Qualcomm SDHCI controller
  2016-01-06 18:21 [U-Boot] [PATCH v1 00/16] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 01/16] serial: Add support for Qualcomm serial port Mateusz Kulikowski
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 02/16] gpio: Add support for Qualcomm gpio controller Mateusz Kulikowski
@ 2016-01-06 18:21 ` Mateusz Kulikowski
  2016-01-11 16:57   ` Simon Glass
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 04/16] ehci-hcd: Add init_after_reset Mateusz Kulikowski
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-06 18:21 UTC (permalink / raw)
  To: u-boot

Add support for SD/eMMC controller present on some Qualcomm Snapdragon
devices. This controller implements SDHCI 2.0 interface but requires
vendor-specific initialization.
Driver works in PIO mode as ADMA is not supported by U-Boot (yet).

Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
---

Changes in v1:
- Added commit message
- Added DT binding documentation
- Added Kconfig help
- Reordered includes
- Dropped redundant fields from msm_sdhc
- Cleaned up clock init code (+ added error handling)
- Dropped mdelay - use wait_for_bit instead in reset code
- Added missing newline after declarations
- Added error handling if "reg" is missing
- Converted base address to pointer

 doc/device-tree-bindings/mmc/msm_sdhci.txt |  25 ++++
 drivers/mmc/Kconfig                        |   9 ++
 drivers/mmc/Makefile                       |   1 +
 drivers/mmc/msm_sdhci.c                    | 180 +++++++++++++++++++++++++++++
 4 files changed, 215 insertions(+)
 create mode 100644 doc/device-tree-bindings/mmc/msm_sdhci.txt
 create mode 100644 drivers/mmc/msm_sdhci.c

diff --git a/doc/device-tree-bindings/mmc/msm_sdhci.txt b/doc/device-tree-bindings/mmc/msm_sdhci.txt
new file mode 100644
index 0000000..08a290c
--- /dev/null
+++ b/doc/device-tree-bindings/mmc/msm_sdhci.txt
@@ -0,0 +1,25 @@
+Qualcomm Snapdragon SDHCI controller
+
+Required properties:
+- compatible : "qcom,sdhci-msm-v4"
+- reg: Base address and length of registers:
+	- Host controller registers (SDHCI)
+	- SD Core registers
+- clock: interface clock (must accept SD bus clock as a frequency)
+
+Optional properties:
+- index: If there is more than one controller - controller index (required
+	by generic SDHCI code).
+- bus_width: Width of SD/eMMC bus (default 4)
+- clock-frequency: Frequency of SD/eMMC bus (default 400 kHz)
+
+Example:
+
+sdhci at 07864000 {
+	compatible = "qcom,sdhci-msm-v4";
+	reg = <0x7864900 0x11c 0x7864000 0x800>;
+	index = <0x1>;
+	bus-width = <0x4>;
+	clock = <&clkc 1>;
+	clock-frequency = <200000000>;
+};
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index ceae7bc..280f015 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -16,6 +16,15 @@ config DM_MMC
 	  appear as block devices in U-Boot and can support filesystems such
 	  as EXT4 and FAT.
 
+config MSM_SDHCI
+	bool "Qualcomm SDHCI controller"
+	depends on DM_MMC
+	help
+	  Enables support for SDHCI 2.0 controller present on some Qualcomm
+          Snapdragon devices. This device is compatible with eMMC v4.5 and
+          SD 3.0 specifications. Both SD and eMMC devices are supported.
+	  Card-detect gpios are not supported.
+
 config ROCKCHIP_DWMMC
 	bool "Rockchip SD/MMC controller support"
 	depends on DM_MMC && OF_CONTROL
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 5d35705..f4fdfca 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -49,3 +49,4 @@ else
 obj-$(CONFIG_GENERIC_MMC) += mmc_write.o
 endif
 
+obj-$(CONFIG_MSM_SDHCI) += msm_sdhci.o
diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c
new file mode 100644
index 0000000..1e2a29b
--- /dev/null
+++ b/drivers/mmc/msm_sdhci.c
@@ -0,0 +1,180 @@
+/*
+ * Qualcomm SDHCI driver - SD/eMMC controller
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * Based on Linux driver
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <sdhci.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+
+/* Non-standard registers needed for SDHCI startup */
+#define SDCC_MCI_POWER   0x0
+#define SDCC_MCI_POWER_SW_RST BIT(7)
+
+/* This is undocumented register */
+#define SDCC_MCI_VERSION             0x50
+#define SDCC_MCI_VERSION_MAJOR_SHIFT 28
+#define SDCC_MCI_VERSION_MAJOR_MASK  (0xf << SDCC_MCI_VERSION_MAJOR_SHIFT)
+#define SDCC_MCI_VERSION_MINOR_MASK  0xff
+
+#define SDCC_MCI_STATUS2 0x6C
+#define SDCC_MCI_STATUS2_MCI_ACT 0x1
+#define SDCC_MCI_HC_MODE 0x78
+
+/* Offset to SDHCI registers */
+#define SDCC_SDHCI_OFFSET 0x900
+
+/* Non standard (?) SDHCI register */
+#define SDHCI_VENDOR_SPEC_CAPABILITIES0  0x11c
+
+struct msm_sdhc {
+	struct sdhci_host host;
+	void *base;
+};
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int msm_sdc_clk_init(struct udevice *dev)
+{
+	uint clk_rate = fdtdec_get_uint(gd->fdt_blob, dev->of_offset,
+					"clock-frequency", 400000);
+	uint clkd[2]; /* clk_id and clk_no */
+	int clk_offset;
+	struct udevice *clk;
+	int ret;
+
+	ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "clock", clkd,
+				   2);
+	if (ret)
+		return ret;
+
+	clk_offset = fdt_node_offset_by_phandle(gd->fdt_blob, clkd[0]);
+	if (clk_offset < 0)
+		return clk_offset;
+
+	ret = uclass_get_device_by_of_offset(UCLASS_CLK, clk_offset, &clk);
+	if (ret)
+		return ret;
+
+	ret = clk_set_periph_rate(clk, clkd[1], clk_rate);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int msm_sdc_probe(struct udevice *dev)
+{
+	struct msm_sdhc *prv = dev_get_priv(dev);
+	struct sdhci_host *host = &prv->host;
+	u32 core_version, core_minor, core_major;
+	int ret;
+
+	host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B;
+
+	/* Init clocks */
+	ret = msm_sdc_clk_init(dev);
+	if (ret)
+		return ret;
+
+	/* Reset the core and Enable SDHC mode */
+	writel(readl(prv->base + SDCC_MCI_POWER) | SDCC_MCI_POWER_SW_RST,
+	       prv->base + SDCC_MCI_POWER);
+
+
+	/* Wait for reset to be written to register */
+	if (wait_for_bit(__func__, prv->base + SDCC_MCI_STATUS2,
+			 SDCC_MCI_STATUS2_MCI_ACT, false, 10, false)) {
+		printf("msm_sdhci: reset request failed\n");
+		return -EIO;
+	}
+
+	/* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */
+	if (wait_for_bit(__func__, prv->base + SDCC_MCI_POWER,
+			 SDCC_MCI_POWER_SW_RST, false, 2, false)) {
+		printf("msm_sdhci: stuck in reset\n");
+		return -ETIMEDOUT;
+	}
+
+	/* Enable host-controller mode */
+	writel(1, prv->base + SDCC_MCI_HC_MODE);
+
+	core_version = readl(prv->base + SDCC_MCI_VERSION);
+
+	core_major = (core_version & SDCC_MCI_VERSION_MAJOR_MASK);
+	core_major >>= SDCC_MCI_VERSION_MAJOR_SHIFT;
+
+	core_minor = core_version & SDCC_MCI_VERSION_MINOR_MASK;
+
+	/*
+	 * Support for some capabilities is not advertised by newer
+	 * controller versions and must be explicitly enabled.
+	 */
+	if (core_major >= 1 && core_minor != 0x11 && core_minor != 0x12) {
+		u32 caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
+		caps |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT;
+		writel(caps, host->ioaddr + SDHCI_VENDOR_SPEC_CAPABILITIES0);
+	}
+
+	/* Set host controller version */
+	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
+
+	/* automatically detect max and min speed */
+	return add_sdhci(host, 0, 0);
+}
+
+static int msm_sdc_remove(struct udevice *dev)
+{
+	struct msm_sdhc *priv = dev_get_priv(dev);
+
+	 /* Disable host-controller mode */
+	writel(0, priv->base + SDCC_MCI_HC_MODE);
+
+	return 0;
+}
+
+static int msm_ofdata_to_platdata(struct udevice *dev)
+{
+	struct udevice *parent = dev->parent;
+	struct msm_sdhc *priv = dev_get_priv(dev);
+	struct sdhci_host *host = &priv->host;
+
+	host->name = strdup(dev->name);
+	host->ioaddr = (void *)dev_get_addr(dev);
+	host->bus_width = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+					 "bus-width", 4);
+	host->index = fdtdec_get_uint(gd->fdt_blob, dev->of_offset, "index", 0);
+	priv->base = (void *)fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
+							      parent->of_offset,
+							      dev->of_offset,
+							      "reg", 1, NULL);
+	if (priv->base == (void *)FDT_ADDR_T_NONE ||
+	    host->ioaddr == (void *)FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	return 0;
+}
+
+static const struct udevice_id msm_mmc_ids[] = {
+	{ .compatible = "qcom,sdhci-msm-v4" },
+	{ }
+};
+
+U_BOOT_DRIVER(msm_sdc_drv) = {
+	.name		= "msm_sdc",
+	.id		= UCLASS_MMC,
+	.of_match	= msm_mmc_ids,
+	.ofdata_to_platdata = msm_ofdata_to_platdata,
+	.probe		= msm_sdc_probe,
+	.remove		= msm_sdc_remove,
+	.priv_auto_alloc_size = sizeof(struct msm_sdhc),
+};
-- 
2.5.0

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

* [U-Boot] [PATCH v1 04/16] ehci-hcd: Add init_after_reset
  2016-01-06 18:21 [U-Boot] [PATCH v1 00/16] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (2 preceding siblings ...)
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 03/16] mmc: Add support for Qualcomm SDHCI controller Mateusz Kulikowski
@ 2016-01-06 18:21 ` Mateusz Kulikowski
  2016-01-11 16:57   ` Simon Glass
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 05/16] usb: ulpi: Add Kconfig options for ULPI Mateusz Kulikowski
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-06 18:21 UTC (permalink / raw)
  To: u-boot

Some host controllers need addidional initialization after ehci_reset()
In non-dm implementation it is possible to use CONFIG_EHCI_HCD_INIT_AFTER_RESET.
This patch adds similar option to ehci drivers using dm.

Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
Acked-by: Marek Vasut <marex@denx.de>
Reviewed-by: Tom Rini <trini@konsulko.com>
---

Changes in v1:
- No changes, just added Acked-by, Reviewed-by

 drivers/usb/host/ehci-hcd.c | 6 ++++++
 drivers/usb/host/ehci.h     | 1 +
 2 files changed, 7 insertions(+)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index c85dbce..a54f817 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1654,6 +1654,12 @@ int ehci_register(struct udevice *dev, struct ehci_hccr *hccr,
 	if (ret)
 		goto err;
 
+	if (ops->init_after_reset) {
+		ret = ops->init_after_reset(ctrl);
+		if (ret)
+			goto err;
+	}
+
 	ret = ehci_common_init(ctrl, tweaks);
 	if (ret)
 		goto err;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index b41c04a..ed567fc 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -239,6 +239,7 @@ struct ehci_ops {
 	void (*powerup_fixup)(struct ehci_ctrl *ctrl, uint32_t *status_reg,
 			      uint32_t *reg);
 	uint32_t *(*get_portsc_register)(struct ehci_ctrl *ctrl, int port);
+	int (*init_after_reset)(struct ehci_ctrl *ctrl);
 };
 
 struct ehci_ctrl {
-- 
2.5.0

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

* [U-Boot] [PATCH v1 05/16] usb: ulpi: Add Kconfig options for ULPI
  2016-01-06 18:21 [U-Boot] [PATCH v1 00/16] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (3 preceding siblings ...)
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 04/16] ehci-hcd: Add init_after_reset Mateusz Kulikowski
@ 2016-01-06 18:21 ` Mateusz Kulikowski
  2016-01-06 20:49   ` Marek Vasut
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 06/16] usb: Rename ehci-fsl.h to ehci-ci.h Mateusz Kulikowski
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-06 18:21 UTC (permalink / raw)
  To: u-boot

The following options can be now enabled via defconfig:
- CONFIG_USB_ULPI
- CONFIG_USB_ULPI_VIEWPORT
- CONFIG_USB_ULPI_VIEWPORT_OMAP

Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
---

Changes in v1: New patch

 drivers/usb/Kconfig      |  2 ++
 drivers/usb/ulpi/Kconfig | 10 ++++++++++
 2 files changed, 12 insertions(+)
 create mode 100644 drivers/usb/ulpi/Kconfig

diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index abb06fc..57b99f2 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -53,6 +53,8 @@ source "drivers/usb/musb-new/Kconfig"
 
 source "drivers/usb/emul/Kconfig"
 
+source "drivers/usb/ulpi/Kconfig"
+
 comment "USB peripherals"
 
 config USB_STORAGE
diff --git a/drivers/usb/ulpi/Kconfig b/drivers/usb/ulpi/Kconfig
new file mode 100644
index 0000000..f3210bc
--- /dev/null
+++ b/drivers/usb/ulpi/Kconfig
@@ -0,0 +1,10 @@
+comment "ULPI drivers"
+
+config USB_ULPI
+	bool
+
+config USB_ULPI_VIEWPORT
+	bool
+
+config USB_ULPI_VIEWPORT_OMAP
+	bool
-- 
2.5.0

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

* [U-Boot] [PATCH v1 06/16] usb: Rename ehci-fsl.h to ehci-ci.h
  2016-01-06 18:21 [U-Boot] [PATCH v1 00/16] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (4 preceding siblings ...)
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 05/16] usb: ulpi: Add Kconfig options for ULPI Mateusz Kulikowski
@ 2016-01-06 18:21 ` Mateusz Kulikowski
  2016-01-06 20:51   ` Marek Vasut
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 07/16] usb: ehci-ci: Add missing registers Mateusz Kulikowski
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-06 18:21 UTC (permalink / raw)
  To: u-boot

Most of ehci-fsl header describe USB controller
designed by Chipidea and used by various SoC vendors.

This patch renames it to a generic header: ehci-ci.h
Contents of file are not changed (so it contains several
references to freescale SoCs).

Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
---

Changes in v1: New patch

 drivers/usb/host/ehci-fsl.c           | 2 +-
 drivers/usb/host/ehci-mpc512x.c       | 2 +-
 drivers/usb/host/ehci-mx5.c           | 2 +-
 drivers/usb/host/ehci-mx6.c           | 2 +-
 drivers/usb/host/ehci-mxc.c           | 2 +-
 drivers/usb/host/ehci-vf.c            | 2 +-
 drivers/usb/host/ehci-zynq.c          | 2 +-
 include/usb/{ehci-fsl.h => ehci-ci.h} | 6 +++---
 8 files changed, 10 insertions(+), 10 deletions(-)
 rename include/usb/{ehci-fsl.h => ehci-ci.h} (99%)

diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 97b7f14..4bcea9d 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -12,7 +12,7 @@
 #include <pci.h>
 #include <usb.h>
 #include <asm/io.h>
-#include <usb/ehci-fsl.h>
+#include <usb/ehci-ci.h>
 #include <hwconfig.h>
 #include <fsl_usb.h>
 #include <fdt_support.h>
diff --git a/drivers/usb/host/ehci-mpc512x.c b/drivers/usb/host/ehci-mpc512x.c
index b320c4a..4b50ac8 100644
--- a/drivers/usb/host/ehci-mpc512x.c
+++ b/drivers/usb/host/ehci-mpc512x.c
@@ -17,7 +17,7 @@
 #include <pci.h>
 #include <usb.h>
 #include <asm/io.h>
-#include <usb/ehci-fsl.h>
+#include <usb/ehci-ci.h>
 
 #include "ehci.h"
 
diff --git a/drivers/usb/host/ehci-mx5.c b/drivers/usb/host/ehci-mx5.c
index d319962..2b36ceb 100644
--- a/drivers/usb/host/ehci-mx5.c
+++ b/drivers/usb/host/ehci-mx5.c
@@ -9,7 +9,7 @@
 #include <usb.h>
 #include <errno.h>
 #include <linux/compiler.h>
-#include <usb/ehci-fsl.h>
+#include <usb/ehci-ci.h>
 #include <asm/io.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/clock.h>
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index e1c67f7..a981b50 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -10,7 +10,7 @@
 #include <errno.h>
 #include <wait_bit.h>
 #include <linux/compiler.h>
-#include <usb/ehci-fsl.h>
+#include <usb/ehci-ci.h>
 #include <asm/io.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/clock.h>
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index f09c75a..f8324ee 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -9,7 +9,7 @@
 #include <usb.h>
 #include <asm/io.h>
 #include <asm/arch/imx-regs.h>
-#include <usb/ehci-fsl.h>
+#include <usb/ehci-ci.h>
 #include <errno.h>
 
 #include "ehci.h"
diff --git a/drivers/usb/host/ehci-vf.c b/drivers/usb/host/ehci-vf.c
index 98e0fc6..f5a8bb5 100644
--- a/drivers/usb/host/ehci-vf.c
+++ b/drivers/usb/host/ehci-vf.c
@@ -17,7 +17,7 @@
 #include <asm/arch/crm_regs.h>
 #include <asm/imx-common/iomux-v3.h>
 #include <asm/imx-common/regs-usbphy.h>
-#include <usb/ehci-fsl.h>
+#include <usb/ehci-ci.h>
 
 #include "ehci.h"
 
diff --git a/drivers/usb/host/ehci-zynq.c b/drivers/usb/host/ehci-zynq.c
index 7770d05..37a7935 100644
--- a/drivers/usb/host/ehci-zynq.c
+++ b/drivers/usb/host/ehci-zynq.c
@@ -11,7 +11,7 @@
 #include <asm/arch/sys_proto.h>
 #include <asm/io.h>
 #include <usb.h>
-#include <usb/ehci-fsl.h>
+#include <usb/ehci-ci.h>
 #include <usb/ulpi.h>
 
 #include "ehci.h"
diff --git a/include/usb/ehci-fsl.h b/include/usb/ehci-ci.h
similarity index 99%
rename from include/usb/ehci-fsl.h
rename to include/usb/ehci-ci.h
index e9349b5..725aec5 100644
--- a/include/usb/ehci-fsl.h
+++ b/include/usb/ehci-ci.h
@@ -6,8 +6,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#ifndef _EHCI_FSL_H
-#define _EHCI_FSL_H
+#ifndef _EHCI_CI_H
+#define _EHCI_CI_H
 
 #include <asm/processor.h>
 
@@ -285,4 +285,4 @@ int usb_phy_mode(int port);
 int board_ehci_hcd_init(int port);
 int board_usb_phy_mode(int port);
 
-#endif /* _EHCI_FSL_H */
+#endif /* _EHCI_CI_H */
-- 
2.5.0

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

* [U-Boot] [PATCH v1 07/16] usb: ehci-ci: Add missing registers.
  2016-01-06 18:21 [U-Boot] [PATCH v1 00/16] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (5 preceding siblings ...)
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 06/16] usb: Rename ehci-fsl.h to ehci-ci.h Mateusz Kulikowski
@ 2016-01-06 18:21 ` Mateusz Kulikowski
  2016-01-06 20:53   ` Marek Vasut
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 08/16] ehci-ci.h: drop generic USBCMD fields Mateusz Kulikowski
                   ` (8 subsequent siblings)
  15 siblings, 1 reply; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-06 18:21 UTC (permalink / raw)
  To: u-boot

Some registers of usb_ehci were marked as reserved.
This may be true for some variants of Chipidea USB core, but they have
meaning on other devices.

The following registers were added:
sbusstatus/sbusmode: AHB-related registers
genconfig*: Auxiluary IP core configuration registers.

Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
---

Changes in v1: New patch

 include/usb/ehci-ci.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/usb/ehci-ci.h b/include/usb/ehci-ci.h
index 725aec5..305b180 100644
--- a/include/usb/ehci-ci.h
+++ b/include/usb/ehci-ci.h
@@ -191,7 +191,11 @@ struct usb_ehci {
 	u32     gptimer1_ld;	/* 0x088 - General Purpose Timer 1 load value */
 	u32     gptimer1_ctrl;	/* 0x08C - General Purpose Timer 1 control */
 	u32	sbuscfg;	/* 0x090 - System Bus Interface Control */
-	u8	res2[0x6C];
+	u32	sbusstatus;	/* 0x094 - System Bus Interface Status */
+	u32	sbusmode;	/* 0x098 - System Bus Interface Mode */
+	u32	genconfig;	/* 0x09C - USB Core Configuration */
+	u32	genconfig2;	/* 0x0A0 - USB Core Configuration 2 */
+	u8	res2[0x5c];
 	u8	caplength;	/* 0x100 - Capability Register Length */
 	u8	res3[0x1];
 	u16	hciversion;	/* 0x102 - Host Interface Version */
-- 
2.5.0

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

* [U-Boot] [PATCH v1 08/16] ehci-ci.h: drop generic USBCMD fields
  2016-01-06 18:21 [U-Boot] [PATCH v1 00/16] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (6 preceding siblings ...)
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 07/16] usb: ehci-ci: Add missing registers Mateusz Kulikowski
@ 2016-01-06 18:21 ` Mateusz Kulikowski
  2016-01-06 20:54   ` Marek Vasut
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 09/16] ehci: Add support for Qualcomm EHCI Mateusz Kulikowski
                   ` (7 subsequent siblings)
  15 siblings, 1 reply; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-06 18:21 UTC (permalink / raw)
  To: u-boot

Use definitions from ehci.h instead.

Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
---

Changes in v1: New patch

 drivers/usb/host/ehci-mpc512x.c | 4 ++--
 include/usb/ehci-ci.h           | 4 ----
 2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/host/ehci-mpc512x.c b/drivers/usb/host/ehci-mpc512x.c
index 4b50ac8..bb4f461 100644
--- a/drivers/usb/host/ehci-mpc512x.c
+++ b/drivers/usb/host/ehci-mpc512x.c
@@ -93,7 +93,7 @@ static int reset_usb_controller(volatile struct usb_ehci *ehci)
 	unsigned int i;
 
 	/* Command a reset of the USB Controller */
-	out_be32(&(ehci->usbcmd), EHCI_FSL_USBCMD_RST);
+	out_be32(&(ehci->usbcmd), CMD_RESET);
 
 	/* Wait for the reset process to finish */
 	for (i = 65535 ; i > 0 ; i--) {
@@ -101,7 +101,7 @@ static int reset_usb_controller(volatile struct usb_ehci *ehci)
 		 * The host will set this bit to zero once the
 		 * reset process is complete
 		 */
-		if ((in_be32(&(ehci->usbcmd)) & EHCI_FSL_USBCMD_RST) == 0)
+		if ((in_be32(&(ehci->usbcmd)) & CMD_RESET) == 0)
 			return 0;
 	}
 
diff --git a/include/usb/ehci-ci.h b/include/usb/ehci-ci.h
index 305b180..586d32a 100644
--- a/include/usb/ehci-ci.h
+++ b/include/usb/ehci-ci.h
@@ -97,10 +97,6 @@
 #define INTR_DATA_PULSING_EN	(0x1<<30)
 #define INTSTS_MASK		(0x00ff0000)
 
-/* USBCMD Bits of interest */
-#define EHCI_FSL_USBCMD_RST	(1 <<  1)
-#define EHCI_FSL_USBCMD_RS	(1 <<  0)
-
 #define  INTERRUPT_ENABLE_BITS_MASK  \
 		(INTR_USB_ID_EN		| \
 		INTR_1MS_TIMER_EN	| \
-- 
2.5.0

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

* [U-Boot] [PATCH v1 09/16] ehci: Add support for Qualcomm EHCI
  2016-01-06 18:21 [U-Boot] [PATCH v1 00/16] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (7 preceding siblings ...)
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 08/16] ehci-ci.h: drop generic USBCMD fields Mateusz Kulikowski
@ 2016-01-06 18:21 ` Mateusz Kulikowski
  2016-01-06 21:04   ` Marek Vasut
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 10/16] drivers: Add SPMI bus uclass Mateusz Kulikowski
                   ` (6 subsequent siblings)
  15 siblings, 1 reply; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-06 18:21 UTC (permalink / raw)
  To: u-boot

This driver is able to reconfigure OTG controller into HOST mode.
Board can add board-specific initialization as board_prepare_usb().
It requires USB_ULPI_VIEWPORT enabled in board configuration.

Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
---

Changes in v1:
- Reordered header files
- Removed braces around constant
- Added more verbose help to KConfig
- Added ULPI dependency to Kconfig
- Drop register #defines - use ehci-ci.h instead
- Create fixed ulpi viewport for device
- Use setbits/clearbits where possible
- Use wait_for_bit to reset controller
- Add dt binding documents

 doc/device-tree-bindings/usb/ehci-msm.txt |  10 ++
 drivers/usb/host/Kconfig                  |  11 ++
 drivers/usb/host/Makefile                 |   1 +
 drivers/usb/host/ehci-msm.c               | 179 ++++++++++++++++++++++++++++++
 4 files changed, 201 insertions(+)
 create mode 100644 doc/device-tree-bindings/usb/ehci-msm.txt
 create mode 100644 drivers/usb/host/ehci-msm.c

diff --git a/doc/device-tree-bindings/usb/ehci-msm.txt b/doc/device-tree-bindings/usb/ehci-msm.txt
new file mode 100644
index 0000000..205bb07
--- /dev/null
+++ b/doc/device-tree-bindings/usb/ehci-msm.txt
@@ -0,0 +1,10 @@
+Chipidea EHCI controller (part of OTG controller) used on Qualcomm devices.
+
+Required properties:
+- compatible: must be "qcom,ehci-host"
+- reg: start address and size of the registers
+
+ehci at 78d9000 {
+	compatible = "qcom,ehci-host";
+	reg = <0x78d9000 0x400>;
+};
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 39f7185..ff5e843 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -74,6 +74,17 @@ config USB_EHCI_MX6
 	---help---
 	  Enables support for the on-chip EHCI controller on i.MX6 SoCs.
 
+config USB_EHCI_MSM
+	bool "Support for Qualcomm on-chip EHCI USB controller"
+	depends on DM_USB
+	select USB_ULPI_VIEWPORT
+	default n
+	---help---
+	  Enables support for the on-chip EHCI controller on Qualcomm
+	  Snapdragon SoCs.
+	  This driver supports combination of Chipidea USB controller
+	  and Synapsys USB PHY in host mode only.
+
 config USB_EHCI_UNIPHIER
 	bool "Support for UniPhier on-chip EHCI USB controller"
 	depends on ARCH_UNIPHIER && OF_CONTROL
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 6183b80..426b066 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_USB_EHCI_MX7) += ehci-mx6.o
 obj-$(CONFIG_USB_EHCI_OMAP) += ehci-omap.o
 obj-$(CONFIG_USB_EHCI_PPC4XX) += ehci-ppc4xx.o
 obj-$(CONFIG_USB_EHCI_MARVELL) += ehci-marvell.o
+obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o
 obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o
 obj-$(CONFIG_USB_EHCI_SPEAR) += ehci-spear.o
 obj-$(CONFIG_USB_EHCI_SUNXI) += ehci-sunxi.o
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
new file mode 100644
index 0000000..2efa880
--- /dev/null
+++ b/drivers/usb/host/ehci-msm.c
@@ -0,0 +1,179 @@
+/*
+ * Qualcomm EHCI driver
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * Based on Linux driver
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <usb.h>
+#include <usb/ehci-ci.h>
+#include <usb/ulpi.h>
+#include <wait_bit.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <linux/compat.h>
+#include "ehci.h"
+
+/* PHY viewport regs */
+#define ULPI_MISC_A_READ         0x96
+#define ULPI_MISC_A_SET          0x97
+#define ULPI_MISC_A_CLEAR        0x98
+#define ULPI_MISC_A_VBUSVLDEXTSEL    (1 << 1)
+#define ULPI_MISC_A_VBUSVLDEXT       (1 << 0)
+
+#define GEN2_SESS_VLD_CTRL_EN (1 << 7)
+
+#define SESS_VLD_CTRL         (1 << 25)
+
+struct msm_ehci_priv {
+	struct ehci_ctrl ctrl; /* Needed by EHCI */
+	struct usb_ehci *ehci; /* Start of IP core*/
+	struct ulpi_viewport ulpi_vp; /* ULPI Viewport */
+};
+
+int __weak board_prepare_usb(enum usb_init_type type)
+{
+	return 0;
+}
+
+static void setup_usb_phy(struct msm_ehci_priv *priv)
+{
+	/* Select and enable external configuration with USB PHY */
+	ulpi_write(&priv->ulpi_vp, (u8 *)ULPI_MISC_A_SET,
+		   ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT);
+}
+
+static void reset_usb_phy(struct msm_ehci_priv *priv)
+{
+	/* Disable VBUS mimicing in the controller. */
+	ulpi_write(&priv->ulpi_vp, (u8 *)ULPI_MISC_A_CLEAR,
+		   ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT);
+}
+
+
+static int msm_init_after_reset(struct ehci_ctrl *dev)
+{
+	struct msm_ehci_priv *p = container_of(dev, struct msm_ehci_priv, ctrl);
+	struct usb_ehci *ehci = p->ehci;
+
+	/* select ULPI phy */
+	writel(0x80000000, &ehci->portsc);
+	setup_usb_phy(p);
+
+	/* Enable sess_vld */
+	setbits_le32(&ehci->genconfig2, GEN2_SESS_VLD_CTRL_EN);
+
+	/* Enable external vbus configuration in the LINK */
+	setbits_le32(&ehci->usbcmd, SESS_VLD_CTRL);
+
+	/* USB_OTG_HS_AHB_BURST */
+	writel(0x0, &ehci->sbuscfg);
+
+	/* USB_OTG_HS_AHB_MODE: HPROT_MODE */
+	/* Bus access related config. */
+	writel(0x08, &ehci->sbusmode);
+
+	/* set mode to host controller */
+	writel(CM_HOST, &ehci->usbmode);
+
+	return 0;
+}
+
+static const struct ehci_ops msm_ehci_ops = {
+	.init_after_reset = msm_init_after_reset
+};
+
+static int ehci_usb_probe(struct udevice *dev)
+{
+	struct msm_ehci_priv *p = dev_get_priv(dev);
+	struct usb_ehci *ehci = p->ehci;
+	struct ehci_hccr *hccr;
+	struct ehci_hcor *hcor;
+	int ret;
+
+	hccr = (struct ehci_hccr *)((phys_addr_t)&ehci->caplength);
+	hcor = (struct ehci_hcor *)((phys_addr_t)hccr +
+			HC_LENGTH(ehci_readl(&(hccr)->cr_capbase)));
+
+	ret = board_prepare_usb(USB_INIT_HOST);
+	if (ret < 0)
+		return ret;
+
+
+	return ehci_register(dev, hccr, hcor, &msm_ehci_ops, 0, USB_INIT_HOST);
+}
+
+static int ehci_usb_remove(struct udevice *dev)
+{
+	struct msm_ehci_priv *p = dev_get_priv(dev);
+	struct usb_ehci *ehci = p->ehci;
+	int ret;
+
+	ret = ehci_deregister(dev);
+	if (ret)
+		return ret;
+
+	/* Stop controller. */
+	clrbits_le32(&ehci->usbcmd, CMD_RUN);
+
+	reset_usb_phy(p);
+
+	ret = board_prepare_usb(USB_INIT_DEVICE); /* Board specific hook */
+	if (ret < 0)
+		return ret;
+
+	/* Reset controller */
+	setbits_le32(&ehci->usbcmd, CMD_RESET);
+
+	/* Wait for reset */
+	if (wait_for_bit(__func__, &ehci->usbcmd, CMD_RESET, false, 30,
+			 false)) {
+		printf("Stuck on USB reset.\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int ehci_usb_ofdata_to_platdata(struct udevice *dev)
+{
+	struct msm_ehci_priv *priv = dev_get_priv(dev);
+
+	priv->ulpi_vp.port_num = 0;
+	priv->ehci = (void *)dev_get_addr(dev);
+
+	if (priv->ehci == (void *)FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	/* Warning: this will not work if viewport address is > 64 bit due to
+	 * ULPI design.
+	 */
+	priv->ulpi_vp.viewport_addr = (phys_addr_t)&priv->ehci->ulpi_viewpoint;
+
+	return 0;
+}
+
+static const struct udevice_id ehci_usb_ids[] = {
+	{ .compatible = "qcom,ehci-host", },
+	{ }
+};
+
+U_BOOT_DRIVER(usb_ehci) = {
+	.name	= "ehci_msm",
+	.id	= UCLASS_USB,
+	.of_match = ehci_usb_ids,
+	.ofdata_to_platdata = ehci_usb_ofdata_to_platdata,
+	.probe = ehci_usb_probe,
+	.remove = ehci_usb_remove,
+	.ops	= &ehci_usb_ops,
+	.priv_auto_alloc_size = sizeof(struct msm_ehci_priv),
+	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
+};
-- 
2.5.0

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

* [U-Boot] [PATCH v1 10/16] drivers: Add SPMI bus uclass
  2016-01-06 18:21 [U-Boot] [PATCH v1 00/16] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (8 preceding siblings ...)
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 09/16] ehci: Add support for Qualcomm EHCI Mateusz Kulikowski
@ 2016-01-06 18:21 ` Mateusz Kulikowski
  2016-01-11 16:57   ` Simon Glass
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 11/16] spmi: Add sandbox test driver Mateusz Kulikowski
                   ` (5 subsequent siblings)
  15 siblings, 1 reply; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-06 18:21 UTC (permalink / raw)
  To: u-boot

Qualcom processors use proprietary bus to talk with PMIC devices -
SPMI (System Power Management Interface).

On wiring level it is similar to I2C, but on protocol level, it's
multi-master and has simple autodetection capabilities.
This commit adds simple uclass that provides bus read/write interface.

Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
---

Changes in v1:
- Reorder includes
- Add read/write arguments documentation

 drivers/Kconfig            |  2 ++
 drivers/Makefile           |  1 +
 drivers/spmi/Kconfig       | 10 ++++++++++
 drivers/spmi/Makefile      |  7 +++++++
 drivers/spmi/spmi-uclass.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h     |  1 +
 include/spmi/spmi.h        | 47 +++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 116 insertions(+)
 create mode 100644 drivers/spmi/Kconfig
 create mode 100644 drivers/spmi/Makefile
 create mode 100644 drivers/spmi/spmi-uclass.c
 create mode 100644 include/spmi/spmi.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index c481e93..4cbe976 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -52,6 +52,8 @@ source "drivers/remoteproc/Kconfig"
 
 source "drivers/rtc/Kconfig"
 
+source "drivers/spmi/Kconfig"
+
 source "drivers/serial/Kconfig"
 
 source "drivers/sound/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index c9031f2..7ae72c0 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -53,6 +53,7 @@ obj-y += pcmcia/
 obj-y += dfu/
 obj-y += rtc/
 obj-y += sound/
+obj-y += spmi/
 obj-y += timer/
 obj-y += tpm/
 obj-y += twserial/
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
new file mode 100644
index 0000000..440431a
--- /dev/null
+++ b/drivers/spmi/Kconfig
@@ -0,0 +1,10 @@
+menu "SPMI support"
+
+config DM_SPMI
+	bool "Enable SPMI bus support"
+	depends on DM
+	---help---
+	  Select this to enable to support SPMI bus.
+	  SPMI (System Power Management Interface) bus is used
+	  to connect PMIC devices on various SoCs.
+endmenu
diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
new file mode 100644
index 0000000..2015b1a
--- /dev/null
+++ b/drivers/spmi/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_DM_SPMI)  += spmi-uclass.o
diff --git a/drivers/spmi/spmi-uclass.c b/drivers/spmi/spmi-uclass.c
new file mode 100644
index 0000000..7d5429a
--- /dev/null
+++ b/drivers/spmi/spmi-uclass.c
@@ -0,0 +1,48 @@
+/*
+ * SPMI bus uclass driver
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/root.h>
+#include <errno.h>
+#include <spmi/spmi.h>
+#include <linux/ctype.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int spmi_reg_read(struct udevice *dev, int usid, int pid, int reg)
+{
+	const struct dm_spmi_ops *ops = dev_get_driver_ops(dev);
+
+	if (!ops || !ops->read)
+		return -ENOSYS;
+
+	return ops->read(dev, usid, pid, reg);
+}
+
+int spmi_reg_write(struct udevice *dev, int usid, int pid, int reg,
+		   uint8_t value)
+{
+	const struct dm_spmi_ops *ops = dev_get_driver_ops(dev);
+
+	if (!ops || !ops->write)
+		return -ENOSYS;
+
+	return ops->write(dev, usid, pid, reg, value);
+}
+
+static int spmi_post_bind(struct udevice *dev)
+{
+	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+}
+
+UCLASS_DRIVER(spmi) = {
+	.id		= UCLASS_SPMI,
+	.name		= "spmi",
+	.post_bind	= spmi_post_bind,
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 27fa0b6..772e780 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -57,6 +57,7 @@ enum uclass_id {
 	UCLASS_RTC,		/* Real time clock device */
 	UCLASS_SERIAL,		/* Serial UART */
 	UCLASS_SPI,		/* SPI bus */
+	UCLASS_SPMI,		/* System Power Management Interface bus */
 	UCLASS_SPI_FLASH,	/* SPI flash */
 	UCLASS_SPI_GENERIC,	/* Generic SPI flash target */
 	UCLASS_SYSCON,		/* System configuration device */
diff --git a/include/spmi/spmi.h b/include/spmi/spmi.h
new file mode 100644
index 0000000..65a49bd
--- /dev/null
+++ b/include/spmi/spmi.h
@@ -0,0 +1,47 @@
+#ifndef _SPMI_SPMI_H
+#define _SPMI_SPMI_H
+
+/**
+ * struct dm_spmi_ops - SPMI device I/O interface
+ *
+ * Should be implemented by UCLASS_SPMI device drivers. The standard
+ * device operations provides the I/O interface for it's childs.
+ *
+ * @read:      read register 'reg' of slave 'usid' and peripheral 'pid'
+ * @write:     write register 'reg' of slave 'usid' and peripheral 'pid'
+ *
+ * Each register is 8-bit, both read and write can return negative values
+ * on error.
+ */
+struct dm_spmi_ops {
+	int (*read)(struct udevice *dev, int usid, int pid, int reg);
+	int (*write)(struct udevice *dev, int usid, int pid, int reg,
+		     uint8_t value);
+};
+
+/**
+ * spmi_reg_read() - read a register from specific slave/peripheral
+ *
+ * @dev:	SPMI bus to read
+ * @usid	SlaveID
+ * @pid		Peripheral ID
+ * @reg:	Register to read
+ * @return value read on success or negative value of errno.
+ */
+int spmi_reg_read(struct udevice *dev, int usid, int pid, int reg);
+
+/**
+ * spmi_reg_write() - write a register of specific slave/peripheral
+ *
+ * @dev:	SPMI bus to write
+ * @usid	SlaveID
+ * @pid		Peripheral ID
+ * @reg:	Register to write
+ * @value:	Value to write
+ * @return 0 on success or negative value of errno.
+ */
+int spmi_reg_write(struct udevice *dev, int usid, int pid, int reg,
+		   uint8_t value);
+
+#endif
+
-- 
2.5.0

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

* [U-Boot] [PATCH v1 11/16] spmi: Add sandbox test driver
  2016-01-06 18:21 [U-Boot] [PATCH v1 00/16] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (9 preceding siblings ...)
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 10/16] drivers: Add SPMI bus uclass Mateusz Kulikowski
@ 2016-01-06 18:21 ` Mateusz Kulikowski
  2016-01-11 16:57   ` Simon Glass
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 12/16] drivers: spmi: Add support for Qualcomm SPMI bus driver Mateusz Kulikowski
                   ` (4 subsequent siblings)
  15 siblings, 1 reply; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-06 18:21 UTC (permalink / raw)
  To: u-boot

This patch adds emulated spmi bus controller with part of
pm8916 pmic on it to sandbox and tests validating SPMI uclass.

Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
---

Changes in v1: None

 arch/sandbox/dts/sandbox.dts                   |  20 ++++
 configs/sandbox_defconfig                      |   4 +
 doc/device-tree-bindings/spmi/spmi-sandbox.txt |  34 ++++++
 drivers/spmi/Kconfig                           |   8 ++
 drivers/spmi/Makefile                          |   1 +
 drivers/spmi/spmi-sandbox.c                    | 157 +++++++++++++++++++++++++
 test/dm/Makefile                               |   1 +
 test/dm/spmi.c                                 | 115 ++++++++++++++++++
 8 files changed, 340 insertions(+)
 create mode 100644 doc/device-tree-bindings/spmi/spmi-sandbox.txt
 create mode 100644 drivers/spmi/spmi-sandbox.c
 create mode 100644 test/dm/spmi.c

diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index d2addb4..ff37283 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -239,6 +239,26 @@
 		status = "disabled";
 	};
 
+	spmi: spmi at 0 {
+		compatible = "sandbox,spmi";
+		#address-cells = <0x1>;
+		#size-cells = <0x1>;
+		pm8916 at 0 {
+			compatible = "qcom,spmi-pmic";
+			reg = <0x0 0x1>;
+			#address-cells = <0x1>;
+			#size-cells = <0x1>;
+
+			spmi_gpios: gpios at c000 {
+				compatible = "qcom,pm8916-gpio";
+				reg = <0xc000 0x400>;
+				gpio-controller;
+				gpio-count = <4>;
+				#gpio-cells = <2>;
+				gpio-bank-name="spmi";
+			};
+		};
+	};
 };
 
 #include "cros-ec-keyboard.dtsi"
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 731fc25..0b4ce7b 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -30,6 +30,7 @@ CONFIG_ADC=y
 CONFIG_ADC_SANDBOX=y
 CONFIG_CLK=y
 CONFIG_SANDBOX_GPIO=y
+CONFIG_PM8916_GPIO=y
 CONFIG_SYS_I2C_SANDBOX=y
 CONFIG_CROS_EC_KEYB=y
 CONFIG_LED=y
@@ -58,6 +59,9 @@ CONFIG_PINCONF=y
 CONFIG_PINCTRL_SANDBOX=y
 CONFIG_DM_PMIC=y
 CONFIG_DM_PMIC_SANDBOX=y
+CONFIG_PMIC_PM8916=y
+CONFIG_DM_SPMI=y
+CONFIG_SPMI_SANDBOX=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_SANDBOX=y
 CONFIG_RAM=y
diff --git a/doc/device-tree-bindings/spmi/spmi-sandbox.txt b/doc/device-tree-bindings/spmi/spmi-sandbox.txt
new file mode 100644
index 0000000..f120b99
--- /dev/null
+++ b/doc/device-tree-bindings/spmi/spmi-sandbox.txt
@@ -0,0 +1,34 @@
+Sandbox SPMI emulated arbiter.
+
+This is bus driver for Sandbox. It includes part of emulated pm8916 pmic.
+
+Required properties:
+- compatible: "sandbox,spmi"
+- #address-cells: 0x1 - childs slave ID address
+- #size-cells: 0x1
+
+Optional properties (if not set by parent):
+Child nodes (as in example)
+
+Example:
+
+spmi: spmi at 0 {
+	compatible = "sandbox,spmi";
+	#address-cells = <0x1>;
+	#size-cells = <0x1>;
+	pm8916 at 0 {
+		compatible = "qcom,spmi-pmic";
+		reg = <0x0 0x1>;
+		#address-cells = <0x1>;
+		#size-cells = <0x1>;
+
+		spmi_gpios: gpios at c000 {
+			compatible = "qcom,pm8916-gpio";
+			reg = <0xc000 0x400>;
+			gpio-controller;
+			gpio-count = <4>;
+			#gpio-cells = <2>;
+			gpio-bank-name="spmi";
+		};
+	};
+};
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
index 440431a..e3e8216 100644
--- a/drivers/spmi/Kconfig
+++ b/drivers/spmi/Kconfig
@@ -7,4 +7,12 @@ config DM_SPMI
 	  Select this to enable to support SPMI bus.
 	  SPMI (System Power Management Interface) bus is used
 	  to connect PMIC devices on various SoCs.
+
+config SPMI_SANDBOX
+	boolean "Support for Sandbox SPMI bus"
+	depends on DM_SPMI
+	---help---
+	  Demo SPMI bus implementation. Emulates part of PM8916 as single
+          slave (0) on bus. It has 4 GPIO peripherals, pid 0xC0-0xC3.
+
 endmenu
diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
index 2015b1a..035d466 100644
--- a/drivers/spmi/Makefile
+++ b/drivers/spmi/Makefile
@@ -5,3 +5,4 @@
 #
 
 obj-$(CONFIG_DM_SPMI)  += spmi-uclass.o
+obj-$(CONFIG_SPMI_SANDBOX) += spmi-sandbox.o
diff --git a/drivers/spmi/spmi-sandbox.c b/drivers/spmi/spmi-sandbox.c
new file mode 100644
index 0000000..7e67a40
--- /dev/null
+++ b/drivers/spmi/spmi-sandbox.c
@@ -0,0 +1,157 @@
+/*
+ * Sample SPMI bus driver
+ *
+ * It emulates bus with single pm8916-like pmic that has only GPIO reigsters.
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <spmi/spmi.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define EMUL_GPIO_PID_START 0xC0
+#define EMUL_GPIO_PID_END   0xC3
+
+#define EMUL_GPIO_COUNT 4
+
+#define EMUL_GPIO_REG_END 0x46 /* Last valid register */
+
+#define EMUL_PERM_R 0x1
+#define EMUL_PERM_W 0x2
+#define EMUL_PERM_RW (EMUL_PERM_R | EMUL_PERM_W)
+
+struct sandbox_emul_fake_regs {
+	u8 value;
+	u8 access_mask;
+	u8 perms; /* Access permissions */
+};
+
+struct sandbox_emul_gpio {
+	struct sandbox_emul_fake_regs r[EMUL_GPIO_REG_END]; /* Fake registers */
+};
+
+struct sandbox_spmi_priv {
+	struct sandbox_emul_gpio gpios[EMUL_GPIO_COUNT];
+};
+
+/* Check if valid register was requested */
+static bool check_address_valid(int usid, int pid, int off)
+{
+	if (usid != 0)
+		return false;
+	if (pid < EMUL_GPIO_PID_START || pid > EMUL_GPIO_PID_END)
+		return false;
+	if (off > EMUL_GPIO_REG_END)
+		return false;
+	return true;
+}
+
+static int sandbox_spmi_write(struct udevice *dev, int usid, int pid, int off,
+			  uint8_t val)
+{
+	struct sandbox_spmi_priv *p = dev_get_priv(dev);
+	struct sandbox_emul_fake_regs *r;
+
+	if (!check_address_valid(usid, pid, off))
+		return -EIO;
+
+	r = p->gpios[pid & 0x3].r; /* Last 3 bits of pid are gpio # */
+
+	switch (off) {
+	case 0x40: /* Control */
+		val &= r[off].access_mask;
+		if (((val & 0x30) == 0x10) || ((val & 0x30) == 0x20)) {
+			/* out/inout - set status register */
+			r[0x8].value &= ~0x1;
+			r[0x8].value |= val & 0x1;
+		}
+		break;
+	default:
+		if (r[off].perms & EMUL_PERM_W)
+			r[off].value = val & r[off].access_mask;
+	}
+	return 0;
+}
+
+static int sandbox_spmi_read(struct udevice *dev, int usid, int pid, int off)
+{
+	struct sandbox_spmi_priv *p = dev_get_priv(dev);
+	struct sandbox_emul_fake_regs *r;
+
+	if (!check_address_valid(usid, pid, off))
+		return -EIO;
+
+	r = p->gpios[pid & 0x3].r; /* Last 3 bits of pid are gpio # */
+
+	if (r[0x46].value == 0) /* Block disabled */
+		return 0;
+
+	switch (off) {
+	case 0x8: /* Status */
+		if (r[0x46].value == 0) /* Block disabled */
+			return 0;
+		return r[off].value;
+	default:
+		if (r[off].perms & EMUL_PERM_R)
+			return r[off].value;
+		else
+			return 0;
+	}
+}
+
+static struct dm_spmi_ops sandbox_spmi_ops = {
+	.read = sandbox_spmi_read,
+	.write = sandbox_spmi_write,
+};
+
+static int sandbox_spmi_probe(struct udevice *dev)
+{
+	struct sandbox_spmi_priv *p = dev_get_priv(dev);
+	int i;
+
+	for (i = 0; i < EMUL_GPIO_COUNT; ++i) {
+		struct sandbox_emul_fake_regs *r = p->gpios[i].r;
+		r[4].perms = EMUL_PERM_R;
+		r[4].value = 0x10;
+		r[5].perms = EMUL_PERM_R;
+		r[5].value = 0x5;
+		r[8].access_mask = 0x81;
+		r[8].perms = EMUL_PERM_RW;
+		r[0x40].access_mask = 0x7F;
+		r[0x40].perms = EMUL_PERM_RW;
+		r[0x41].access_mask = 7;
+		r[0x41].perms = EMUL_PERM_RW;
+		r[0x42].access_mask = 7;
+		r[0x42].perms = EMUL_PERM_RW;
+		r[0x42].value = 0x4;
+		r[0x45].access_mask = 0x3F;
+		r[0x45].perms = EMUL_PERM_RW;
+		r[0x45].value = 0x1;
+		r[0x46].access_mask = 0x80;
+		r[0x46].perms = EMUL_PERM_RW;
+		r[0x46].value = 0x80;
+	}
+	return 0;
+}
+
+static const struct udevice_id sandbox_spmi_ids[] = {
+	{ .compatible = "sandbox,spmi" },
+	{ }
+};
+
+U_BOOT_DRIVER(msm_spmi) = {
+	.name = "sandbox_spmi",
+	.id = UCLASS_SPMI,
+	.of_match = sandbox_spmi_ids,
+	.ops = &sandbox_spmi_ops,
+	.probe = sandbox_spmi_probe,
+	.priv_auto_alloc_size = sizeof(struct sandbox_spmi_priv),
+};
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 681c6ae..178bd5e 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -35,4 +35,5 @@ obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_REGULATOR) += regulator.o
 obj-$(CONFIG_TIMER) += timer.o
 obj-$(CONFIG_ADC) += adc.o
+obj-$(CONFIG_DM_SPMI) += spmi.o
 endif
diff --git a/test/dm/spmi.c b/test/dm/spmi.c
new file mode 100644
index 0000000..81767f6
--- /dev/null
+++ b/test/dm/spmi.c
@@ -0,0 +1,115 @@
+/*
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <dm.h>
+#include <dm/device.h>
+#include <dm/root.h>
+#include <dm/test.h>
+#include <dm/util.h>
+#include <power/pmic.h>
+#include <spmi/spmi.h>
+#include <asm/gpio.h>
+#include <test/ut.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Test if bus childs got probed propperly*/
+static int dm_test_spmi_probe(struct unit_test_state *uts)
+{
+	const char *name = "spmi at 0";
+	struct udevice *bus, *dev;
+
+	ut_assertok(uclass_get_device(UCLASS_SPMI, 0, &bus));
+
+	/* Check bus name */
+	ut_asserteq_str(name, bus->name);
+
+	/* Check that it has some devices */
+	ut_asserteq(device_has_children(bus), true);
+
+	ut_assertok(device_find_first_child(bus, &dev));
+
+	/* There should be at least one child */
+	ut_assertnonnull(dev);
+
+	/* Check that only PMICs are connected to the bus */
+	while (dev) {
+		ut_asserteq(device_get_uclass_id(dev), UCLASS_PMIC);
+		device_find_next_child(&dev);
+	}
+
+	return 0;
+}
+DM_TEST(dm_test_spmi_probe, DM_TESTF_SCAN_FDT);
+
+/* Test if it's possible to read bus directly and indirectly */
+static int dm_test_spmi_access(struct unit_test_state *uts)
+{
+	const char *pmic_name = "pm8916 at 0";
+	struct udevice *bus, *pmic;
+
+	ut_assertok(uclass_get_device(UCLASS_SPMI, 0, &bus));
+
+	ut_assertok(device_get_child(bus, 0, &pmic));
+
+	/* Sanity check if it's proper PMIC */
+	ut_asserteq_str(pmic_name, pmic->name);
+
+	/* Read PMIC ID reg using SPMI bus - it assumes it has slaveID == 0*/
+	ut_asserteq(spmi_reg_read(bus, 0, 0xC0, 0x4), 0x10);
+	ut_asserteq(spmi_reg_read(bus, 0, 0xC0, 0x5), 0x5);
+
+	/* Read ID reg via pmic interface */
+	ut_asserteq(pmic_reg_read(pmic, 0xC004), 0x10);
+	ut_asserteq(pmic_reg_read(pmic, 0xC005), 0x5);
+
+	return 0;
+}
+DM_TEST(dm_test_spmi_access, DM_TESTF_SCAN_FDT);
+
+
+/* Test if it's possible to access GPIO that should be in pmic */
+static int dm_test_spmi_access_peripheral(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	unsigned int offset, gpio;
+	const char *name;
+	int offset_count;
+
+	/* Get second pin of PMIC GPIO */
+	ut_assertok(gpio_lookup_name("spmi1", &dev, &offset, &gpio));
+
+	/* Check if PMIC is parent */
+	ut_asserteq(device_get_uclass_id(dev->parent), UCLASS_PMIC);
+
+	/* This should be second gpio */
+	ut_asserteq(1, offset);
+
+	name = gpio_get_bank_info(dev, &offset_count);
+
+	/* Check bank name */
+	ut_asserteq_str("spmi", name);
+	/* Check pin count */
+	ut_asserteq(4, offset_count);
+
+	ut_assertok(gpio_request(gpio, "testing"));
+
+	/* Try to set/clear gpio */
+	ut_assertok(gpio_direction_output(gpio, 0));
+	ut_asserteq(gpio_get_value(gpio), 0);
+	ut_assertok(gpio_direction_output(gpio, 1));
+	ut_asserteq(gpio_get_value(gpio), 1);
+	ut_assertok(gpio_direction_input(gpio));
+	ut_asserteq(gpio_get_value(gpio), 1);
+
+	ut_assertok(gpio_free(gpio));
+
+	return 0;
+}
+DM_TEST(dm_test_spmi_access_peripheral, DM_TESTF_SCAN_FDT);
+
-- 
2.5.0

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

* [U-Boot] [PATCH v1 12/16] drivers: spmi: Add support for Qualcomm SPMI bus driver
  2016-01-06 18:21 [U-Boot] [PATCH v1 00/16] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (10 preceding siblings ...)
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 11/16] spmi: Add sandbox test driver Mateusz Kulikowski
@ 2016-01-06 18:21 ` Mateusz Kulikowski
  2016-01-11 16:57   ` Simon Glass
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 13/16] pmic: Add support for Qualcomm PM8916 PMIC Mateusz Kulikowski
                   ` (3 subsequent siblings)
  15 siblings, 1 reply; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-06 18:21 UTC (permalink / raw)
  To: u-boot

Support SPMI arbiter on Qualcomm Snapdragon devices.

Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
---

Changes in v1:
- add binding documentation and better Kconfig help
- Changed a bit mapping
- Change include order
- Use clrsetbits* where possible
- Add one more supported dts id
- Handle missing fields in dt properly

 doc/device-tree-bindings/spmi/spmi-msm.txt |  26 ++++
 drivers/spmi/Kconfig                       |   7 +-
 drivers/spmi/Makefile                      |   1 +
 drivers/spmi/spmi-msm.c                    | 188 +++++++++++++++++++++++++++++
 4 files changed, 221 insertions(+), 1 deletion(-)
 create mode 100644 doc/device-tree-bindings/spmi/spmi-msm.txt
 create mode 100644 drivers/spmi/spmi-msm.c

diff --git a/doc/device-tree-bindings/spmi/spmi-msm.txt b/doc/device-tree-bindings/spmi/spmi-msm.txt
new file mode 100644
index 0000000..ae47673
--- /dev/null
+++ b/doc/device-tree-bindings/spmi/spmi-msm.txt
@@ -0,0 +1,26 @@
+Qualcomm SPMI arbiter/bus driver
+
+This is bus driver for Qualcomm chips that use SPMI to communicate with PMICs.
+
+Required properties:
+- compatible: "qcom,spmi-pmic-arb"
+- reg: Register block adresses and sizes for various parts of device:
+   1) PMIC arbiter channel mapping base (PMIC_ARB_REG_CHNLn)
+   2) SPMI write command (master) registers (PMIC_ARB_CORE_SW_DEC_CHANNELS)
+   3) SPMI read command (observer) registers (PMIC_ARB_CORE_REGISTERS_OBS)
+
+Optional properties (if not set by parent):
+- #address-cells: 0x1 - childs slave ID address
+- #size-cells: 0x1
+
+All PMICs should be placed as a child nodes of bus arbiter.
+Automatic detection of childs is currently not supported.
+
+Example:
+
+spmi at 200f000 {
+	compatible = "qcom,spmi-pmic-arb";
+	reg = <0x200f800 0x200 0x2400000 0x400000 0x2c00000 0x400000>;
+	#address-cells = <0x1>;
+	#size-cells = <0x1>;
+};
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
index e3e8216..9632b14 100644
--- a/drivers/spmi/Kconfig
+++ b/drivers/spmi/Kconfig
@@ -8,11 +8,16 @@ config DM_SPMI
 	  SPMI (System Power Management Interface) bus is used
 	  to connect PMIC devices on various SoCs.
 
+config SPMI_MSM
+	boolean "Support Qualcomm SPMI bus"
+	depends on DM_SPMI
+	---help---
+	  Support SPMI bus implementation found on Qualcomm Snapdragon SoCs.
+
 config SPMI_SANDBOX
 	boolean "Support for Sandbox SPMI bus"
 	depends on DM_SPMI
 	---help---
 	  Demo SPMI bus implementation. Emulates part of PM8916 as single
           slave (0) on bus. It has 4 GPIO peripherals, pid 0xC0-0xC3.
-
 endmenu
diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
index 035d466..caad96f 100644
--- a/drivers/spmi/Makefile
+++ b/drivers/spmi/Makefile
@@ -5,4 +5,5 @@
 #
 
 obj-$(CONFIG_DM_SPMI)  += spmi-uclass.o
+obj-$(CONFIG_SPMI_MSM) += spmi-msm.o
 obj-$(CONFIG_SPMI_SANDBOX) += spmi-sandbox.o
diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c
new file mode 100644
index 0000000..c1e7a3d
--- /dev/null
+++ b/drivers/spmi/spmi-msm.c
@@ -0,0 +1,188 @@
+/*
+ * Qualcomm SPMI bus driver
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * Loosely based on Little Kernel driver
+ *
+ * SPDX-License-Identifier:	BSD-3-Clause
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <spmi/spmi.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define ARB_CHANNEL_OFFSET(n)		(0x4 * (n))
+#define SPMI_CH_OFFSET(chnl)		((chnl) * 0x8000)
+
+#define SPMI_REG_CMD0			0x0
+#define SPMI_REG_CONFIG			0x4
+#define SPMI_REG_STATUS			0x8
+#define SPMI_REG_WDATA			0x10
+#define SPMI_REG_RDATA			0x18
+
+#define SPMI_CMD_OPCODE_SHIFT		27
+#define SPMI_CMD_SLAVE_ID_SHIFT		20
+#define SPMI_CMD_ADDR_SHIFT		12
+#define SPMI_CMD_ADDR_OFFSET_SHIFT	4
+#define SPMI_CMD_BYTE_CNT_SHIFT		0
+
+#define SPMI_CMD_EXT_REG_WRITE_LONG	0x00
+#define SPMI_CMD_EXT_REG_READ_LONG	0x01
+
+#define SPMI_STATUS_DONE		0x1
+
+#define SPMI_MAX_CHANNELS	128
+#define SPMI_MAX_SLAVES		16
+#define SPMI_MAX_PERIPH		256
+
+struct msm_spmi_priv {
+	phys_addr_t arb_chnl; /* ARB channel mapping base */
+	phys_addr_t spmi_core; /* SPMI core */
+	phys_addr_t spmi_obs; /* SPMI observer */
+	/* SPMI channel map */
+	uint8_t channel_map[SPMI_MAX_SLAVES][SPMI_MAX_PERIPH];
+};
+
+static int msm_spmi_write(struct udevice *dev, int usid, int pid, int off,
+			  uint8_t val)
+{
+	struct msm_spmi_priv *p = dev_get_priv(dev);
+	unsigned channel;
+	uint32_t reg = 0;
+
+	if (usid >= SPMI_MAX_SLAVES)
+		return -EIO;
+	if (pid >= SPMI_MAX_PERIPH)
+		return -EIO;
+
+	channel = p->channel_map[usid][pid];
+
+	/* Disable IRQ mode for the current channel*/
+	writel(0x0, p->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_CONFIG);
+
+	/* Write single byte */
+	writel(val, p->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_WDATA);
+
+	/* Prepare write command */
+	reg |= SPMI_CMD_EXT_REG_WRITE_LONG << SPMI_CMD_OPCODE_SHIFT;
+	reg |= (usid << SPMI_CMD_SLAVE_ID_SHIFT);
+	reg |= (pid << SPMI_CMD_ADDR_SHIFT);
+	reg |= (off << SPMI_CMD_ADDR_OFFSET_SHIFT);
+	reg |= 1; /* byte count */
+
+	/* Send write command */
+	writel(reg, p->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_CMD0);
+
+	/* Wait till CMD DONE status */
+	reg = 0;
+	while (!reg) {
+		reg = readl(p->spmi_core + SPMI_CH_OFFSET(channel) +
+			    SPMI_REG_STATUS);
+	}
+
+	if (reg ^ SPMI_STATUS_DONE) {
+		printf("SPMI write failure.\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int msm_spmi_read(struct udevice *dev, int usid, int pid, int off)
+{
+	struct msm_spmi_priv *p = dev_get_priv(dev);
+	unsigned channel;
+	uint32_t reg = 0;
+
+	if (usid >= SPMI_MAX_SLAVES)
+		return -EIO;
+	if (pid >= SPMI_MAX_PERIPH)
+		return -EIO;
+
+	channel = p->channel_map[usid][pid];
+
+	/* Disable IRQ mode for the current channel*/
+	writel(0x0, p->spmi_obs + SPMI_CH_OFFSET(channel) + SPMI_REG_CONFIG);
+
+	/* Prepare read command */
+	reg |= SPMI_CMD_EXT_REG_READ_LONG << SPMI_CMD_OPCODE_SHIFT;
+	reg |= (usid << SPMI_CMD_SLAVE_ID_SHIFT);
+	reg |= (pid << SPMI_CMD_ADDR_SHIFT);
+	reg |= (off << SPMI_CMD_ADDR_OFFSET_SHIFT);
+	reg |= 1; /* byte count */
+
+	/* Request read */
+	writel(reg, p->spmi_obs + SPMI_CH_OFFSET(channel) + SPMI_REG_CMD0);
+
+	/* Wait till CMD DONE status */
+	reg = 0;
+	while (!reg) {
+		reg = readl(p->spmi_obs + SPMI_CH_OFFSET(channel) +
+			    SPMI_REG_STATUS);
+	}
+
+	if (reg ^ SPMI_STATUS_DONE) {
+		printf("SPMI read failure.\n");
+		return -EIO;
+	}
+
+	/* Read the data */
+	return readl(p->spmi_obs + SPMI_CH_OFFSET(channel) + SPMI_REG_RDATA) &
+			0xFF;
+}
+
+static struct dm_spmi_ops msm_spmi_ops = {
+	.read = msm_spmi_read,
+	.write = msm_spmi_write,
+};
+
+static int msm_spmi_probe(struct udevice *dev)
+{
+	struct udevice *parent = dev->parent;
+	struct msm_spmi_priv *priv = dev_get_priv(dev);
+	int i;
+
+	priv->arb_chnl = dev_get_addr(dev);
+	priv->spmi_core = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
+							   parent->of_offset,
+							   dev->of_offset,
+							   "reg", 1, NULL);
+	priv->spmi_obs = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
+							  parent->of_offset,
+							  dev->of_offset, "reg",
+							  2, NULL);
+	if (priv->arb_chnl == FDT_ADDR_T_NONE ||
+	    priv->spmi_core == FDT_ADDR_T_NONE ||
+	    priv->spmi_obs == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	/* Scan peripherals connected to each SPMI channel */
+	for (i = 0; i < SPMI_MAX_CHANNELS ; i++) {
+		uint32_t periph = readl(priv->arb_chnl + ARB_CHANNEL_OFFSET(i));
+		uint8_t slave_id = (periph & 0xf0000) >> 16;
+		uint8_t pid = (periph & 0xff00) >> 8;
+
+		priv->channel_map[slave_id][pid] = i;
+	}
+	return 0;
+}
+
+static const struct udevice_id msm_spmi_ids[] = {
+	{ .compatible = "qcom,spmi-pmic-arb" },
+	{ }
+};
+
+U_BOOT_DRIVER(msm_spmi) = {
+	.name = "msm_spmi",
+	.id = UCLASS_SPMI,
+	.of_match = msm_spmi_ids,
+	.ops = &msm_spmi_ops,
+	.probe = msm_spmi_probe,
+	.priv_auto_alloc_size = sizeof(struct msm_spmi_priv),
+};
-- 
2.5.0

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

* [U-Boot] [PATCH v1 13/16] pmic: Add support for Qualcomm PM8916 PMIC
  2016-01-06 18:21 [U-Boot] [PATCH v1 00/16] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (11 preceding siblings ...)
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 12/16] drivers: spmi: Add support for Qualcomm SPMI bus driver Mateusz Kulikowski
@ 2016-01-06 18:21 ` Mateusz Kulikowski
  2016-01-11 16:58   ` Simon Glass
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 14/16] gpio: Add support for Qualcomm PM8916 gpios Mateusz Kulikowski
                   ` (2 subsequent siblings)
  15 siblings, 1 reply; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-06 18:21 UTC (permalink / raw)
  To: u-boot

This PMIC is connected on SPMI bus so needs SPMI support enabled.

Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
---

Changes in v1:
- Added dt bindings
- Reoder includes
- Replaced extract_* macros with ordinary shift/mask
- Added error checking and whitespaces in probe

 doc/device-tree-bindings/pmic/pm8916.txt | 18 ++++++
 drivers/power/pmic/Kconfig               | 14 +++++
 drivers/power/pmic/Makefile              |  1 +
 drivers/power/pmic/pm8916.c              | 96 ++++++++++++++++++++++++++++++++
 4 files changed, 129 insertions(+)
 create mode 100644 doc/device-tree-bindings/pmic/pm8916.txt
 create mode 100644 drivers/power/pmic/pm8916.c

diff --git a/doc/device-tree-bindings/pmic/pm8916.txt b/doc/device-tree-bindings/pmic/pm8916.txt
new file mode 100644
index 0000000..15c598b
--- /dev/null
+++ b/doc/device-tree-bindings/pmic/pm8916.txt
@@ -0,0 +1,18 @@
+Qualcomm pm8916 PMIC
+
+This PMIC is connected using SPMI bus so should be child of SPMI bus controller.
+
+Required properties:
+- compatible: "qcom,spmi-pmic";
+- reg: SPMI Slave ID, size (ignored)
+- #address-cells: 0x1 (peripheral ID)
+- #size-cells: 0x1 (size of peripheral register space)
+
+Example:
+
+pm8916 at 0 {
+	compatible = "qcom,spmi-pmic";
+	reg = <0x0 0x1>;
+	#address-cells = <0x1>;
+	#size-cells = <0x1>;
+};
diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
index fb29843..eb1dde0 100644
--- a/drivers/power/pmic/Kconfig
+++ b/drivers/power/pmic/Kconfig
@@ -89,3 +89,17 @@ config PMIC_TPS65090
 	FETs and a battery charger. This driver provides register access
 	only, and you can enable the regulator/charger drivers separately if
 	required.
+
+config PMIC_PM8916
+	bool "Enable Driver Model for Qualcomm PM8916 PMIC"
+	depends on DM_PMIC
+	---help---
+	The PM8916 is a PMIC connected to one (or several) processors
+	with SPMI bus. It has 2 slaves with several peripherals:
+	- 18x LDO
+	- 4x GPIO
+	- Power and Reset buttons
+	- Watchdog
+	- RTC
+	- Vibrator drivers
+	- Others
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index 91e78f8..ac653c7 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
 obj-$(CONFIG_PMIC_ACT8846) += act8846.o
 obj-$(CONFIG_PMIC_TPS65090) += tps65090.o
 obj-$(CONFIG_PMIC_S5M8767) += s5m8767.o
+obj-$(CONFIG_PMIC_PM8916) += pm8916.o
 
 obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o
 obj-$(CONFIG_POWER_MAX77696) += pmic_max77696.o
diff --git a/drivers/power/pmic/pm8916.c b/drivers/power/pmic/pm8916.c
new file mode 100644
index 0000000..9acf5f5
--- /dev/null
+++ b/drivers/power/pmic/pm8916.c
@@ -0,0 +1,96 @@
+/*
+ * Qualcomm pm8916 pmic driver
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+#include <dm.h>
+#include <dm/root.h>
+#include <power/pmic.h>
+#include <spmi/spmi.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define PID_SHIFT 8
+#define PID_MASK (0xFF << PID_SHIFT)
+#define REG_MASK 0xFF
+
+struct pm8916_priv {
+	uint16_t usid; /* Slave ID on SPMI bus */
+};
+
+static int pm8916_reg_count(struct udevice *dev)
+{
+	return 0xFFFF;
+}
+
+static int pm8916_write(struct udevice *dev, uint reg, const uint8_t *buff,
+			int len)
+{
+	struct pm8916_priv *priv = dev_get_priv(dev);
+
+	if (len != 1)
+		return -EINVAL;
+
+	return spmi_reg_write(dev->parent, priv->usid,
+			      (reg & PID_MASK) >> PID_SHIFT, reg & REG_MASK,
+			      *buff);
+}
+
+static int pm8916_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+	struct pm8916_priv *priv = dev_get_priv(dev);
+	int val;
+
+	if (len != 1)
+		return -EINVAL;
+
+	val = spmi_reg_read(dev->parent, priv->usid,
+			    (reg & PID_MASK) >> PID_SHIFT, reg & REG_MASK);
+
+	if (val < 0)
+		return val;
+	*buff = val;
+	return 0;
+}
+
+static struct dm_pmic_ops pm8916_ops = {
+	.reg_count = pm8916_reg_count,
+	.read = pm8916_read,
+	.write = pm8916_write,
+};
+
+static const struct udevice_id pm8916_ids[] = {
+	{ .compatible = "qcom,spmi-pmic" },
+	{ }
+};
+
+static int pm8916_probe(struct udevice *dev)
+{
+	struct pm8916_priv *priv = dev_get_priv(dev);
+
+	priv->usid = dev_get_addr(dev);
+
+	if (priv->usid == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	return 0;
+}
+
+
+static int pm8916_bind(struct udevice *dev)
+{
+	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+}
+
+U_BOOT_DRIVER(pmic_pm8916) = {
+	.name = "pmic_pm8916",
+	.id = UCLASS_PMIC,
+	.of_match = pm8916_ids,
+	.bind = pm8916_bind,
+	.probe = pm8916_probe,
+	.ops = &pm8916_ops,
+	.priv_auto_alloc_size = sizeof(struct pm8916_priv),
+};
-- 
2.5.0

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

* [U-Boot] [PATCH v1 14/16] gpio: Add support for Qualcomm PM8916 gpios
  2016-01-06 18:21 [U-Boot] [PATCH v1 00/16] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (12 preceding siblings ...)
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 13/16] pmic: Add support for Qualcomm PM8916 PMIC Mateusz Kulikowski
@ 2016-01-06 18:21 ` Mateusz Kulikowski
  2016-01-11 16:58   ` Simon Glass
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 15/16] arm: Add support for Qualcomm Snapdragon family Mateusz Kulikowski
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 16/16] board: Add Qualcomm Dragonboard 410C support Mateusz Kulikowski
  15 siblings, 1 reply; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-06 18:21 UTC (permalink / raw)
  To: u-boot

This driver supports GPIOs present on PM8916 PMIC.
There are 2 device drivers inside:
- GPIO driver (4 "generic" GPIOs)
- Keypad driver that presents itself as GPIO with 2 inputs (power and reset)

Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
---

Changes in v1:
- Add binding doc
- Fixed inlcude ordering
- Merged direction_input and direction_output functions
- gpio_get: use switch instead of stacked if
- use pmic_clrsetbits
- add possibility to change prwkey bank name
- Handle invalid bindings
- Sanity HW check (i.e. check type/subtype registers)

 doc/device-tree-bindings/gpio/pm8916_gpio.txt |  48 ++++
 drivers/gpio/Kconfig                          |  10 +
 drivers/gpio/Makefile                         |   1 +
 drivers/gpio/pm8916_gpio.c                    | 302 ++++++++++++++++++++++++++
 4 files changed, 361 insertions(+)
 create mode 100644 doc/device-tree-bindings/gpio/pm8916_gpio.txt
 create mode 100644 drivers/gpio/pm8916_gpio.c

diff --git a/doc/device-tree-bindings/gpio/pm8916_gpio.txt b/doc/device-tree-bindings/gpio/pm8916_gpio.txt
new file mode 100644
index 0000000..58185b8
--- /dev/null
+++ b/doc/device-tree-bindings/gpio/pm8916_gpio.txt
@@ -0,0 +1,48 @@
+Driver for part of pm8916 PMIC - gpio and power/reset keys
+
+This device should be child of SPMI pmic.
+
+1) GPIO driver
+
+Required properties:
+- compatible: "qcom,pm8916-gpio"
+- reg: peripheral ID, size of register block
+- gpio-controller
+- gpio-count: number of GPIOs
+- #gpio-cells: 2
+
+Optional properties:
+- gpio-bank-name: name of bank (as default "pm8916" is used)
+
+Example:
+
+pmic_gpios: gpios at c000 {
+	compatible = "qcom,pm8916-gpio";
+	reg = <0xc000 0x400>;
+	gpio-controller;
+	gpio-count = <4>;
+	#gpio-cells = <2>;
+	gpio-bank-name="pmic";
+};
+
+
+2) Power/Reset key driver
+
+Required properties:
+- compatible: "qcom,pm8916-pwrkey"
+- reg: peripheral ID, size of register block
+- gpio-controller
+- #gpio-cells: 2
+
+Optional properties:
+- gpio-bank-name: name of bank (as default "pm8916_key" is used)
+
+
+Example:
+
+pmic_pon: pon at 800 {
+	compatible = "qcom,pm8916-pwrkey";
+	reg = <0x800 0x96>;
+	#gpio-cells = <2>;
+	gpio-controller;
+};
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 3d112b9..a81ad1d 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -60,6 +60,16 @@ config MSM_GPIO
 	  - APQ8016
 	  - MSM8916
 
+config PM8916_GPIO
+	bool "Qualcomm PM8916 PMIC GPIO/keypad driver"
+	depends on DM_GPIO && PMIC_PM8916
+	help
+	  Support for GPIO pins and power/reset buttons found on
+	  Qualcomm PM8916 PMIC.
+	  Default name for GPIO bank is "pm8916".
+	  Power and reset buttons are placed in "pm8916_key" bank and
+          have gpio numbers 0 and 1 respectively.
+
 config ROCKCHIP_GPIO
 	bool "Rockchip GPIO driver"
 	depends on DM_GPIO
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 9520b1e..aaa9f8d 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -47,3 +47,4 @@ obj-$(CONFIG_ZYNQ_GPIO)		+= zynq_gpio.o
 obj-$(CONFIG_VYBRID_GPIO)	+= vybrid_gpio.o
 obj-$(CONFIG_HIKEY_GPIO)	+= hi6220_gpio.o
 obj-$(CONFIG_MSM_GPIO)		+= msm_gpio.o
+obj-$(CONFIG_PM8916_GPIO)	+= pm8916_gpio.o
diff --git a/drivers/gpio/pm8916_gpio.c b/drivers/gpio/pm8916_gpio.c
new file mode 100644
index 0000000..1abab7f
--- /dev/null
+++ b/drivers/gpio/pm8916_gpio.c
@@ -0,0 +1,302 @@
+/*
+ * Qualcomm pm8916 pmic gpio driver - part of Qualcomm PM8916 PMIC
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <power/pmic.h>
+#include <spmi/spmi.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <linux/bitops.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Register offset for each gpio */
+#define REG_OFFSET(x)          ((x) * 0x100)
+
+/* Register maps */
+
+/* Type and subtype are shared for all pm8916 peripherals */
+#define REG_TYPE               0x4
+#define REG_SUBTYPE            0x5
+
+#define REG_STATUS             0x08
+#define REG_STATUS_VAL_MASK    0x1
+
+/* MODE_CTL */
+#define REG_CTL           0x40
+#define REG_CTL_MODE_MASK       0x70
+#define REG_CTL_MODE_INPUT      0x00
+#define REG_CTL_MODE_INOUT      0x20
+#define REG_CTL_MODE_OUTPUT     0x10
+#define REG_CTL_OUTPUT_MASK     0x0F
+
+#define REG_DIG_VIN_CTL        0x41
+#define REG_DIG_VIN_VIN0       0
+
+#define REG_DIG_PULL_CTL       0x42
+#define REG_DIG_PULL_NO_PU     0x5
+
+#define REG_DIG_OUT_CTL        0x45
+#define REG_DIG_OUT_CTL_CMOS   (0x0 << 4)
+#define REG_DIG_OUT_CTL_DRIVE_L 0x1
+
+#define REG_EN_CTL             0x46
+#define REG_EN_CTL_ENABLE      (1 << 7)
+
+struct pm8916_gpio_bank {
+	uint16_t pid; /* Peripheral ID on SPMI bus */
+};
+
+static int pm8916_gpio_set_direction(struct udevice *dev, unsigned offset,
+				     bool input, int value)
+{
+	struct pm8916_gpio_bank *priv = dev_get_priv(dev);
+	uint32_t gpio_base = priv->pid + REG_OFFSET(offset);
+	int ret;
+
+	/* Disable the GPIO */
+	ret = pmic_clrsetbits(dev->parent, gpio_base + REG_EN_CTL,
+			      REG_EN_CTL_ENABLE, 0);
+	if (ret < 0)
+		return ret;
+
+	/* Select the mode */
+	if (input)
+		ret = pmic_reg_write(dev->parent, gpio_base + REG_CTL,
+				     REG_CTL_MODE_INPUT);
+	else
+		ret = pmic_reg_write(dev->parent, gpio_base + REG_CTL,
+				     REG_CTL_MODE_INOUT | (value ? 1 : 0));
+	if (ret < 0)
+		return ret;
+
+	/* Set the right pull (no pull) */
+	ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_PULL_CTL,
+			     REG_DIG_PULL_NO_PU);
+	if (ret < 0)
+		return ret;
+
+	/* Configure output pin drivers if needed */
+	if (!input) {
+		/* Select the VIN - VIN0, pin is input so it doesn't matter */
+		ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_VIN_CTL,
+				     REG_DIG_VIN_VIN0);
+		if (ret < 0)
+			return ret;
+
+		/* Set the right dig out control */
+		ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_OUT_CTL,
+				     REG_DIG_OUT_CTL_CMOS |
+				     REG_DIG_OUT_CTL_DRIVE_L);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Enable the GPIO */
+	return pmic_clrsetbits(dev->parent, gpio_base + REG_EN_CTL, 0,
+			       REG_EN_CTL_ENABLE);
+}
+
+static int pm8916_gpio_direction_input(struct udevice *dev, unsigned offset)
+{
+	return pm8916_gpio_set_direction(dev, offset, true, 0);
+}
+
+static int pm8916_gpio_direction_output(struct udevice *dev, unsigned offset,
+					int value)
+{
+	return pm8916_gpio_set_direction(dev, offset, false, value);
+}
+
+static int pm8916_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+	struct pm8916_gpio_bank *priv = dev_get_priv(dev);
+	uint32_t gpio_base = priv->pid + REG_OFFSET(offset);
+	int reg;
+
+	/* Set the output value of the gpio */
+	reg = pmic_reg_read(dev->parent, gpio_base + REG_CTL);
+	if (reg < 0)
+		return reg;
+
+	switch (reg & REG_CTL_MODE_MASK) {
+	case REG_CTL_MODE_INPUT:
+		return GPIOF_INPUT;
+	case REG_CTL_MODE_INOUT: /* Fallthrough */
+	case REG_CTL_MODE_OUTPUT:
+		return GPIOF_OUTPUT;
+	default:
+		return GPIOF_UNKNOWN;
+	}
+}
+
+static int pm8916_gpio_get_value(struct udevice *dev, unsigned offset)
+{
+	struct pm8916_gpio_bank *priv = dev_get_priv(dev);
+	uint32_t gpio_base = priv->pid + REG_OFFSET(offset);
+	int reg;
+
+	reg = pmic_reg_read(dev->parent, gpio_base + REG_STATUS);
+	if (reg < 0)
+		return reg;
+
+	return !!(reg & REG_STATUS_VAL_MASK);
+}
+
+static int pm8916_gpio_set_value(struct udevice *dev, unsigned offset,
+				 int value)
+{
+	struct pm8916_gpio_bank *priv = dev_get_priv(dev);
+	uint32_t gpio_base = priv->pid + REG_OFFSET(offset);
+
+	/* Set the output value of the gpio */
+	return pmic_clrsetbits(dev->parent, gpio_base + REG_CTL,
+			       REG_CTL_OUTPUT_MASK, !!value);
+}
+
+static const struct dm_gpio_ops pm8916_gpio_ops = {
+	.direction_input	= pm8916_gpio_direction_input,
+	.direction_output	= pm8916_gpio_direction_output,
+	.get_value		= pm8916_gpio_get_value,
+	.set_value		= pm8916_gpio_set_value,
+	.get_function		= pm8916_gpio_get_function,
+};
+
+static int pm8916_gpio_probe(struct udevice *dev)
+{
+	struct pm8916_gpio_bank *priv = dev_get_priv(dev);
+	int reg;
+
+	priv->pid = dev_get_addr(dev);
+	if (priv->pid == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	/* Do a sanity check */
+	reg = pmic_reg_read(dev->parent, priv->pid + REG_TYPE);
+	if (reg != 0x10)
+		return -ENODEV;
+
+	reg = pmic_reg_read(dev->parent, priv->pid + REG_SUBTYPE);
+	if (reg != 0x5)
+		return -ENODEV;
+
+	return 0;
+}
+
+static int pm8916_gpio_ofdata_to_platdata(struct udevice *dev)
+{
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	uc_priv->gpio_count = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+					     "gpio-count", 0);
+	uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev->of_offset,
+					 "gpio-bank-name", NULL);
+	if (uc_priv->bank_name == NULL)
+		uc_priv->bank_name = "pm8916";
+
+	return 0;
+}
+
+static const struct udevice_id pm8916_gpio_ids[] = {
+	{ .compatible = "qcom,pm8916-gpio" },
+	{ }
+};
+
+U_BOOT_DRIVER(gpio_pm8916) = {
+	.name	= "gpio_pm8916",
+	.id	= UCLASS_GPIO,
+	.of_match = pm8916_gpio_ids,
+	.ofdata_to_platdata = pm8916_gpio_ofdata_to_platdata,
+	.probe	= pm8916_gpio_probe,
+	.ops	= &pm8916_gpio_ops,
+	.priv_auto_alloc_size = sizeof(struct pm8916_gpio_bank),
+};
+
+
+/* Add pmic buttons as GPIO as well - there is no generic way for now */
+#define PON_INT_RT_STS                        0x10
+#define KPDPWR_ON_INT_BIT                     0
+#define RESIN_ON_INT_BIT                      1
+
+static int pm8941_pwrkey_get_function(struct udevice *dev, unsigned offset)
+{
+	return GPIOF_INPUT;
+}
+
+static int pm8941_pwrkey_get_value(struct udevice *dev, unsigned offset)
+{
+	struct pm8916_gpio_bank *priv = dev_get_priv(dev);
+
+	int reg = pmic_reg_read(dev->parent, priv->pid + PON_INT_RT_STS);
+
+	if (reg < 0)
+		return 0;
+
+	switch (offset) {
+	case 0: /* Power button */
+		return (reg & BIT(KPDPWR_ON_INT_BIT)) != 0;
+		break;
+	case 1: /* Reset button */
+	default:
+		return (reg & BIT(RESIN_ON_INT_BIT)) != 0;
+		break;
+	}
+}
+
+static const struct dm_gpio_ops pm8941_pwrkey_ops = {
+	.get_value		= pm8941_pwrkey_get_value,
+	.get_function		= pm8941_pwrkey_get_function,
+};
+
+static int pm8941_pwrkey_probe(struct udevice *dev)
+{
+	struct pm8916_gpio_bank *priv = dev_get_priv(dev);
+	int reg;
+
+	priv->pid = dev_get_addr(dev);
+	if (priv->pid == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	/* Do a sanity check */
+	reg = pmic_reg_read(dev->parent, priv->pid + REG_TYPE);
+	if (reg != 0x1)
+		return -ENODEV;
+
+	reg = pmic_reg_read(dev->parent, priv->pid + REG_SUBTYPE);
+	if (reg != 0x1)
+		return -ENODEV;
+
+	return 0;
+}
+
+static int pm8941_pwrkey_ofdata_to_platdata(struct udevice *dev)
+{
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	uc_priv->gpio_count = 2;
+	if (uc_priv->bank_name == NULL)
+		uc_priv->bank_name = "pm8916_key";
+
+	return 0;
+}
+
+static const struct udevice_id pm8941_pwrkey_ids[] = {
+	{ .compatible = "qcom,pm8916-pwrkey" },
+	{ }
+};
+
+U_BOOT_DRIVER(pwrkey_pm8941) = {
+	.name	= "pwrkey_pm8916",
+	.id	= UCLASS_GPIO,
+	.of_match = pm8941_pwrkey_ids,
+	.ofdata_to_platdata = pm8941_pwrkey_ofdata_to_platdata,
+	.probe	= pm8941_pwrkey_probe,
+	.ops	= &pm8941_pwrkey_ops,
+	.priv_auto_alloc_size = sizeof(struct pm8916_gpio_bank),
+};
-- 
2.5.0

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

* [U-Boot] [PATCH v1 15/16] arm: Add support for Qualcomm Snapdragon family
  2016-01-06 18:21 [U-Boot] [PATCH v1 00/16] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (13 preceding siblings ...)
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 14/16] gpio: Add support for Qualcomm PM8916 gpios Mateusz Kulikowski
@ 2016-01-06 18:21 ` Mateusz Kulikowski
  2016-01-11 16:58   ` Simon Glass
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 16/16] board: Add Qualcomm Dragonboard 410C support Mateusz Kulikowski
  15 siblings, 1 reply; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-06 18:21 UTC (permalink / raw)
  To: u-boot

First supported chip is APQ8016 (that is compatible with MSM8916).
Drivers in SoC code:
- Reset controller (PSHOLD)
- Clock controller (very simple clock configuration for MMC and UART)

Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
---

Changes in v1:
- Fix include order
- Cleanup defines (added spaces for readibility)
- Base address is integer to avoid casting
- Use setbits_* family where possible
- Drop unneded comments, added newlines where needed
- Check return value of dev_get_addr
- Add binding for apq8016
- Cleaned up divider calculation
- Drop most of gpio.h (only empty file is needed)

 arch/arm/Kconfig                                   |  12 +
 arch/arm/Makefile                                  |   1 +
 arch/arm/mach-snapdragon/Kconfig                   |   6 +
 arch/arm/mach-snapdragon/Makefile                  |   8 +
 arch/arm/mach-snapdragon/clock-apq8016.c           | 262 +++++++++++++++++++++
 arch/arm/mach-snapdragon/include/mach/gpio.h       |   9 +
 .../mach-snapdragon/include/mach/sysmap-apq8016.h  |  14 ++
 arch/arm/mach-snapdragon/reset.c                   |  40 ++++
 8 files changed, 352 insertions(+)
 create mode 100644 arch/arm/mach-snapdragon/Kconfig
 create mode 100644 arch/arm/mach-snapdragon/Makefile
 create mode 100644 arch/arm/mach-snapdragon/clock-apq8016.c
 create mode 100644 arch/arm/mach-snapdragon/include/mach/gpio.h
 create mode 100644 arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h
 create mode 100644 arch/arm/mach-snapdragon/reset.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9bd6cf1..0b68cb6 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -493,6 +493,16 @@ config OMAP54XX
 	select CPU_V7
 	select SUPPORT_SPL
 
+config ARCH_SNAPDRAGON
+	bool "Qualcomm Snapdragon SoCs"
+	select ARM64
+	select DM
+	select DM_GPIO
+	select DM_SERIAL
+	select DM_SPMI
+	select OF_CONTROL
+	select OF_SEPARATE
+
 config RMOBILE
 	bool "Renesas ARM SoCs"
 	select CPU_V7
@@ -749,6 +759,8 @@ source "arch/arm/mach-rockchip/Kconfig"
 
 source "arch/arm/mach-s5pc1xx/Kconfig"
 
+source "arch/arm/mach-snapdragon/Kconfig"
+
 source "arch/arm/mach-socfpga/Kconfig"
 
 source "arch/arm/mach-tegra/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 18283d1..b977309 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -54,6 +54,7 @@ machine-$(CONFIG_ARMADA_XP)		+= mvebu
 # TODO: rename CONFIG_ORION5X -> CONFIG_ARCH_ORION5X
 machine-$(CONFIG_ORION5X)		+= orion5x
 machine-$(CONFIG_ARCH_S5PC1XX)		+= s5pc1xx
+machine-$(CONFIG_ARCH_SNAPDRAGON)	+= snapdragon
 machine-$(CONFIG_ARCH_SOCFPGA)		+= socfpga
 machine-$(CONFIG_ARCH_ROCKCHIP)		+= rockchip
 machine-$(CONFIG_TEGRA)			+= tegra
diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig
new file mode 100644
index 0000000..156e733
--- /dev/null
+++ b/arch/arm/mach-snapdragon/Kconfig
@@ -0,0 +1,6 @@
+if ARCH_SNAPDRAGON
+
+config SYS_SOC
+	default "snapdragon"
+
+endif
diff --git a/arch/arm/mach-snapdragon/Makefile b/arch/arm/mach-snapdragon/Makefile
new file mode 100644
index 0000000..8e84705
--- /dev/null
+++ b/arch/arm/mach-snapdragon/Makefile
@@ -0,0 +1,8 @@
+#
+# (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += clock-apq8016.o
+obj-y += reset.o
diff --git a/arch/arm/mach-snapdragon/clock-apq8016.c b/arch/arm/mach-snapdragon/clock-apq8016.c
new file mode 100644
index 0000000..360064e
--- /dev/null
+++ b/arch/arm/mach-snapdragon/clock-apq8016.c
@@ -0,0 +1,262 @@
+/*
+ * Clock drivers for Qualcomm APQ8016
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * Based on Little Kernel driver, simplified
+ *
+ * SPDX-License-Identifier:	BSD-3-Clause
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+
+/* GPLL0 clock control registers */
+#define GPLL0_STATUS        0x2101C
+#define GPLL0_STATUS_ACTIVE BIT(17)
+
+#define APCS_GPLL_ENA_VOTE  0x45000
+#define APCS_GPLL_ENA_VOTE_GPLL0 BIT(0)
+
+/* vote reg for blsp1 clock */
+#define APCS_CLOCK_BRANCH_ENA_VOTE  0x45004
+#define APCS_CLOCK_BRANCH_ENA_VOTE_BLSP1 BIT(10)
+
+/* SDC(n) clock control registers; n=1,2 */
+
+/* block control register */
+#define SDCC_BCR(n)                 ((n * 0x1000) + 0x41000)
+/* cmd */
+#define SDCC_CMD_RCGR(n)            ((n * 0x1000) + 0x41004)
+/* cfg */
+#define SDCC_CFG_RCGR(n)            ((n * 0x1000) + 0x41008)
+/* m */
+#define SDCC_M(n)                   ((n * 0x1000) + 0x4100C)
+/* n */
+#define SDCC_N(n)                   ((n * 0x1000) + 0x41010)
+/* d */
+#define SDCC_D(n)                   ((n * 0x1000) + 0x41014)
+/* branch control */
+#define SDCC_APPS_CBCR(n)           ((n * 0x1000) + 0x41018)
+#define SDCC_AHB_CBCR(n)            ((n * 0x1000) + 0x4101C)
+
+/* BLSP1 AHB clock (root clock for BLSP) */
+#define BLSP1_AHB_CBCR              0x1008
+
+/* Uart clock control registers */
+#define BLSP1_UART2_BCR             0x3028
+#define BLSP1_UART2_APPS_CBCR       0x302C
+#define BLSP1_UART2_APPS_CMD_RCGR   0x3034
+#define BLSP1_UART2_APPS_CFG_RCGR   0x3038
+#define BLSP1_UART2_APPS_M          0x303C
+#define BLSP1_UART2_APPS_N          0x3040
+#define BLSP1_UART2_APPS_D          0x3044
+
+/* CBCR register fields */
+#define CBCR_BRANCH_ENABLE_BIT  BIT(0)
+#define CBCR_BRANCH_OFF_BIT     BIT(31)
+
+struct msm_clk_priv {
+	phys_addr_t base;
+};
+
+/* Enable clock controlled by CBC soft macro */
+static void clk_enable_cbc(phys_addr_t cbcr)
+{
+	setbits_le32(cbcr, CBCR_BRANCH_ENABLE_BIT);
+
+	while (readl(cbcr) & CBCR_BRANCH_OFF_BIT)
+		;
+}
+
+/* clock has 800MHz */
+static void clk_enable_gpll0(phys_addr_t base)
+{
+	if (readl(base + GPLL0_STATUS) & GPLL0_STATUS_ACTIVE)
+		return; /* clock already enabled */
+
+	setbits_le32(base + APCS_GPLL_ENA_VOTE, APCS_GPLL_ENA_VOTE_GPLL0);
+
+	while ((readl(base + GPLL0_STATUS) & GPLL0_STATUS_ACTIVE) == 0)
+		;
+}
+
+#define APPS_CMD_RGCR_UPDATE BIT(0)
+
+/* Update clock command via CMD_RGCR */
+static void clk_bcr_update(phys_addr_t apps_cmd_rgcr)
+{
+	setbits_le32(apps_cmd_rgcr, APPS_CMD_RGCR_UPDATE);
+
+	/* Wait for frequency to be updated. */
+	while (readl(apps_cmd_rgcr) & APPS_CMD_RGCR_UPDATE)
+		;
+}
+
+struct bcr_regs {
+	uintptr_t cfg_rcgr;
+	uintptr_t cmd_rcgr;
+	uintptr_t M;
+	uintptr_t N;
+	uintptr_t D;
+};
+
+/* RCGR_CFG register fields */
+#define CFG_MODE_DUAL_EDGE (0x2 << 12) /* Counter mode */
+
+/* sources */
+#define CFG_CLK_SRC_CXO   (0 << 8)
+#define CFG_CLK_SRC_GPLL0 (1 << 8)
+#define CFG_CLK_SRC_MASK  (7 << 8)
+
+/* Mask for supported fields */
+#define CFG_MASK 0x3FFF
+
+#define CFG_DIVIDER_MASK 0x1F
+
+/* root set rate for clocks with half integer and MND divider */
+static void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs,
+				 int div, int m, int n, int source)
+{
+	uint32_t cfg;
+	/* This register houses the M value for MND divider. */
+	uint32_t m_val = m;
+	/* This register houses the NOT(N-M) value for MND divider. */
+	uint32_t n_val = ~((n)-(m)) * !!(n);
+	/* This register houses the NOT 2D value for MND divider. */
+	uint32_t d_val = ~(n);
+
+	/* Program MND values */
+	writel(m_val, base + regs->M);
+	writel(n_val, base + regs->N);
+	writel(d_val, base + regs->D);
+
+	/* setup src select and divider */
+	cfg  = readl(base + regs->cfg_rcgr);
+	cfg &= ~CFG_MASK;
+	cfg |= source & CFG_CLK_SRC_MASK; /* Select clock source */
+
+	/* Set the divider; HW permits fraction dividers (+0.5), but
+	   for simplicity, we will support integers only */
+	if (div)
+		cfg |= (2 * div - 1) & CFG_DIVIDER_MASK;
+
+	if (n_val)
+		cfg |= CFG_MODE_DUAL_EDGE;
+
+	writel(cfg, base + regs->cfg_rcgr); /* Write new clock configuration */
+
+	/* Inform h/w to start using the new config. */
+	clk_bcr_update(base + regs->cmd_rcgr);
+}
+
+static const struct bcr_regs sdc_regs[] = {
+	{
+	.cfg_rcgr = SDCC_CFG_RCGR(1),
+	.cmd_rcgr = SDCC_CMD_RCGR(1),
+	.M = SDCC_M(1),
+	.N = SDCC_N(1),
+	.D = SDCC_D(1),
+	},
+	{
+	.cfg_rcgr = SDCC_CFG_RCGR(2),
+	.cmd_rcgr = SDCC_CMD_RCGR(2),
+	.M = SDCC_M(2),
+	.N = SDCC_N(2),
+	.D = SDCC_D(2),
+	}
+};
+
+/* Init clock for SDHCI controller */
+static int clk_init_sdc(struct msm_clk_priv *p, int slot, uint rate)
+{
+	int div = 8; /* 100MHz default */
+
+	if (rate == 200000000)
+		div = 4;
+
+	clk_enable_cbc(p->base + SDCC_AHB_CBCR(slot));
+	/* 800Mhz/div, gpll0 */
+	clk_rcg_set_rate_mnd(p->base, &sdc_regs[slot], div, 0, 0,
+			     CFG_CLK_SRC_GPLL0);
+	clk_enable_gpll0(p->base);
+	clk_enable_cbc(p->base + SDCC_APPS_CBCR(slot));
+
+	return rate;
+}
+
+static const struct bcr_regs uart2_regs = {
+	.cfg_rcgr = BLSP1_UART2_APPS_CFG_RCGR,
+	.cmd_rcgr = BLSP1_UART2_APPS_CMD_RCGR,
+	.M = BLSP1_UART2_APPS_M,
+	.N = BLSP1_UART2_APPS_N,
+	.D = BLSP1_UART2_APPS_D,
+};
+
+/* Init UART clock, 115200 */
+static int clk_init_uart(struct msm_clk_priv *p)
+{
+	/* Enable iface clk */
+	clk_enable_cbc(p->base + BLSP1_AHB_CBCR);
+	/* 7372800 uart block clock @ GPLL0 */
+	clk_rcg_set_rate_mnd(p->base, &uart2_regs, 1, 144, 15625,
+			     CFG_CLK_SRC_GPLL0);
+	clk_enable_gpll0(p->base);
+	/* Enable core clk */
+	clk_enable_cbc(p->base + BLSP1_UART2_APPS_CBCR);
+
+	return 0;
+}
+
+ulong msm_set_periph_rate(struct udevice *dev, int periph, ulong rate)
+{
+	struct msm_clk_priv *priv = dev_get_priv(dev);
+
+	switch (periph) {
+	case 0: /* SDC1 */
+		return clk_init_sdc(priv, 0, rate);
+		break;
+	case 1: /* SDC2 */
+		return clk_init_sdc(priv, 1, rate);
+		break;
+	case 4: /* UART2 */
+		return clk_init_uart(priv);
+		break;
+	default:
+		return 0;
+	}
+}
+
+static int msm_clk_probe(struct udevice *dev)
+{
+	struct msm_clk_priv *priv = dev_get_priv(dev);
+
+	priv->base = dev_get_addr(dev);
+	if (priv->base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	return 0;
+}
+
+static struct clk_ops msm_clk_ops = {
+	.set_periph_rate = msm_set_periph_rate,
+};
+
+static const struct udevice_id msm_clk_ids[] = {
+	{ .compatible = "qcom,gcc-msm8916" },
+	{ .compatible = "qcom,gcc-apq8016" },
+	{ }
+};
+
+U_BOOT_DRIVER(clk_msm) = {
+	.name		= "clk_msm",
+	.id		= UCLASS_CLK,
+	.of_match	= msm_clk_ids,
+	.ops		= &msm_clk_ops,
+	.priv_auto_alloc_size = sizeof(struct msm_clk_priv),
+	.probe		= msm_clk_probe,
+};
diff --git a/arch/arm/mach-snapdragon/include/mach/gpio.h b/arch/arm/mach-snapdragon/include/mach/gpio.h
new file mode 100644
index 0000000..ff949b2
--- /dev/null
+++ b/arch/arm/mach-snapdragon/include/mach/gpio.h
@@ -0,0 +1,9 @@
+/*
+ * Empty gpio.h
+ *
+ * This file must stay as arch/arm/include/asm/gpio.h requires it.
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
diff --git a/arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h b/arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h
new file mode 100644
index 0000000..cdbfad0
--- /dev/null
+++ b/arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h
@@ -0,0 +1,14 @@
+/*
+ * Qualcomm APQ8916 sysmap
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#ifndef _MACH_SYSMAP_APQ8016_H
+#define _MACH_SYSMAP_APQ8016_H
+
+#define GICD_BASE 0x0b000000
+#define GICC_BASE 0x0a20c000
+
+#endif
diff --git a/arch/arm/mach-snapdragon/reset.c b/arch/arm/mach-snapdragon/reset.c
new file mode 100644
index 0000000..ade3237
--- /dev/null
+++ b/arch/arm/mach-snapdragon/reset.c
@@ -0,0 +1,40 @@
+/*
+ * Qualcomm APQ8016 reset controller driver
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <reset.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int msm_reset_request(struct udevice *dev, enum reset_t type)
+{
+	phys_addr_t addr = dev_get_addr(dev);
+	if (!addr)
+		return -EINVAL;
+	writel(0, addr);
+	return -EINPROGRESS;
+}
+
+static struct reset_ops msm_reset_ops = {
+	.request	= msm_reset_request,
+};
+
+static const struct udevice_id msm_reset_ids[] = {
+	{ .compatible = "qcom,pshold" },
+	{ }
+};
+
+U_BOOT_DRIVER(reset_sandbox) = {
+	.name		= "msm_reset",
+	.id		= UCLASS_RESET,
+	.of_match	= msm_reset_ids,
+	.ops		= &msm_reset_ops,
+};
-- 
2.5.0

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

* [U-Boot] [PATCH v1 16/16] board: Add Qualcomm Dragonboard 410C support
  2016-01-06 18:21 [U-Boot] [PATCH v1 00/16] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (14 preceding siblings ...)
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 15/16] arm: Add support for Qualcomm Snapdragon family Mateusz Kulikowski
@ 2016-01-06 18:21 ` Mateusz Kulikowski
  2016-01-07 10:23   ` Sjoerd Simons
                     ` (2 more replies)
  15 siblings, 3 replies; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-06 18:21 UTC (permalink / raw)
  To: u-boot

This commit add support for 96Boards Dragonboard410C.

It is board based on APQ8016 Qualcomm SoC, complying with 
96boards specification. 

Features (present out of the box):
- 4x Cortex A53 (ARMv8)
- 2x USB Host port
- 1x USB Device port
- 4x LEDs
- 1x HDMI connector
- 1x uSD connector
- 3x buttons (Power, Vol+, Vol-/Reset)
- WIFI, Bluetooth with integrated antenna
- 8GiB eMMC

U-Boot boots chained with fastboot in 64-bit mode.
For detailed build instructions see readme.txt in board directory.

Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
---

Changes in v1:
- Add better help for dragonboard
- Move static structures to board_prepare_usb
- Add DM_SPMI to defconfig

 arch/arm/dts/Makefile                            |   2 +
 arch/arm/dts/dragonboard410c.dts                 | 154 +++++++++++++++++++
 arch/arm/mach-snapdragon/Kconfig                 |  20 +++
 board/qualcomm/dragonboard410c/Kconfig           |  15 ++
 board/qualcomm/dragonboard410c/Makefile          |   8 +
 board/qualcomm/dragonboard410c/dragonboard410c.c | 111 ++++++++++++++
 board/qualcomm/dragonboard410c/head.S            |  20 +++
 board/qualcomm/dragonboard410c/readme.txt        |  40 +++++
 board/qualcomm/dragonboard410c/u-boot.lds        |  90 +++++++++++
 configs/dragonboard410c_defconfig                |  30 ++++
 include/configs/dragonboard410c.h                | 182 +++++++++++++++++++++++
 11 files changed, 672 insertions(+)
 create mode 100644 arch/arm/dts/dragonboard410c.dts
 create mode 100644 board/qualcomm/dragonboard410c/Kconfig
 create mode 100644 board/qualcomm/dragonboard410c/Makefile
 create mode 100644 board/qualcomm/dragonboard410c/dragonboard410c.c
 create mode 100644 board/qualcomm/dragonboard410c/head.S
 create mode 100644 board/qualcomm/dragonboard410c/readme.txt
 create mode 100644 board/qualcomm/dragonboard410c/u-boot.lds
 create mode 100644 configs/dragonboard410c_defconfig
 create mode 100644 include/configs/dragonboard410c.h

diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 0bcd316..47aecf5 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -95,6 +95,8 @@ dtb-$(CONFIG_FSL_LSCH3) += fsl-ls2080a-qds.dtb \
 dtb-$(CONFIG_FSL_LSCH2) += fsl-ls1043a-qds.dtb \
 	fsl-ls1043a-rdb.dtb
 
+dtb-$(CONFIG_ARCH_SNAPDRAGON) += dragonboard410c.dtb
+
 dtb-$(CONFIG_MACH_SUN4I) += \
 	sun4i-a10-a1000.dtb \
 	sun4i-a10-ba10-tvbox.dtb \
diff --git a/arch/arm/dts/dragonboard410c.dts b/arch/arm/dts/dragonboard410c.dts
new file mode 100644
index 0000000..1de5d23
--- /dev/null
+++ b/arch/arm/dts/dragonboard410c.dts
@@ -0,0 +1,154 @@
+/dts-v1/;
+
+#include "skeleton64.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. Dragonboard 410c";
+	compatible = "qcom,dragonboard", "qcom,apq8016-sbc";
+	qcom,msm-id = <0xce 0x0 0xf8 0x0 0xf9 0x0 0xfa 0x0 0xf7 0x0>;
+	qcom,board-id = <0x10018 0x0>;
+	#address-cells = <0x2>;
+	#size-cells = <0x2>;
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x80000000 0 0x3da00000>;
+	};
+
+	chosen {
+		stdout-path = "/soc/serial at 78b0000";
+	};
+
+
+	soc {
+		#address-cells = <0x1>;
+		#size-cells = <0x1>;
+		ranges = <0x0 0x0 0x0 0xffffffff>;
+		compatible = "simple-bus";
+
+		clkc: qcom,gcc at 1800000 {
+			compatible = "qcom,gcc-apq8016";
+			reg = <0x1800000 0x80000>;
+			#address-cells = <0x1>;
+			#size-cells = <0x0>;
+		};
+
+		serial at 78b0000 {
+			compatible = "qcom,msm-uartdm-v1.4";
+			reg = <0x78b0000 0x200>;
+			u-boot,dm-pre-reloc;
+			clock = <&clkc 4>;
+		};
+
+		restart at 4ab000 {
+			compatible = "qcom,pshold";
+			reg = <0x4ab000 0x4>;
+		};
+
+		soc_gpios: pinctrl at 1000000 {
+			compatible = "qcom,apq8016-pinctrl";
+			reg = <0x1000000 0x300000>;
+			gpio-controller;
+			gpio-count = <122>;
+			gpio-bank-name="soc";
+			#gpio-cells = <1>;
+		};
+
+		ehci at 78d9000 {
+			compatible = "qcom,ehci-host";
+			reg = <0x78d9000 0x400>;
+		};
+
+		sdhci at 07824000 {
+			compatible = "qcom,sdhci-msm-v4";
+			reg = <0x7824900 0x11c 0x7824000 0x800>;
+			bus-width = <0x8>;
+			index = <0x0>;
+			non-removable;
+			clock = <&clkc 0>;
+			clock-frequency = <100000000>;
+		};
+
+		sdhci at 07864000 {
+			compatible = "qcom,sdhci-msm-v4";
+			reg = <0x7864900 0x11c 0x7864000 0x800>;
+			index = <0x1>;
+			bus-width = <0x4>;
+			clock = <&clkc 1>;
+			clock-frequency = <200000000>;
+		};
+
+		spmi at 200f000 {
+			compatible = "qcom,spmi-pmic-arb";
+			reg = <0x200f800 0x200 0x2400000 0x400000 0x2c00000 0x400000>;
+			#address-cells = <0x1>;
+			#size-cells = <0x1>;
+			pm8916 at 0 {
+				compatible = "qcom,spmi-pmic";
+				reg = <0x0 0x1>;
+				#address-cells = <0x1>;
+				#size-cells = <0x1>;
+
+				pmic_pon: pon at 800 {
+					compatible = "qcom,pm8916-pwrkey";
+					reg = <0x800 0x96>;
+					#gpio-cells = <2>;
+					gpio-controller;
+				};
+
+				pmic_gpios: gpios at c000 {
+					compatible = "qcom,pm8916-gpio";
+					reg = <0xc000 0x400>;
+					gpio-controller;
+					gpio-count = <4>;
+					#gpio-cells = <2>;
+					gpio-bank-name="pmic";
+				};
+			};
+
+			pm8916 at 1 {
+				compatible = "qcom,spmi-pmic";
+				reg = <0x1 0x1>;
+			};
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		user1 {
+			label = "green:user1";
+			gpios = <&soc_gpios 21 0>;
+		};
+
+		user2 {
+			label = "green:user2";
+			gpios = <&soc_gpios 120 0>;
+		};
+
+		user3 {
+			label = "green:user3";
+			gpios = <&pmic_gpios 0 0>;
+		};
+
+		user4 {
+			label = "green:user4";
+			gpios = <&pmic_gpios 1 0>;
+		};
+	};
+
+	usb_hub_reset_n_pm {
+		gpios = <&pmic_gpios 2 0>;
+	};
+
+	usb_sw_sel_pm {
+		gpios = <&pmic_gpios 3 0>;
+	};
+
+	key_vol_down {
+		gpios = <&pmic_pon 1 0>;
+	};
+
+	key_power {
+		gpios = <&pmic_pon 0 0>;
+	};
+};
diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig
index 156e733..dc7ba21 100644
--- a/arch/arm/mach-snapdragon/Kconfig
+++ b/arch/arm/mach-snapdragon/Kconfig
@@ -3,4 +3,24 @@ if ARCH_SNAPDRAGON
 config SYS_SOC
 	default "snapdragon"
 
+choice
+	prompt "Snapdragon board select"
+
+config TARGET_DRAGONBOARD410C
+	bool "96Boards Dragonboard 410C"
+	help
+	  Support for 96Boards Dragonboard 410C. This board complies with
+	  96Board Open Platform Specifications. Features:
+	  - Qualcomm Snapdragon 410C SoC - APQ8016 (4xCortex A53, Adreno 306)
+	  - 1GiB RAM
+	  - 8GiB eMMC, uSD slot
+	  - WiFi, Bluetooth and GPS module
+	  - 2x Host, 1x Device USB port
+	  - HDMI
+	  - 20-pin low speed and 40-pin high speed expanders, 4 LED, 3 buttons
+
+endchoice
+
+source "board/qualcomm/dragonboard410c/Kconfig"
+
 endif
diff --git a/board/qualcomm/dragonboard410c/Kconfig b/board/qualcomm/dragonboard410c/Kconfig
new file mode 100644
index 0000000..03bd7ae
--- /dev/null
+++ b/board/qualcomm/dragonboard410c/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_DRAGONBOARD410C
+
+config SYS_BOARD
+	default "dragonboard410c"
+
+config SYS_VENDOR
+	default "qualcomm"
+
+config SYS_SOC
+	default "apq8016"
+
+config SYS_CONFIG_NAME
+	default "dragonboard410c"
+
+endif
diff --git a/board/qualcomm/dragonboard410c/Makefile b/board/qualcomm/dragonboard410c/Makefile
new file mode 100644
index 0000000..cd67808
--- /dev/null
+++ b/board/qualcomm/dragonboard410c/Makefile
@@ -0,0 +1,8 @@
+#
+# (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	:= dragonboard410c.o
+extra-y += head.o
diff --git a/board/qualcomm/dragonboard410c/dragonboard410c.c b/board/qualcomm/dragonboard410c/dragonboard410c.c
new file mode 100644
index 0000000..5ca9659
--- /dev/null
+++ b/board/qualcomm/dragonboard410c/dragonboard410c.c
@@ -0,0 +1,111 @@
+/*
+ * Board init file for Dragonboard 410C
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <usb.h>
+#include <asm/gpio.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+	gd->ram_size = PHYS_SDRAM_1_SIZE;
+	return 0;
+}
+
+void dram_init_banksize(void)
+{
+	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+	gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
+}
+
+
+int board_prepare_usb(enum usb_init_type type)
+{
+	static struct gpio_desc hub_reset, usb_sel;
+	int ret = 0, node;
+
+	/* Try to request gpios needed to start usb host on dragonboard */
+	if (!dm_gpio_is_valid(&hub_reset)) {
+		node = fdt_subnode_offset(gd->fdt_blob, 0,
+					  "usb_hub_reset_n_pm");
+		if (node < 0) {
+			printf("Failed to find usb_hub_reset_n_pm dt node.\n");
+			return node;
+		}
+		ret = gpio_request_by_name_nodev(gd->fdt_blob, node, "gpios", 0,
+						 &hub_reset, 0);
+		if (ret < 0) {
+			printf("Failed to request usb_hub_reset_n_pm gpio.\n");
+			return ret;
+		}
+	}
+
+	if (!dm_gpio_is_valid(&usb_sel)) {
+		node = fdt_subnode_offset(gd->fdt_blob, 0, "usb_sw_sel_pm");
+		if (node < 0) {
+			printf("Failed to find usb_sw_sel_pm dt node.\n");
+			return 0;
+		}
+		ret = gpio_request_by_name_nodev(gd->fdt_blob, node, "gpios", 0,
+						 &usb_sel, 0);
+		if (ret < 0) {
+			printf("Failed to request usb_sw_sel_pm gpio.\n");
+			return ret;
+		}
+	}
+
+	if (type == USB_INIT_HOST) {
+		/* Start USB Hub */
+		dm_gpio_set_dir_flags(&hub_reset,
+				      GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+		mdelay(100);
+		/* Switch usb to host connectors */
+		dm_gpio_set_dir_flags(&usb_sel,
+				      GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+		mdelay(100);
+	} else { /* Device */
+		/* Disable hub */
+		dm_gpio_set_dir_flags(&hub_reset, GPIOD_IS_OUT);
+		/* Switch back to device connector */
+		dm_gpio_set_dir_flags(&usb_sel, GPIOD_IS_OUT);
+	}
+	return 0;
+}
+
+int board_init(void)
+{
+	return 0;
+}
+
+/* Check for vol- button - if pressed - stop autoboot */
+int misc_init_r(void)
+{
+	int node;
+	struct gpio_desc resin;
+
+	node = fdt_subnode_offset(gd->fdt_blob, 0, "key_vol_down");
+	if (node < 0) {
+		printf("Failed to find key_vol_down node. Check device tree\n");
+		return 0;
+	}
+
+	if (gpio_request_by_name_nodev(gd->fdt_blob, node, "gpios", 0, &resin,
+				       0)) {
+		printf("Failed to request key_vol_down button.\n");
+		return 0;
+	}
+
+	if (dm_gpio_get_value(&resin)) {
+		setenv("bootdelay", "-1");
+		printf("Power button pressed - dropping to console.\n");
+	}
+
+	return 0;
+}
diff --git a/board/qualcomm/dragonboard410c/head.S b/board/qualcomm/dragonboard410c/head.S
new file mode 100644
index 0000000..00d6d97
--- /dev/null
+++ b/board/qualcomm/dragonboard410c/head.S
@@ -0,0 +1,20 @@
+#include <config.h>
+
+.global _fastboot_header
+_fastboot_header:
+	b _start
+	add     x13, x18, #0x16
+	// Image load offset from start of RAM, little-endian
+	.quad   CONFIG_SYS_TEXT_BASE-PHYS_SDRAM_1
+	// Effective size of kernel image, little-endian
+	.quad   0 //0x60000
+	// Informative flags, little-endian
+	.quad   0
+	.quad   0                               // reserved
+	.quad   0                               // reserved
+	.quad   0                               // reserved
+	.byte   0x41                            // Magic number, "ARM\x64"
+	.byte   0x52
+	.byte   0x4d
+	.byte   0x64
+	.word   0                               // reserved
diff --git a/board/qualcomm/dragonboard410c/readme.txt b/board/qualcomm/dragonboard410c/readme.txt
new file mode 100644
index 0000000..0f575db
--- /dev/null
+++ b/board/qualcomm/dragonboard410c/readme.txt
@@ -0,0 +1,40 @@
+#
+# (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+Build & Run instructions:
+
+1) Install mkbootimg from git://codeaurora.org/quic/kernel/skales (15ece94f09 worked for me)
+2) Setup CROSS_COMPILE to aarch64 compiler
+3) make dragonboard410c_config
+4) make
+5) generate fake, empty ramdisk (can have 0 bytes)
+$ touch rd
+
+6) generate qualcomm device tree, use dtbTool to generate it
+$ dtbTool -o dt.img arch/arm/dts
+
+7) generate image with mkbootimg:
+$ mkbootimg --kernel=u-boot-dtb.bin --output=u-boot.img --dt=dt.img  --pagesize 2048 --base 0x80000000 --ramdisk=rd --cmdline=""
+
+Boot it with fastboot:
+fastboot boot u-boot.img
+or flash as kernel:
+fastboot flash boot u-boot.img
+fastboot reboot
+
+
+What is working:
+- UART
+- GPIO (SoC)
+- SD
+- eMMC
+- Reset
+- USB in EHCI mode (usb starts does switch device->host, usb stop does the opposite)
+- PMIC GPIOS (but not in generic subsystem)
+- PMIC "special" buttons (power, vol-)
+
+What is not working / known bugs:
+- SDHCI is slow (~2.5MiB/s for SD and eMMC)
diff --git a/board/qualcomm/dragonboard410c/u-boot.lds b/board/qualcomm/dragonboard410c/u-boot.lds
new file mode 100644
index 0000000..3fb4235
--- /dev/null
+++ b/board/qualcomm/dragonboard410c/u-boot.lds
@@ -0,0 +1,90 @@
+/*
+ * Override linker script for fastboot-readable images
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * Based on arch/arm/cpu/armv8/u-boot.lds (Just add header)
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
+OUTPUT_ARCH(aarch64)
+ENTRY(_fastboot_header)
+SECTIONS
+{
+	. = 0x00000000;
+
+	. = ALIGN(8);
+	.text :
+	{
+		*(.__image_copy_start)
+		board/qualcomm/dragonboard410c/head.o (.text*)
+		CPUDIR/start.o (.text*)
+		*(.text*)
+	}
+
+	. = ALIGN(8);
+	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+	. = ALIGN(8);
+	.data : {
+		*(.data*)
+	}
+
+	. = ALIGN(8);
+
+	. = .;
+
+	. = ALIGN(8);
+	.u_boot_list : {
+		KEEP(*(SORT(.u_boot_list*)));
+	}
+
+	. = ALIGN(8);
+
+	.image_copy_end :
+	{
+		*(.__image_copy_end)
+	}
+
+	. = ALIGN(8);
+
+	.rel_dyn_start :
+	{
+		*(.__rel_dyn_start)
+	}
+
+	.rela.dyn : {
+		*(.rela*)
+	}
+
+	.rel_dyn_end :
+	{
+		*(.__rel_dyn_end)
+	}
+
+	_end = .;
+
+	. = ALIGN(8);
+
+	.bss_start : {
+		KEEP(*(.__bss_start));
+	}
+
+	.bss : {
+		*(.bss*)
+		 . = ALIGN(8);
+	}
+
+	.bss_end : {
+		KEEP(*(.__bss_end));
+	}
+
+	/DISCARD/ : { *(.dynsym) }
+	/DISCARD/ : { *(.dynstr*) }
+	/DISCARD/ : { *(.dynamic*) }
+	/DISCARD/ : { *(.plt*) }
+	/DISCARD/ : { *(.interp*) }
+	/DISCARD/ : { *(.gnu*) }
+}
diff --git a/configs/dragonboard410c_defconfig b/configs/dragonboard410c_defconfig
new file mode 100644
index 0000000..fd2bc16
--- /dev/null
+++ b/configs/dragonboard410c_defconfig
@@ -0,0 +1,30 @@
+CONFIG_ARM=y
+CONFIG_ARM64=y
+CONFIG_ARCH_SNAPDRAGON=y
+CONFIG_TARGET_DRAGONBOARD410C=y
+
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="dragonboard410c => "
+CONFIG_CMD_USB=y
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_IMLS is not set
+CONFIG_DEFAULT_DEVICE_TREE="dragonboard410c"
+
+CONFIG_CLK=y
+CONFIG_MSM_GPIO=y
+CONFIG_PM8916_GPIO=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_RESET=y
+CONFIG_DM_MMC=y
+CONFIG_MSM_SDHCI=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_PM8916=y
+CONFIG_DM_SPMI=y
+CONFIG_SPMI_MSM=y
+CONFIG_MSM_SERIAL=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_STORAGE=y
diff --git a/include/configs/dragonboard410c.h b/include/configs/dragonboard410c.h
new file mode 100644
index 0000000..91f0e02
--- /dev/null
+++ b/include/configs/dragonboard410c.h
@@ -0,0 +1,182 @@
+/*
+ * Board configuration file for Dragonboard 410C
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __CONFIGS_DRAGONBOARD410C_H
+#define __CONFIGS_DRAGONBOARD410C_H
+
+#include <linux/sizes.h>
+#include <asm/arch/sysmap-apq8016.h>
+
+#define CONFIG_IDENT_STRING		"\nQualcomm-DragonBoard 410C"
+
+#define CONFIG_MISC_INIT_R /* To stop autoboot */
+
+/* Flat Device Tree Definitions */
+#define CONFIG_OF_LIBFDT
+
+/* Physical Memory Map */
+#define CONFIG_NR_DRAM_BANKS		1
+#define PHYS_SDRAM_1			0x80000000
+/* 1008 MB (the last ~30Mb are secured for TrustZone by ATF*/
+#define PHYS_SDRAM_1_SIZE		0x3da00000
+#define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
+#define CONFIG_SYS_TEXT_BASE		0x80080000
+#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_SDRAM_BASE + 0x7fff0)
+#define CONFIG_SYS_LOAD_ADDR		(CONFIG_SYS_SDRAM_BASE + 0x80000)
+#define CONFIG_SYS_BOOTM_LEN		0x1000000 /* 16MB max kernel size */
+
+/* UART */
+#define CONFIG_BAUDRATE			115200
+
+/* Generic Timer Definitions */
+#define COUNTER_FREQUENCY		19000000
+
+/* This are needed to have proper mmc support */
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_SDHCI
+
+#define CONFIG_SYS_LDSCRIPT "board/qualcomm/dragonboard410c/u-boot.lds"
+
+/* Fixup - in init code we switch from device to host mode,
+ * it has to be done after each HCD reset */
+#define CONFIG_EHCI_HCD_INIT_AFTER_RESET
+
+#define CONFIG_USB_HOST_ETHER /* Enable USB Networking */
+
+/* Support all possible USB ethernet dongles */
+#define CONFIG_USB_ETHER_DM9601
+#define CONFIG_USB_ETHER_ASIX
+#define CONFIG_USB_ETHER_ASIX88179
+#define CONFIG_USB_ETHER_MCS7830
+#define CONFIG_USB_ETHER_SMSC95XX
+
+/* Libraries  */
+#define CONFIG_MD5
+
+/* Extra Commands */
+#define CONFIG_CMD_CACHE
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ENV
+#define CONFIG_CMD_FAT		/* FAT support			*/
+#define CONFIG_CMD_GPIO
+#define CONFIG_CMD_GPT
+#define CONFIG_CMD_MD5SUM
+#define CONFIG_CMD_MEMINFO	/* meminfo			*/
+#define CONFIG_CMD_MMC
+/* Enable that for switching of boot partitions */
+/* Disabled by default as some sub-commands can brick eMMC */
+/*#define CONFIG_SUPPORT_EMMC_BOOT */
+#define CONFIG_CMD_PART
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_REGINFO	/* Register dump		*/
+#define CONFIG_CMD_TFTP
+#define CONFIG_CMD_TIMER
+#define CONFIG_CMD_UNZIP
+#define CONFIG_CMD_BOOTZ
+#define CONFIG_CMD_BOOTI
+
+/* Command line configuration */
+#define CONFIG_MENU
+#define CONFIG_SYS_LONGHELP
+
+/* Partition table support */
+#define HAVE_BLOCK_DEVICE /* Needed for partition commands */
+#define CONFIG_DOS_PARTITION
+#define CONFIG_EFI_PARTITION
+#define CONFIG_PARTITION_UUIDS
+
+/* BOOTP options */
+#define CONFIG_BOOTP_BOOTFILESIZE
+
+/* Environment - Boot*/
+#define CONFIG_BOOTDELAY		2	/* autoboot after 2 seconds */
+
+#define CONFIG_NFSBOOTCOMMAND ""
+#define CONFIG_BOOTCOMMAND "usb start && dhcp && tftp && usb stop && bootm"
+#define CONFIG_BOOTARGS "console=ttyMSM0,115200n8"
+
+/* Does what recovery does */
+#define REFLASH(file, part) \
+"part start mmc 0 "#part" start && "\
+"part size mmc 0 "#part" size && "\
+"tftp $loadaddr "#file" &&" \
+"mmc write $loadaddr $start $size &&"
+
+
+#define CONFIG_ENV_REFLASH \
+"mmc dev 0 &&"\
+"usb start &&"\
+"dhcp &&"\
+"tftp $loadaddr dragonboard/rescue/gpt_both0.bin && "\
+"mmc write $loadaddr 0 43 &&" \
+"mmc rescan &&"\
+REFLASH(dragonboard/rescue/NON-HLOS.bin, 1)\
+REFLASH(dragonboard/rescue/sbl1.mbn, 2)\
+REFLASH(dragonboard/rescue/rpm.mbn, 3)\
+REFLASH(dragonboard/rescue/tz.mbn, 4)\
+REFLASH(dragonboard/rescue/hyp.mbn, 5)\
+REFLASH(dragonboard/rescue/sec.dat, 6)\
+REFLASH(dragonboard/rescue/emmc_appsboot.mbn, 7)\
+REFLASH(dragonboard/u-boot.img, 8)\
+"usb stop &&"\
+"echo Reflash completed"
+
+#define CONFIG_UBOOT_REFLASH \
+"mmc dev 0 &&"\
+"usb start &&"\
+"dhcp &&"\
+"part start mmc 0 8 start && "\
+"setenv size 0x800  &&"\
+"tftp $loadaddr dragonboard/u-boot.img &&" \
+"mmc write $loadaddr $start $size &&"\
+"usb stop &&"\
+"echo Reflash completed &&" \
+"reset"
+
+/* Environment */
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"reflash="CONFIG_ENV_REFLASH"\0"\
+	"reflash_uboot="CONFIG_UBOOT_REFLASH"\0"\
+	"loadaddr=0x81000000\0" \
+	"fdt_high=0xffffffffffffffff\0" \
+	"initrd_high=0xffffffffffffffff\0" \
+	"linux_image=dragonboard/Image\0" \
+	"linux_addr=0x81000000\0"\
+	"fdt_image=dragonboard/apq8016-sbc.dtb\0" \
+	"fdt_addr=0x83000000\0"\
+	"ramdisk_addr=0x84000000\0"\
+	"ramdisk_image=dragonboard/initrd.img\0" \
+	"dl_uboot=tftp $loadaddr dragonboard/u-boot.img\0"\
+	"dl_kernel=tftp $linux_addr $linux_image " \
+		"&& tftp $fdt_addr $fdt_image\0"\
+	"dl_ramdisk=tftp $ramdisk_addr $ramdisk_image\0"\
+	"nboot_nord=usb start && run dl_kernel && usb stop && " \
+		    "booti $linux_addr - $fdt_addr\0"\
+	"nboot_rd=usb start && run dl_kernel && run dl_ramdisk && "\
+		  "booti $linux_addr $ramdisk_addr $fdt_addr\0"
+
+#define CONFIG_ENV_IS_NOWHERE
+#define CONFIG_ENV_SIZE			0x1000
+#define CONFIG_ENV_VARS_UBOOT_CONFIG
+#define CONFIG_SYS_NO_FLASH
+
+/* Size of malloc() pool */
+#define CONFIG_SYS_MALLOC_LEN		(CONFIG_ENV_SIZE + SZ_8M)
+
+/* Monitor Command Prompt */
+#define CONFIG_SYS_CBSIZE		512	/* Console I/O Buffer Size */
+#define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE + \
+					sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_BARGSIZE		CONFIG_SYS_CBSIZE
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_SYS_MAXARGS		64	/* max command args */
+
+
+#endif
-- 
2.5.0

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

* [U-Boot] [PATCH v1 05/16] usb: ulpi: Add Kconfig options for ULPI
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 05/16] usb: ulpi: Add Kconfig options for ULPI Mateusz Kulikowski
@ 2016-01-06 20:49   ` Marek Vasut
  2016-01-07 22:12     ` Mateusz Kulikowski
  0 siblings, 1 reply; 49+ messages in thread
From: Marek Vasut @ 2016-01-06 20:49 UTC (permalink / raw)
  To: u-boot

On Wednesday, January 06, 2016 at 07:21:17 PM, Mateusz Kulikowski wrote:
> The following options can be now enabled via defconfig:
> - CONFIG_USB_ULPI
> - CONFIG_USB_ULPI_VIEWPORT
> - CONFIG_USB_ULPI_VIEWPORT_OMAP
> 
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> ---
> 
> Changes in v1: New patch
> 
>  drivers/usb/Kconfig      |  2 ++
>  drivers/usb/ulpi/Kconfig | 10 ++++++++++
>  2 files changed, 12 insertions(+)
>  create mode 100644 drivers/usb/ulpi/Kconfig
> 
> diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
> index abb06fc..57b99f2 100644
> --- a/drivers/usb/Kconfig
> +++ b/drivers/usb/Kconfig
> @@ -53,6 +53,8 @@ source "drivers/usb/musb-new/Kconfig"
> 
>  source "drivers/usb/emul/Kconfig"
> 
> +source "drivers/usb/ulpi/Kconfig"
> +
>  comment "USB peripherals"
> 
>  config USB_STORAGE
> diff --git a/drivers/usb/ulpi/Kconfig b/drivers/usb/ulpi/Kconfig
> new file mode 100644
> index 0000000..f3210bc
> --- /dev/null
> +++ b/drivers/usb/ulpi/Kconfig
> @@ -0,0 +1,10 @@
> +comment "ULPI drivers"
> +
> +config USB_ULPI
> +	bool
> +
> +config USB_ULPI_VIEWPORT
> +	bool
> +
> +config USB_ULPI_VIEWPORT_OMAP
> +	bool

Description of these options is missing.

Best regards,
Marek Vasut

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

* [U-Boot] [PATCH v1 06/16] usb: Rename ehci-fsl.h to ehci-ci.h
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 06/16] usb: Rename ehci-fsl.h to ehci-ci.h Mateusz Kulikowski
@ 2016-01-06 20:51   ` Marek Vasut
  0 siblings, 0 replies; 49+ messages in thread
From: Marek Vasut @ 2016-01-06 20:51 UTC (permalink / raw)
  To: u-boot

On Wednesday, January 06, 2016 at 07:21:18 PM, Mateusz Kulikowski wrote:
> Most of ehci-fsl header describe USB controller
> designed by Chipidea and used by various SoC vendors.
> 
> This patch renames it to a generic header: ehci-ci.h
> Contents of file are not changed (so it contains several
> references to freescale SoCs).
> 
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> ---

Acked-by: Marek Vasut <marex@denx.de>

Best regards,
Marek Vasut

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

* [U-Boot] [PATCH v1 07/16] usb: ehci-ci: Add missing registers.
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 07/16] usb: ehci-ci: Add missing registers Mateusz Kulikowski
@ 2016-01-06 20:53   ` Marek Vasut
  0 siblings, 0 replies; 49+ messages in thread
From: Marek Vasut @ 2016-01-06 20:53 UTC (permalink / raw)
  To: u-boot

On Wednesday, January 06, 2016 at 07:21:19 PM, Mateusz Kulikowski wrote:
> Some registers of usb_ehci were marked as reserved.
> This may be true for some variants of Chipidea USB core, but they have
> meaning on other devices.
> 
> The following registers were added:
> sbusstatus/sbusmode: AHB-related registers
> genconfig*: Auxiluary IP core configuration registers.
> 
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> ---

CCing Fabio, so he can check this on the NXP chips :)

In general, I am not opposed to this change.

Reviewed-by: Marek Vasut <marex@denx.de>

> Changes in v1: New patch
> 
>  include/usb/ehci-ci.h | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/include/usb/ehci-ci.h b/include/usb/ehci-ci.h
> index 725aec5..305b180 100644
> --- a/include/usb/ehci-ci.h
> +++ b/include/usb/ehci-ci.h
> @@ -191,7 +191,11 @@ struct usb_ehci {
>  	u32     gptimer1_ld;	/* 0x088 - General Purpose Timer 1 load value */
>  	u32     gptimer1_ctrl;	/* 0x08C - General Purpose Timer 1 control */
>  	u32	sbuscfg;	/* 0x090 - System Bus Interface Control */
> -	u8	res2[0x6C];
> +	u32	sbusstatus;	/* 0x094 - System Bus Interface Status */
> +	u32	sbusmode;	/* 0x098 - System Bus Interface Mode */
> +	u32	genconfig;	/* 0x09C - USB Core Configuration */
> +	u32	genconfig2;	/* 0x0A0 - USB Core Configuration 2 */
> +	u8	res2[0x5c];
>  	u8	caplength;	/* 0x100 - Capability Register Length */
>  	u8	res3[0x1];
>  	u16	hciversion;	/* 0x102 - Host Interface Version */

Best regards,
Marek Vasut

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

* [U-Boot] [PATCH v1 08/16] ehci-ci.h: drop generic USBCMD fields
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 08/16] ehci-ci.h: drop generic USBCMD fields Mateusz Kulikowski
@ 2016-01-06 20:54   ` Marek Vasut
  0 siblings, 0 replies; 49+ messages in thread
From: Marek Vasut @ 2016-01-06 20:54 UTC (permalink / raw)
  To: u-boot

On Wednesday, January 06, 2016 at 07:21:20 PM, Mateusz Kulikowski wrote:
> Use definitions from ehci.h instead.
> 
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> ---

Nice

Acked-by: Marek Vasut <marex@denx.de>

Best regards,
Marek Vasut

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

* [U-Boot] [PATCH v1 09/16] ehci: Add support for Qualcomm EHCI
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 09/16] ehci: Add support for Qualcomm EHCI Mateusz Kulikowski
@ 2016-01-06 21:04   ` Marek Vasut
  2016-01-11 21:39     ` Mateusz Kulikowski
  0 siblings, 1 reply; 49+ messages in thread
From: Marek Vasut @ 2016-01-06 21:04 UTC (permalink / raw)
  To: u-boot

On Wednesday, January 06, 2016 at 07:21:21 PM, Mateusz Kulikowski wrote:
> This driver is able to reconfigure OTG controller into HOST mode.
> Board can add board-specific initialization as board_prepare_usb().
> It requires USB_ULPI_VIEWPORT enabled in board configuration.
> 
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>

[...]

> +static int msm_init_after_reset(struct ehci_ctrl *dev)
> +{
> +	struct msm_ehci_priv *p = container_of(dev, struct msm_ehci_priv, ctrl);
> +	struct usb_ehci *ehci = p->ehci;
> +
> +	/* select ULPI phy */
> +	writel(0x80000000, &ehci->portsc);

Don't we have macro for this bit ?

> +	setup_usb_phy(p);
> +
> +	/* Enable sess_vld */
> +	setbits_le32(&ehci->genconfig2, GEN2_SESS_VLD_CTRL_EN);
> +
> +	/* Enable external vbus configuration in the LINK */
> +	setbits_le32(&ehci->usbcmd, SESS_VLD_CTRL);
> +
> +	/* USB_OTG_HS_AHB_BURST */
> +	writel(0x0, &ehci->sbuscfg);
> +
> +	/* USB_OTG_HS_AHB_MODE: HPROT_MODE */
> +	/* Bus access related config. */
> +	writel(0x08, &ehci->sbusmode);
> +
> +	/* set mode to host controller */
> +	writel(CM_HOST, &ehci->usbmode);
> +
> +	return 0;
> +}

[...]

> +static int ehci_usb_remove(struct udevice *dev)
> +{
> +	struct msm_ehci_priv *p = dev_get_priv(dev);
> +	struct usb_ehci *ehci = p->ehci;
> +	int ret;
> +
> +	ret = ehci_deregister(dev);
> +	if (ret)
> +		return ret;
> +
> +	/* Stop controller. */
> +	clrbits_le32(&ehci->usbcmd, CMD_RUN);
> +
> +	reset_usb_phy(p);
> +
> +	ret = board_prepare_usb(USB_INIT_DEVICE); /* Board specific hook */
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Reset controller */
> +	setbits_le32(&ehci->usbcmd, CMD_RESET);
> +
> +	/* Wait for reset */
> +	if (wait_for_bit(__func__, &ehci->usbcmd, CMD_RESET, false, 30,

Ad. this wait_for_bit() , you can define a macro "wait_for_bit()" in some header 
file which would call the final __wait_for_bit(). The trick is, such macro will 
expand in place and you wouldn't have to call it with __func__ argument. The 
macro would be able to pass that __func__ argument into the final 
__wait_for_bit() . But that's just an idea, it doesn't prevent this driver from 
mainlining of course.

> +			 false)) {
> +		printf("Stuck on USB reset.\n");
> +		return -ETIMEDOUT;
> +	}
> +
> +	return 0;
> +}

Other than that portsc bit, add my

Acked-by: Marek Vasut <marex@denx.de>

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

* [U-Boot] [PATCH v1 16/16] board: Add Qualcomm Dragonboard 410C support
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 16/16] board: Add Qualcomm Dragonboard 410C support Mateusz Kulikowski
@ 2016-01-07 10:23   ` Sjoerd Simons
  2016-01-11 21:49     ` Mateusz Kulikowski
  2016-01-11 16:58   ` Simon Glass
  2016-01-20  4:35   ` Simon Glass
  2 siblings, 1 reply; 49+ messages in thread
From: Sjoerd Simons @ 2016-01-07 10:23 UTC (permalink / raw)
  To: u-boot

On Wed, 2016-01-06 at 19:21 +0100, Mateusz Kulikowski wrote:
> This commit add support for 96Boards Dragonboard410C.
> 
> diff --git a/include/configs/dragonboard410c.h
> b/include/configs/dragonboard410c.h
> new file mode 100644
> index 0000000..91f0e02
> --- /dev/null
> +++ b/include/configs/dragonboard410c.h
> @@ -0,0 +1,182 @@
> +/*
> + * Board configuration file for Dragonboard 410C
> + *
> + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.c
> om>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#ifndef __CONFIGS_DRAGONBOARD410C_H
> +#define __CONFIGS_DRAGONBOARD410C_H
> +
> +#include <linux/sizes.h>
> +#include <asm/arch/sysmap-apq8016.h>
> +
> +#define CONFIG_IDENT_STRING		"\nQualcomm-DragonBoard
> 410C"
> +
> +#define CONFIG_MISC_INIT_R /* To stop autoboot */
> +
> +/* Flat Device Tree Definitions */
> +#define CONFIG_OF_LIBFDT
> +
> +/* Physical Memory Map */
> +#define CONFIG_NR_DRAM_BANKS		1
> +#define PHYS_SDRAM_1			0x80000000
> +/* 1008 MB (the last ~30Mb are secured for TrustZone by ATF*/
> +#define PHYS_SDRAM_1_SIZE		0x3da00000
> +#define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
> +#define CONFIG_SYS_TEXT_BASE		0x80080000
> +#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_SDRAM_BAS
> E + 0x7fff0)
> +#define CONFIG_SYS_LOAD_ADDR		(CONFIG_SYS_SDRAM_BASE +
> 0x80000)
> +#define CONFIG_SYS_BOOTM_LEN		0x1000000 /* 16MB max
> kernel size */
> +
> +/* UART */
> +#define CONFIG_BAUDRATE			115200
> +
> +/* Generic Timer Definitions */
> +#define COUNTER_FREQUENCY		19000000
> +
> +/* This are needed to have proper mmc support */
> +#define CONFIG_MMC
> +#define CONFIG_GENERIC_MMC
> +#define CONFIG_SDHCI
> +
> +#define CONFIG_SYS_LDSCRIPT "board/qualcomm/dragonboard410c/u-
> boot.lds"
> +
> +/* Fixup - in init code we switch from device to host mode,
> + * it has to be done after each HCD reset */
> +#define CONFIG_EHCI_HCD_INIT_AFTER_RESET
> +
> +#define CONFIG_USB_HOST_ETHER /* Enable USB Networking */
> +
> +/* Support all possible USB ethernet dongles */
> +#define CONFIG_USB_ETHER_DM9601
> +#define CONFIG_USB_ETHER_ASIX
> +#define CONFIG_USB_ETHER_ASIX88179
> +#define CONFIG_USB_ETHER_MCS7830
> +#define CONFIG_USB_ETHER_SMSC95XX
> +
> +/* Libraries??*/
> +#define CONFIG_MD5
> +
> +/* Extra Commands */
> +#define CONFIG_CMD_CACHE
> +#define CONFIG_CMD_DHCP
> +#define CONFIG_CMD_ENV
> +#define CONFIG_CMD_FAT		/* FAT support			
> */
> +#define CONFIG_CMD_GPIO
> +#define CONFIG_CMD_GPT
> +#define CONFIG_CMD_MD5SUM
> +#define CONFIG_CMD_MEMINFO	/* meminfo			
> */
> +#define CONFIG_CMD_MMC
> +/* Enable that for switching of boot partitions */
> +/* Disabled by default as some sub-commands can brick eMMC */
> +/*#define CONFIG_SUPPORT_EMMC_BOOT */
> +#define CONFIG_CMD_PART
> +#define CONFIG_CMD_PING
> +#define CONFIG_CMD_REGINFO	/* Register dump		*/
> +#define CONFIG_CMD_TFTP
> +#define CONFIG_CMD_TIMER
> +#define CONFIG_CMD_UNZIP
> +#define CONFIG_CMD_BOOTZ
> +#define CONFIG_CMD_BOOT

Using config_distro_defaults would give you a nice set of default
commands to include. May make sense to use that and drop the
duplicates.

Also the 410C is 64 bit arm afaik, so i would hvae expected _CMD_BOOTI
rather then _CMD_BOOTZ


> +
> +/* Command line configuration */
> +#define CONFIG_MENU
> +#define CONFIG_SYS_LONGHELP
> +
> +/* Partition table support */
> +#define HAVE_BLOCK_DEVICE /* Needed for partition commands */
> +#define CONFIG_DOS_PARTITION
> +#define CONFIG_EFI_PARTITION
> +#define CONFIG_PARTITION_UUIDS
> +
> +/* BOOTP options */
> +#define CONFIG_BOOTP_BOOTFILESIZE
> +
> +/* Environment - Boot*/
> +#define CONFIG_BOOTDELAY		2	/* autoboot after 2
> seconds */
> +
> +#define CONFIG_NFSBOOTCOMMAND ""
> +#define CONFIG_BOOTCOMMAND "usb start && dhcp && tftp && usb stop &&
> bootm"

Any reason for a custom default bootcmd rather then
using?config_distro_bootcmd ? (Especially for board like the 96boards
ones it seems quite useful to use a standardized boot sequence).


-- 
Sjoerd Simons
Collabora Ltd.

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

* [U-Boot] [PATCH v1 05/16] usb: ulpi: Add Kconfig options for ULPI
  2016-01-06 20:49   ` Marek Vasut
@ 2016-01-07 22:12     ` Mateusz Kulikowski
  2016-01-07 22:50       ` Marek Vasut
  2016-01-07 23:18       ` Simon Glass
  0 siblings, 2 replies; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-07 22:12 UTC (permalink / raw)
  To: u-boot

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

On 06.01.2016 21:49, Marek Vasut wrote:
> On Wednesday, January 06, 2016 at 07:21:17 PM, Mateusz Kulikowski wrote:
>> The following options can be now enabled via defconfig:
>> - CONFIG_USB_ULPI
>> - CONFIG_USB_ULPI_VIEWPORT
>> - CONFIG_USB_ULPI_VIEWPORT_OMAP
>>
[...]

>> +++ b/drivers/usb/ulpi/Kconfig
>> @@ -0,0 +1,10 @@
>> +comment "ULPI drivers"
>> +
>> +config USB_ULPI
>> +	bool
>> +
>> +config USB_ULPI_VIEWPORT
>> +	bool
>> +
>> +config USB_ULPI_VIEWPORT_OMAP
>> +	bool
> 
> Description of these options is missing.

My intention here was to keep it away from "users". 

This options are not "optional" in any way.
They are rather like CPU_something or VBAR_something, 
that is - they are required and should be selected by drivers that use them, 
but without this drivers, they are useless.

But maybe I'm missing something :)
If anyone insists on that - I'll make them visible and add description.



Regards,
Mateusz
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQEcBAEBCAAGBQJWjuLGAAoJELvtohmVtQzBKT0H/RpJpIiXOrjLpAiQRL2V78t7
RUFiaCNolTHWqxerJ1JK4RqBiO9xn1Z8CWzAyxOkjt+fGUzjkkWjCJ4l5tDAcqpP
BXPCPEMu4otOKN5LksUOBWDNIWyFuuvvDNS/tbQmPwosNCaUdKankxwbP4esoNuO
t4ZpoDgcls9p73zTCYfcku6KR2viSEGabpvUT0YATmtc/2GdYfRjZYGjdEAF2Rug
oEqDFX7tzVqgOtzWSoGdvA/qiUbLTqc4L2AyxWrMhgyl780bMaKzBCPtEQrAP/iD
sc/ikXGB72I4Km5IhUoliDCZeJtxaPrpfZo1L7vOQ/WXQDGTcq7JWQhgKJ11dUw=
=08ri
-----END PGP SIGNATURE-----

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

* [U-Boot] [PATCH v1 05/16] usb: ulpi: Add Kconfig options for ULPI
  2016-01-07 22:12     ` Mateusz Kulikowski
@ 2016-01-07 22:50       ` Marek Vasut
  2016-01-07 23:18       ` Simon Glass
  1 sibling, 0 replies; 49+ messages in thread
From: Marek Vasut @ 2016-01-07 22:50 UTC (permalink / raw)
  To: u-boot

On Thursday, January 07, 2016 at 11:12:27 PM, Mateusz Kulikowski wrote:
> On 06.01.2016 21:49, Marek Vasut wrote:
> > On Wednesday, January 06, 2016 at 07:21:17 PM, Mateusz Kulikowski wrote:
> >> The following options can be now enabled via defconfig:
> >> - CONFIG_USB_ULPI
> >> - CONFIG_USB_ULPI_VIEWPORT
> >> - CONFIG_USB_ULPI_VIEWPORT_OMAP
> 
> [...]
> 
> >> +++ b/drivers/usb/ulpi/Kconfig
> >> @@ -0,0 +1,10 @@
> >> +comment "ULPI drivers"
> >> +
> >> +config USB_ULPI
> >> +	bool
> >> +
> >> +config USB_ULPI_VIEWPORT
> >> +	bool
> >> +
> >> +config USB_ULPI_VIEWPORT_OMAP
> >> +	bool
> > 
> > Description of these options is missing.
> 
> My intention here was to keep it away from "users".
> 
> This options are not "optional" in any way.
> They are rather like CPU_something or VBAR_something,
> that is - they are required and should be selected by drivers that use
> them, but without this drivers, they are useless.

OK, so they're just options which are selected by drivers. Got it.
All is good from my side then.

> But maybe I'm missing something :)
> If anyone insists on that - I'll make them visible and add description.
> 
> 
> 
> Regards,
> Mateusz

Best regards,
Marek Vasut

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

* [U-Boot] [PATCH v1 05/16] usb: ulpi: Add Kconfig options for ULPI
  2016-01-07 22:12     ` Mateusz Kulikowski
  2016-01-07 22:50       ` Marek Vasut
@ 2016-01-07 23:18       ` Simon Glass
  2016-01-11 21:30         ` Mateusz Kulikowski
  1 sibling, 1 reply; 49+ messages in thread
From: Simon Glass @ 2016-01-07 23:18 UTC (permalink / raw)
  To: u-boot

Hi,

On 7 January 2016 at 15:12, Mateusz Kulikowski
<mateusz.kulikowski@gmail.com> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA256
>
> On 06.01.2016 21:49, Marek Vasut wrote:
>> On Wednesday, January 06, 2016 at 07:21:17 PM, Mateusz Kulikowski wrote:
>>> The following options can be now enabled via defconfig:
>>> - CONFIG_USB_ULPI
>>> - CONFIG_USB_ULPI_VIEWPORT
>>> - CONFIG_USB_ULPI_VIEWPORT_OMAP
>>>
> [...]
>
>>> +++ b/drivers/usb/ulpi/Kconfig
>>> @@ -0,0 +1,10 @@
>>> +comment "ULPI drivers"
>>> +
>>> +config USB_ULPI
>>> +    bool
>>> +
>>> +config USB_ULPI_VIEWPORT
>>> +    bool
>>> +
>>> +config USB_ULPI_VIEWPORT_OMAP
>>> +    bool
>>
>> Description of these options is missing.
>
> My intention here was to keep it away from "users".
>
> This options are not "optional" in any way.
> They are rather like CPU_something or VBAR_something,
> that is - they are required and should be selected by drivers that use them,
> but without this drivers, they are useless.

Perhaps we don't need the options at all then?

But there are lots of users in the tree. You should use the
moveconfig.py script to move them all to Kconfig.

>
> But maybe I'm missing something :)
> If anyone insists on that - I'll make them visible and add description.

Please add detailed help for all Kconfig options you add.
>

Regards,
Simon

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

* [U-Boot] [PATCH v1 01/16] serial: Add support for Qualcomm serial port
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 01/16] serial: Add support for Qualcomm serial port Mateusz Kulikowski
@ 2016-01-11 16:57   ` Simon Glass
  0 siblings, 0 replies; 49+ messages in thread
From: Simon Glass @ 2016-01-11 16:57 UTC (permalink / raw)
  To: u-boot

Hi Mateusz,

On 6 January 2016 at 11:21, Mateusz Kulikowski
<mateusz.kulikowski@gmail.com> wrote:
> This driver works in "new" Data Mover UART mode, so
> will be compatible with modern Qualcomm chips only.
>
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> ---
>
> Changes in v1:
> - Added (better) help to KConfig
> - Added dt binding documentation
> - Fixed include ordering
> - Reworked msm_serial_getc
> - Added error handling to msm_uart_clk_init (that is ignored later for now)
> - Dropped unneeded DM_FLAG_PRE_RELOC
>
>  doc/device-tree-bindings/serial/msm-serial.txt |   6 +
>  drivers/serial/Kconfig                         |   8 +
>  drivers/serial/Makefile                        |   1 +
>  drivers/serial/serial_msm.c                    | 206 +++++++++++++++++++++++++
>  4 files changed, 221 insertions(+)
>  create mode 100644 doc/device-tree-bindings/serial/msm-serial.txt
>  create mode 100644 drivers/serial/serial_msm.c

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

See note and a few nits below...

>
> diff --git a/doc/device-tree-bindings/serial/msm-serial.txt b/doc/device-tree-bindings/serial/msm-serial.txt
> new file mode 100644
> index 0000000..48b8428
> --- /dev/null
> +++ b/doc/device-tree-bindings/serial/msm-serial.txt
> @@ -0,0 +1,6 @@
> +Qualcomm UART (Data Mover mode)
> +
> +Required properties:
> +- compatible: must be "qcom,msm-uartdm-v1.4"
> +- reg: start address and size of the registers
> +- clock: interface clock (must accept baudrate as a frequency)
> diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
> index 1fc287e..56d7b76 100644
> --- a/drivers/serial/Kconfig
> +++ b/drivers/serial/Kconfig
> @@ -223,4 +223,12 @@ config UNIPHIER_SERIAL
>           If you have a UniPhier based board and want to use the on-chip
>           serial ports, say Y to this option. If unsure, say N.
>
> +config MSM_SERIAL
> +       bool "Qualcomm on-chip UART"
> +       depends on DM_SERIAL
> +       help
> +         Support Data Mover UART used on Qualcomm Snapdragon SoCs.
> +         It should support all Qualcomm devices with UARTDM version 1.4,
> +         for example APQ8016 and MSM8916.
> +         Single baudrate is supported in current implementation (115200).
>  endmenu
> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
> index dd87147..d052175 100644
> --- a/drivers/serial/Makefile
> +++ b/drivers/serial/Makefile
> @@ -41,6 +41,7 @@ obj-$(CONFIG_MXS_AUART) += mxs_auart.o
>  obj-$(CONFIG_ARC_SERIAL) += serial_arc.o
>  obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o
>  obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o
> +obj-$(CONFIG_MSM_SERIAL) += serial_msm.o
>
>  ifndef CONFIG_SPL_BUILD
>  obj-$(CONFIG_USB_TTY) += usbtty.o
> diff --git a/drivers/serial/serial_msm.c b/drivers/serial/serial_msm.c
> new file mode 100644
> index 0000000..344f254
> --- /dev/null
> +++ b/drivers/serial/serial_msm.c
> @@ -0,0 +1,206 @@
> +/*
> + * Qualcomm UART driver
> + *
> + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> + *
> + * UART will work in Data Mover mode.
> + * Based on Linux driver.
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <serial.h>
> +#include <watchdog.h>
> +#include <asm/io.h>
> +#include <linux/compiler.h>
> +
> +/* Serial registers - this driver works in uartdm mode*/
> +
> +#define UARTDM_DMRX             0x34 /* Max RX transfer length */
> +#define UARTDM_NCF_TX           0x40 /* Number of chars to TX */
> +
> +#define UARTDM_RXFS             0x50 /* RX channel status register */
> +#define UARTDM_RXFS_BUF_SHIFT   0x7  /* Number of bytes in the packing buffer */
> +#define UARTDM_RXFS_BUF_MASK    0x7
> +
> +#define UARTDM_SR                0xA4 /* Status register */
> +#define UARTDM_SR_RX_READY       (1 << 0) /* Word is the receiver FIFO */
> +#define UARTDM_SR_TX_EMPTY       (1 << 3) /* Transmitter underrun */
> +#define UARTDM_SR_UART_OVERRUN   (1 << 4) /* Receive overrun */
> +
> +#define UARTDM_CR                         0xA8 /* Command register */
> +#define UARTDM_CR_CMD_RESET_ERR           (3 << 4) /* Clear overrun error */
> +#define UARTDM_CR_CMD_RESET_STALE_INT     (8 << 4) /* Clears stale irq */
> +#define UARTDM_CR_CMD_RESET_TX_READY      (3 << 8) /* Clears TX Ready irq*/
> +#define UARTDM_CR_CMD_FORCE_STALE         (4 << 8) /* Causes stale event */
> +#define UARTDM_CR_CMD_STALE_EVENT_DISABLE (6 << 8) /* Disable stale event */
> +
> +#define UARTDM_IMR                0xB0 /* Interrupt mask register */
> +#define UARTDM_ISR                0xB4 /* Interrupt status register */
> +#define UARTDM_ISR_TX_READY       0x80 /* TX FIFO empty */
> +
> +#define UARTDM_TF               0x100 /* UART Transmit FIFO register */
> +#define UARTDM_RF               0x140 /* UART Receive FIFO register */
> +
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct msm_serial_data {
> +       phys_addr_t base;
> +       unsigned chars_cnt; /* number of buffered chars */
> +       uint32_t chars_buf; /* buffered chars */
> +};
> +
> +static int msm_serial_getc(struct udevice *dev)
> +{
> +       struct msm_serial_data *p = dev_get_priv(dev);
> +       char c;
> +       unsigned sr;
> +
> +       if (!p->chars_buf) {
> +               /* Clear error in case of buffer overrun */
> +               if (readl(p->base + UARTDM_SR) & UARTDM_SR_UART_OVERRUN)
> +                       writel(UARTDM_CR_CMD_RESET_ERR, p->base + UARTDM_CR);
> +
> +               /* We need to fetch new character */
> +               sr = readl(p->base + UARTDM_SR);
> +
> +               if (sr & UARTDM_SR_RX_READY) {
> +                       /* There are at least 4 bytes in fifo */
> +                       p->chars_buf = readl(p->base + UARTDM_RF);
> +                       p->chars_cnt = 4;
> +               } else {
> +                       /* Check if there is anything in fifo */
> +                       p->chars_cnt = readl(p->base + UARTDM_RXFS);
> +                       /* Extract number of characters in UART packing buffer*/
> +                       p->chars_cnt = (p->chars_cnt >> UARTDM_RXFS_BUF_SHIFT) &
> +                                      UARTDM_RXFS_BUF_MASK;
> +                       if (!p->chars_cnt)
> +                               return -EAGAIN;
> +
> +                       /* There is at least one charcter, move it to fifo */
> +                       writel(UARTDM_CR_CMD_FORCE_STALE, p->base + UARTDM_CR);
> +
> +                       p->chars_buf = readl(p->base + UARTDM_RF);
> +                       writel(UARTDM_CR_CMD_RESET_STALE_INT,
> +                              p->base + UARTDM_CR);
> +                       writel(0xFFFFFF, p->base + UARTDM_DMRX);
> +               }
> +       }
> +
> +       c = p->chars_buf & 0xFF;
> +       p->chars_buf >>= 8;
> +       p->chars_cnt--;
> +
> +       return c;
> +}
> +
> +static int msm_serial_putc(struct udevice *dev, const char ch)
> +{
> +       struct msm_serial_data *p = dev_get_priv(dev);
> +
> +       if (!(readl(p->base + UARTDM_SR) & UARTDM_SR_TX_EMPTY) &&
> +           !(readl(p->base + UARTDM_ISR) & UARTDM_ISR_TX_READY))
> +               return -EAGAIN;
> +
> +       writel(UARTDM_CR_CMD_RESET_TX_READY, p->base + UARTDM_CR);
> +
> +       writel(1, p->base + UARTDM_NCF_TX);
> +       writel(ch, p->base + UARTDM_TF);
> +       return 0;
> +}
> +
> +static int msm_serial_pending(struct udevice *dev, bool input)
> +{
> +       struct msm_serial_data *p = dev_get_priv(dev);
> +
> +       if (input) {
> +               if (p->chars_cnt)
> +                       return 1;
> +               if (readl(p->base + UARTDM_SR) & UARTDM_SR_RX_READY)
> +                       return 1;
> +               if (readl(p->base + UARTDM_RXFS))
> +                       return 1;
> +       }
> +       return 0;
> +}
> +
> +static const struct dm_serial_ops msm_serial_ops = {
> +       .putc = msm_serial_putc,
> +       .pending = msm_serial_pending,
> +       .getc = msm_serial_getc,
> +};
> +
> +static int msm_uart_clk_init(struct udevice *dev)
> +{
> +       uint clk_rate = fdtdec_get_uint(gd->fdt_blob, dev->of_offset,
> +                                       "clock-frequency", 115200);
> +       uint clkd[2]; /* clk_id and clk_no */
> +       int clk_offset;
> +       struct udevice *clk;
> +       int ret;
> +
> +       ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "clock", clkd,
> +                                  2);
> +       if (ret)
> +               return ret;
> +
> +       clk_offset = fdt_node_offset_by_phandle(gd->fdt_blob, clkd[0]);
> +       if (clk_offset < 0)
> +               return clk_offset;
> +
> +       ret = uclass_get_device_by_of_offset(UCLASS_CLK, clk_offset, &clk);
> +       if (ret)
> +               return ret;

We can do much better than this in the future. Will have some patches
out soon. There is fdtdec_lookup_phandle() which helps a bit, but
really we want to get a clock directly. Anyway, this works for now.

> +
> +       ret = clk_set_periph_rate(clk, clkd[1], clk_rate);
> +       if (ret < 0)
> +               return ret;
> +
> +       return 0;
> +}
> +
> +static int msm_serial_probe(struct udevice *dev)
> +{
> +       struct msm_serial_data *p = dev_get_priv(dev);
> +
> +       msm_uart_clk_init(dev); /* Ignore return value and hope clock was
> +                                 properly initialized by earlier loaders */
> +
> +       if (readl(p->base + UARTDM_SR) & UARTDM_SR_UART_OVERRUN)
> +               writel(UARTDM_CR_CMD_RESET_ERR, p->base + UARTDM_CR);
> +
> +       writel(0, p->base + UARTDM_IMR);
> +       writel(UARTDM_CR_CMD_STALE_EVENT_DISABLE, p->base + UARTDM_CR);
> +       writel(0xFFFFFF, p->base + UARTDM_DMRX);

nit: please try to put a blank line before return.

> +       return 0;
> +}
> +
> +static int msm_serial_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct msm_serial_data *p = dev_get_priv(dev);

Please use *priv instead of *p. We should avoid single characters for
variable names.

> +
> +       p->base = dev_get_addr(dev);
> +       if (p->base == FDT_ADDR_T_NONE)
> +               return -EINVAL;
> +       return 0;
> +}
> +
> +static const struct udevice_id msm_serial_ids[] = {
> +       { .compatible = "qcom,msm-uartdm-v1.4" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(serial_msm) = {
> +       .name   = "serial_msm",
> +       .id     = UCLASS_SERIAL,
> +       .of_match = msm_serial_ids,
> +       .ofdata_to_platdata = ,
> +       .priv_auto_alloc_size = sizeof(struct msm_serial_data),
> +       .probe = msm_serial_probe,
> +       .ops    = &msm_serial_ops,
> +};
> --
> 2.5.0
>

Regards,
Simon

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

* [U-Boot] [PATCH v1 02/16] gpio: Add support for Qualcomm gpio controller
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 02/16] gpio: Add support for Qualcomm gpio controller Mateusz Kulikowski
@ 2016-01-11 16:57   ` Simon Glass
  2016-01-11 21:27     ` Mateusz Kulikowski
  0 siblings, 1 reply; 49+ messages in thread
From: Simon Glass @ 2016-01-11 16:57 UTC (permalink / raw)
  To: u-boot

Hi,

On 6 January 2016 at 11:21, Mateusz Kulikowski
<mateusz.kulikowski@gmail.com> wrote:
> Add support for gpio controllers on Qualcomm Snapdragon devices.
> This devices are usually called Top Level Mode Multiplexing in
> Qualcomm documentation.
>
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> ---
>
> Changes in v1:
> - Added dt binding documentation
> - Added help to KConfig
> - Use clrsetbits() to switch direction
> - Fixed include order
> - Added #defines for registers/register fields
> - Added secondary compatible string
>
>  doc/device-tree-bindings/gpio/gpio-msm.txt |  22 +++++
>  drivers/gpio/Kconfig                       |  14 ++++
>  drivers/gpio/Makefile                      |   2 +-
>  drivers/gpio/msm_gpio.c                    | 129 +++++++++++++++++++++++++++++
>  4 files changed, 166 insertions(+), 1 deletion(-)
>  create mode 100644 doc/device-tree-bindings/gpio/gpio-msm.txt
>  create mode 100644 drivers/gpio/msm_gpio.c

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

nits below

>
> diff --git a/doc/device-tree-bindings/gpio/gpio-msm.txt b/doc/device-tree-bindings/gpio/gpio-msm.txt
> new file mode 100644
> index 0000000..966ce0a
> --- /dev/null
> +++ b/doc/device-tree-bindings/gpio/gpio-msm.txt
> @@ -0,0 +1,22 @@
> +Qualcomm Snapdragon GPIO controller
> +
> +Required properties:
> +- compatible : "qcom,msm8916-pinctrl" or "qcom,apq8016-pinctrl"
> +- reg : Physical base address and length of the controller's registers.
> +       This controller is called "Top Level Mode Multiplexing" in
> +       Qualcomm documentation.
> +- #gpio-cells : Should be one (pin number).
> +- gpio-controller : Marks the device node as a GPIO controller.
> +- gpio-count: Number of GPIO pins.
> +- gpio-bank-name: (optional) name of gpio bank. As default "soc" is used.
> +
> +Example:
> +
> +soc_gpios: pinctrl at 1000000 {
> +       compatible = "qcom,msm8916-pinctrl";
> +       reg = <0x1000000 0x300000>;
> +       gpio-controller;
> +       gpio-count = <122>;
> +       gpio-bank-name="soc";
> +       #gpio-cells = <1>;
> +};
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index e60e9fd..3d112b9 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -46,6 +46,20 @@ config LPC32XX_GPIO
>         help
>           Support for the LPC32XX GPIO driver.
>
> +config MSM_GPIO
> +       bool "Qualcomm GPIO driver"
> +       depends on DM_GPIO
> +       default n
> +       help
> +         Support GPIO controllers on Qualcomm Snapdragon family of SoCs.
> +         This controller have single bank (default name "soc"), every
> +         gpio has it's own set of registers.
> +         Only simple GPIO operations are supported (get/set, change of
> +         direction and checking pin function).
> +         Supported devices:
> +         - APQ8016
> +         - MSM8916
> +
>  config ROCKCHIP_GPIO
>         bool "Rockchip GPIO driver"
>         depends on DM_GPIO
> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> index fb4fd25..9520b1e 100644
> --- a/drivers/gpio/Makefile
> +++ b/drivers/gpio/Makefile
> @@ -46,4 +46,4 @@ obj-$(CONFIG_STM32_GPIO)      += stm32_gpio.o
>  obj-$(CONFIG_ZYNQ_GPIO)                += zynq_gpio.o
>  obj-$(CONFIG_VYBRID_GPIO)      += vybrid_gpio.o
>  obj-$(CONFIG_HIKEY_GPIO)       += hi6220_gpio.o
> -
> +obj-$(CONFIG_MSM_GPIO)         += msm_gpio.o
> diff --git a/drivers/gpio/msm_gpio.c b/drivers/gpio/msm_gpio.c
> new file mode 100644
> index 0000000..173c526
> --- /dev/null
> +++ b/drivers/gpio/msm_gpio.c
> @@ -0,0 +1,129 @@
> +/*
> + * Qualcomm GPIO driver
> + *
> + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <asm/io.h>
> +#include <asm/gpio.h>

gpio.h comes before io.h

> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* Register offsets */
> +#define GPIO_CONFIG_OFF(no)         ((no) * 0x1000)
> +#define GPIO_IN_OUT_OFF(no)         ((no) * 0x1000 + 0x4)
> +
> +/* OE */
> +#define GPIO_OE_DISABLE  (0x0 << 9)
> +#define GPIO_OE_ENABLE   (0x1 << 9)
> +#define GPIO_OE_MASK     (0x1 << 9)
> +
> +/* GPIO_IN_OUT register shifts. */
> +#define GPIO_IN          0
> +#define GPIO_OUT         1
> +
> +struct msm_gpio_bank {
> +       phys_addr_t base;
> +};
> +
> +static int msm_gpio_direction_input(struct udevice *dev, unsigned int gpio)
> +{
> +       struct msm_gpio_bank *priv = dev_get_priv(dev);
> +       phys_addr_t reg = priv->base + GPIO_CONFIG_OFF(gpio);
> +
> +       /* Disable OE bit */
> +       clrsetbits_le32(reg, GPIO_OE_MASK, GPIO_OE_DISABLE);
> +       return 0;
> +}
> +
> +static int msm_gpio_set_value(struct udevice *dev, unsigned gpio, int value)
> +{
> +       struct msm_gpio_bank *priv = dev_get_priv(dev);
> +
> +       value = !!value;
> +       /* set value */
> +       writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_OFF(gpio));
> +       return 0;
> +}
> +
> +static int msm_gpio_direction_output(struct udevice *dev, unsigned gpio,
> +                                    int value)
> +{
> +       struct msm_gpio_bank *priv = dev_get_priv(dev);
> +       phys_addr_t reg = priv->base + GPIO_CONFIG_OFF(gpio);
> +
> +       value = !!value;
> +       /* set value */
> +       writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_OFF(gpio));
> +       /* switch direction */
> +       clrsetbits_le32(reg, GPIO_OE_MASK, GPIO_OE_ENABLE);
> +       return 0;
> +}
> +
> +static int msm_gpio_get_value(struct udevice *dev, unsigned gpio)
> +{
> +       struct msm_gpio_bank *priv = dev_get_priv(dev);
> +
> +       return !!(readl(priv->base + GPIO_IN_OUT_OFF(gpio)) >> GPIO_IN);
> +}
> +
> +static int msm_gpio_get_function(struct udevice *dev, unsigned offset)
> +{
> +       struct msm_gpio_bank *priv = dev_get_priv(dev);
> +
> +       if (readl(priv->base + GPIO_CONFIG_OFF(offset)) & GPIO_OE_ENABLE)
> +               return GPIOF_OUTPUT;
> +       return GPIOF_INPUT;

Can it ever be GPIOF_FUNCTION?

> +}
> +
> +static const struct dm_gpio_ops gpio_msm_ops = {
> +       .direction_input        = msm_gpio_direction_input,
> +       .direction_output       = msm_gpio_direction_output,
> +       .get_value              = msm_gpio_get_value,
> +       .set_value              = msm_gpio_set_value,
> +       .get_function           = msm_gpio_get_function,
> +};
> +
> +static int msm_gpio_probe(struct udevice *dev)
> +{
> +       struct msm_gpio_bank *priv = dev_get_priv(dev);
> +
> +       priv->base = dev_get_addr(dev);
> +       return priv->base == FDT_ADDR_T_NONE;

Maybe you mean:

      return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0;

> +}
> +
> +static int msm_gpio_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
> +
> +       uc_priv->gpio_count = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
> +                                            "gpio-count", 0);
> +       uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev->of_offset,
> +                                        "gpio-bank-name", NULL);
> +       if (uc_priv->bank_name == NULL)
> +               uc_priv->bank_name = "soc";
> +       return 0;
> +}
> +
> +static const struct udevice_id msm_gpio_ids[] = {
> +       { .compatible = "qcom,msm8916-pinctrl" },
> +       { .compatible = "qcom,apq8016-pinctrl" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(gpio_msm) = {
> +       .name   = "gpio_msm",
> +       .id     = UCLASS_GPIO,
> +       .of_match = msm_gpio_ids,
> +       .ofdata_to_platdata = msm_gpio_ofdata_to_platdata,
> +       .probe  = msm_gpio_probe,
> +       .ops    = &gpio_msm_ops,
> +       .priv_auto_alloc_size = sizeof(struct msm_gpio_bank),
> +};
> +
> +
> --
> 2.5.0
>

Regards,
Simon

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

* [U-Boot] [PATCH v1 03/16] mmc: Add support for Qualcomm SDHCI controller
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 03/16] mmc: Add support for Qualcomm SDHCI controller Mateusz Kulikowski
@ 2016-01-11 16:57   ` Simon Glass
  0 siblings, 0 replies; 49+ messages in thread
From: Simon Glass @ 2016-01-11 16:57 UTC (permalink / raw)
  To: u-boot

On 6 January 2016 at 11:21, Mateusz Kulikowski
<mateusz.kulikowski@gmail.com> wrote:
> Add support for SD/eMMC controller present on some Qualcomm Snapdragon
> devices. This controller implements SDHCI 2.0 interface but requires
> vendor-specific initialization.
> Driver works in PIO mode as ADMA is not supported by U-Boot (yet).
>
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> ---
>
> Changes in v1:
> - Added commit message
> - Added DT binding documentation
> - Added Kconfig help
> - Reordered includes
> - Dropped redundant fields from msm_sdhc
> - Cleaned up clock init code (+ added error handling)
> - Dropped mdelay - use wait_for_bit instead in reset code
> - Added missing newline after declarations
> - Added error handling if "reg" is missing
> - Converted base address to pointer
>
>  doc/device-tree-bindings/mmc/msm_sdhci.txt |  25 ++++
>  drivers/mmc/Kconfig                        |   9 ++
>  drivers/mmc/Makefile                       |   1 +
>  drivers/mmc/msm_sdhci.c                    | 180 +++++++++++++++++++++++++++++
>  4 files changed, 215 insertions(+)
>  create mode 100644 doc/device-tree-bindings/mmc/msm_sdhci.txt
>  create mode 100644 drivers/mmc/msm_sdhci.c

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

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

* [U-Boot] [PATCH v1 04/16] ehci-hcd: Add init_after_reset
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 04/16] ehci-hcd: Add init_after_reset Mateusz Kulikowski
@ 2016-01-11 16:57   ` Simon Glass
  0 siblings, 0 replies; 49+ messages in thread
From: Simon Glass @ 2016-01-11 16:57 UTC (permalink / raw)
  To: u-boot

On 6 January 2016 at 11:21, Mateusz Kulikowski
<mateusz.kulikowski@gmail.com> wrote:
> Some host controllers need addidional initialization after ehci_reset()
> In non-dm implementation it is possible to use CONFIG_EHCI_HCD_INIT_AFTER_RESET.
> This patch adds similar option to ehci drivers using dm.
>
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> Acked-by: Marek Vasut <marex@denx.de>
> Reviewed-by: Tom Rini <trini@konsulko.com>
> ---
>
> Changes in v1:
> - No changes, just added Acked-by, Reviewed-by
>
>  drivers/usb/host/ehci-hcd.c | 6 ++++++
>  drivers/usb/host/ehci.h     | 1 +
>  2 files changed, 7 insertions(+)

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

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

* [U-Boot] [PATCH v1 11/16] spmi: Add sandbox test driver
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 11/16] spmi: Add sandbox test driver Mateusz Kulikowski
@ 2016-01-11 16:57   ` Simon Glass
  0 siblings, 0 replies; 49+ messages in thread
From: Simon Glass @ 2016-01-11 16:57 UTC (permalink / raw)
  To: u-boot

On 6 January 2016 at 11:21, Mateusz Kulikowski
<mateusz.kulikowski@gmail.com> wrote:
> This patch adds emulated spmi bus controller with part of
> pm8916 pmic on it to sandbox and tests validating SPMI uclass.
>
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> ---
>
> Changes in v1: None
>
>  arch/sandbox/dts/sandbox.dts                   |  20 ++++
>  configs/sandbox_defconfig                      |   4 +
>  doc/device-tree-bindings/spmi/spmi-sandbox.txt |  34 ++++++
>  drivers/spmi/Kconfig                           |   8 ++
>  drivers/spmi/Makefile                          |   1 +
>  drivers/spmi/spmi-sandbox.c                    | 157 +++++++++++++++++++++++++
>  test/dm/Makefile                               |   1 +
>  test/dm/spmi.c                                 | 115 ++++++++++++++++++
>  8 files changed, 340 insertions(+)
>  create mode 100644 doc/device-tree-bindings/spmi/spmi-sandbox.txt
>  create mode 100644 drivers/spmi/spmi-sandbox.c
>  create mode 100644 test/dm/spmi.c

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

Looks nice. Nits below.

>
> diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
> index d2addb4..ff37283 100644
> --- a/arch/sandbox/dts/sandbox.dts
> +++ b/arch/sandbox/dts/sandbox.dts
> @@ -239,6 +239,26 @@
>                 status = "disabled";
>         };
>
> +       spmi: spmi at 0 {
> +               compatible = "sandbox,spmi";
> +               #address-cells = <0x1>;
> +               #size-cells = <0x1>;
> +               pm8916 at 0 {
> +                       compatible = "qcom,spmi-pmic";
> +                       reg = <0x0 0x1>;
> +                       #address-cells = <0x1>;
> +                       #size-cells = <0x1>;
> +
> +                       spmi_gpios: gpios at c000 {
> +                               compatible = "qcom,pm8916-gpio";
> +                               reg = <0xc000 0x400>;
> +                               gpio-controller;
> +                               gpio-count = <4>;
> +                               #gpio-cells = <2>;
> +                               gpio-bank-name="spmi";
> +                       };
> +               };
> +       };
>  };
>
>  #include "cros-ec-keyboard.dtsi"
> diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
> index 731fc25..0b4ce7b 100644
> --- a/configs/sandbox_defconfig
> +++ b/configs/sandbox_defconfig
> @@ -30,6 +30,7 @@ CONFIG_ADC=y
>  CONFIG_ADC_SANDBOX=y
>  CONFIG_CLK=y
>  CONFIG_SANDBOX_GPIO=y
> +CONFIG_PM8916_GPIO=y
>  CONFIG_SYS_I2C_SANDBOX=y
>  CONFIG_CROS_EC_KEYB=y
>  CONFIG_LED=y
> @@ -58,6 +59,9 @@ CONFIG_PINCONF=y
>  CONFIG_PINCTRL_SANDBOX=y
>  CONFIG_DM_PMIC=y
>  CONFIG_DM_PMIC_SANDBOX=y
> +CONFIG_PMIC_PM8916=y
> +CONFIG_DM_SPMI=y
> +CONFIG_SPMI_SANDBOX=y
>  CONFIG_DM_REGULATOR=y
>  CONFIG_DM_REGULATOR_SANDBOX=y
>  CONFIG_RAM=y
> diff --git a/doc/device-tree-bindings/spmi/spmi-sandbox.txt b/doc/device-tree-bindings/spmi/spmi-sandbox.txt
> new file mode 100644
> index 0000000..f120b99
> --- /dev/null
> +++ b/doc/device-tree-bindings/spmi/spmi-sandbox.txt
> @@ -0,0 +1,34 @@
> +Sandbox SPMI emulated arbiter.
> +
> +This is bus driver for Sandbox. It includes part of emulated pm8916 pmic.
> +
> +Required properties:
> +- compatible: "sandbox,spmi"
> +- #address-cells: 0x1 - childs slave ID address
> +- #size-cells: 0x1
> +
> +Optional properties (if not set by parent):
> +Child nodes (as in example)
> +
> +Example:
> +
> +spmi: spmi at 0 {
> +       compatible = "sandbox,spmi";
> +       #address-cells = <0x1>;
> +       #size-cells = <0x1>;
> +       pm8916 at 0 {
> +               compatible = "qcom,spmi-pmic";
> +               reg = <0x0 0x1>;
> +               #address-cells = <0x1>;
> +               #size-cells = <0x1>;
> +
> +               spmi_gpios: gpios at c000 {
> +                       compatible = "qcom,pm8916-gpio";
> +                       reg = <0xc000 0x400>;
> +                       gpio-controller;
> +                       gpio-count = <4>;
> +                       #gpio-cells = <2>;
> +                       gpio-bank-name="spmi";
> +               };
> +       };
> +};
> diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
> index 440431a..e3e8216 100644
> --- a/drivers/spmi/Kconfig
> +++ b/drivers/spmi/Kconfig
> @@ -7,4 +7,12 @@ config DM_SPMI
>           Select this to enable to support SPMI bus.
>           SPMI (System Power Management Interface) bus is used
>           to connect PMIC devices on various SoCs.
> +
> +config SPMI_SANDBOX
> +       boolean "Support for Sandbox SPMI bus"
> +       depends on DM_SPMI
> +       ---help---
> +         Demo SPMI bus implementation. Emulates part of PM8916 as single
> +          slave (0) on bus. It has 4 GPIO peripherals, pid 0xC0-0xC3.
> +
>  endmenu
> diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
> index 2015b1a..035d466 100644
> --- a/drivers/spmi/Makefile
> +++ b/drivers/spmi/Makefile
> @@ -5,3 +5,4 @@
>  #
>
>  obj-$(CONFIG_DM_SPMI)  += spmi-uclass.o
> +obj-$(CONFIG_SPMI_SANDBOX) += spmi-sandbox.o
> diff --git a/drivers/spmi/spmi-sandbox.c b/drivers/spmi/spmi-sandbox.c
> new file mode 100644
> index 0000000..7e67a40
> --- /dev/null
> +++ b/drivers/spmi/spmi-sandbox.c
> @@ -0,0 +1,157 @@
> +/*
> + * Sample SPMI bus driver
> + *
> + * It emulates bus with single pm8916-like pmic that has only GPIO reigsters.
> + *
> + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <spmi/spmi.h>
> +#include <asm/gpio.h>
> +#include <asm/io.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define EMUL_GPIO_PID_START 0xC0
> +#define EMUL_GPIO_PID_END   0xC3
> +
> +#define EMUL_GPIO_COUNT 4
> +
> +#define EMUL_GPIO_REG_END 0x46 /* Last valid register */
> +
> +#define EMUL_PERM_R 0x1
> +#define EMUL_PERM_W 0x2
> +#define EMUL_PERM_RW (EMUL_PERM_R | EMUL_PERM_W)
> +
> +struct sandbox_emul_fake_regs {
> +       u8 value;
> +       u8 access_mask;
> +       u8 perms; /* Access permissions */
> +};
> +
> +struct sandbox_emul_gpio {
> +       struct sandbox_emul_fake_regs r[EMUL_GPIO_REG_END]; /* Fake registers */
> +};
> +
> +struct sandbox_spmi_priv {
> +       struct sandbox_emul_gpio gpios[EMUL_GPIO_COUNT];
> +};
> +
> +/* Check if valid register was requested */
> +static bool check_address_valid(int usid, int pid, int off)
> +{
> +       if (usid != 0)
> +               return false;
> +       if (pid < EMUL_GPIO_PID_START || pid > EMUL_GPIO_PID_END)
> +               return false;
> +       if (off > EMUL_GPIO_REG_END)
> +               return false;
> +       return true;
> +}
> +
> +static int sandbox_spmi_write(struct udevice *dev, int usid, int pid, int off,
> +                         uint8_t val)
> +{
> +       struct sandbox_spmi_priv *p = dev_get_priv(dev);

s/p/priv/

> +       struct sandbox_emul_fake_regs *r;

s/r/regs/

please fix these globally

> +
> +       if (!check_address_valid(usid, pid, off))
> +               return -EIO;
> +
> +       r = p->gpios[pid & 0x3].r; /* Last 3 bits of pid are gpio # */
> +
> +       switch (off) {
> +       case 0x40: /* Control */
> +               val &= r[off].access_mask;
> +               if (((val & 0x30) == 0x10) || ((val & 0x30) == 0x20)) {
> +                       /* out/inout - set status register */
> +                       r[0x8].value &= ~0x1;
> +                       r[0x8].value |= val & 0x1;
> +               }
> +               break;
> +       default:
> +               if (r[off].perms & EMUL_PERM_W)
> +                       r[off].value = val & r[off].access_mask;
> +       }
> +       return 0;
> +}
> +
> +static int sandbox_spmi_read(struct udevice *dev, int usid, int pid, int off)
> +{
> +       struct sandbox_spmi_priv *p = dev_get_priv(dev);
> +       struct sandbox_emul_fake_regs *r;
> +
> +       if (!check_address_valid(usid, pid, off))
> +               return -EIO;
> +
> +       r = p->gpios[pid & 0x3].r; /* Last 3 bits of pid are gpio # */
> +
> +       if (r[0x46].value == 0) /* Block disabled */
> +               return 0;
> +
> +       switch (off) {
> +       case 0x8: /* Status */
> +               if (r[0x46].value == 0) /* Block disabled */
> +                       return 0;
> +               return r[off].value;
> +       default:
> +               if (r[off].perms & EMUL_PERM_R)
> +                       return r[off].value;
> +               else
> +                       return 0;
> +       }
> +}
> +
> +static struct dm_spmi_ops sandbox_spmi_ops = {
> +       .read = sandbox_spmi_read,
> +       .write = sandbox_spmi_write,
> +};
> +
> +static int sandbox_spmi_probe(struct udevice *dev)
> +{
> +       struct sandbox_spmi_priv *p = dev_get_priv(dev);
> +       int i;
> +
> +       for (i = 0; i < EMUL_GPIO_COUNT; ++i) {
> +               struct sandbox_emul_fake_regs *r = p->gpios[i].r;
> +               r[4].perms = EMUL_PERM_R;
> +               r[4].value = 0x10;
> +               r[5].perms = EMUL_PERM_R;
> +               r[5].value = 0x5;
> +               r[8].access_mask = 0x81;
> +               r[8].perms = EMUL_PERM_RW;
> +               r[0x40].access_mask = 0x7F;
> +               r[0x40].perms = EMUL_PERM_RW;
> +               r[0x41].access_mask = 7;
> +               r[0x41].perms = EMUL_PERM_RW;
> +               r[0x42].access_mask = 7;
> +               r[0x42].perms = EMUL_PERM_RW;
> +               r[0x42].value = 0x4;
> +               r[0x45].access_mask = 0x3F;
> +               r[0x45].perms = EMUL_PERM_RW;
> +               r[0x45].value = 0x1;
> +               r[0x46].access_mask = 0x80;
> +               r[0x46].perms = EMUL_PERM_RW;
> +               r[0x46].value = 0x80;
> +       }
> +       return 0;
> +}
> +
> +static const struct udevice_id sandbox_spmi_ids[] = {
> +       { .compatible = "sandbox,spmi" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(msm_spmi) = {
> +       .name = "sandbox_spmi",
> +       .id = UCLASS_SPMI,
> +       .of_match = sandbox_spmi_ids,
> +       .ops = &sandbox_spmi_ops,
> +       .probe = sandbox_spmi_probe,
> +       .priv_auto_alloc_size = sizeof(struct sandbox_spmi_priv),
> +};
> diff --git a/test/dm/Makefile b/test/dm/Makefile
> index 681c6ae..178bd5e 100644
> --- a/test/dm/Makefile
> +++ b/test/dm/Makefile
> @@ -35,4 +35,5 @@ obj-$(CONFIG_DM_PMIC) += pmic.o
>  obj-$(CONFIG_DM_REGULATOR) += regulator.o
>  obj-$(CONFIG_TIMER) += timer.o
>  obj-$(CONFIG_ADC) += adc.o
> +obj-$(CONFIG_DM_SPMI) += spmi.o
>  endif
> diff --git a/test/dm/spmi.c b/test/dm/spmi.c
> new file mode 100644
> index 0000000..81767f6
> --- /dev/null
> +++ b/test/dm/spmi.c
> @@ -0,0 +1,115 @@
> +/*
> + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <fdtdec.h>
> +#include <dm.h>
> +#include <dm/device.h>
> +#include <dm/root.h>
> +#include <dm/test.h>
> +#include <dm/util.h>
> +#include <power/pmic.h>
> +#include <spmi/spmi.h>
> +#include <asm/gpio.h>
> +#include <test/ut.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* Test if bus childs got probed propperly*/
> +static int dm_test_spmi_probe(struct unit_test_state *uts)
> +{
> +       const char *name = "spmi at 0";
> +       struct udevice *bus, *dev;
> +
> +       ut_assertok(uclass_get_device(UCLASS_SPMI, 0, &bus));
> +
> +       /* Check bus name */
> +       ut_asserteq_str(name, bus->name);
> +
> +       /* Check that it has some devices */
> +       ut_asserteq(device_has_children(bus), true);
> +
> +       ut_assertok(device_find_first_child(bus, &dev));
> +
> +       /* There should be at least one child */
> +       ut_assertnonnull(dev);
> +
> +       /* Check that only PMICs are connected to the bus */
> +       while (dev) {
> +               ut_asserteq(device_get_uclass_id(dev), UCLASS_PMIC);
> +               device_find_next_child(&dev);
> +       }
> +
> +       return 0;
> +}
> +DM_TEST(dm_test_spmi_probe, DM_TESTF_SCAN_FDT);
> +
> +/* Test if it's possible to read bus directly and indirectly */
> +static int dm_test_spmi_access(struct unit_test_state *uts)
> +{
> +       const char *pmic_name = "pm8916 at 0";
> +       struct udevice *bus, *pmic;
> +
> +       ut_assertok(uclass_get_device(UCLASS_SPMI, 0, &bus));
> +
> +       ut_assertok(device_get_child(bus, 0, &pmic));
> +
> +       /* Sanity check if it's proper PMIC */
> +       ut_asserteq_str(pmic_name, pmic->name);
> +
> +       /* Read PMIC ID reg using SPMI bus - it assumes it has slaveID == 0*/
> +       ut_asserteq(spmi_reg_read(bus, 0, 0xC0, 0x4), 0x10);
> +       ut_asserteq(spmi_reg_read(bus, 0, 0xC0, 0x5), 0x5);
> +
> +       /* Read ID reg via pmic interface */
> +       ut_asserteq(pmic_reg_read(pmic, 0xC004), 0x10);
> +       ut_asserteq(pmic_reg_read(pmic, 0xC005), 0x5);
> +
> +       return 0;
> +}
> +DM_TEST(dm_test_spmi_access, DM_TESTF_SCAN_FDT);
> +
> +
> +/* Test if it's possible to access GPIO that should be in pmic */
> +static int dm_test_spmi_access_peripheral(struct unit_test_state *uts)
> +{
> +       struct udevice *dev;
> +       unsigned int offset, gpio;
> +       const char *name;
> +       int offset_count;
> +
> +       /* Get second pin of PMIC GPIO */
> +       ut_assertok(gpio_lookup_name("spmi1", &dev, &offset, &gpio));
> +
> +       /* Check if PMIC is parent */
> +       ut_asserteq(device_get_uclass_id(dev->parent), UCLASS_PMIC);
> +
> +       /* This should be second gpio */
> +       ut_asserteq(1, offset);
> +
> +       name = gpio_get_bank_info(dev, &offset_count);
> +
> +       /* Check bank name */
> +       ut_asserteq_str("spmi", name);
> +       /* Check pin count */
> +       ut_asserteq(4, offset_count);
> +
> +       ut_assertok(gpio_request(gpio, "testing"));
> +
> +       /* Try to set/clear gpio */
> +       ut_assertok(gpio_direction_output(gpio, 0));
> +       ut_asserteq(gpio_get_value(gpio), 0);
> +       ut_assertok(gpio_direction_output(gpio, 1));
> +       ut_asserteq(gpio_get_value(gpio), 1);
> +       ut_assertok(gpio_direction_input(gpio));
> +       ut_asserteq(gpio_get_value(gpio), 1);
> +
> +       ut_assertok(gpio_free(gpio));
> +
> +       return 0;
> +}
> +DM_TEST(dm_test_spmi_access_peripheral, DM_TESTF_SCAN_FDT);
> +
> --
> 2.5.0
>

This is a really nice test.

Regards,
Simon

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

* [U-Boot] [PATCH v1 10/16] drivers: Add SPMI bus uclass
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 10/16] drivers: Add SPMI bus uclass Mateusz Kulikowski
@ 2016-01-11 16:57   ` Simon Glass
  2016-01-11 21:41     ` Mateusz Kulikowski
  0 siblings, 1 reply; 49+ messages in thread
From: Simon Glass @ 2016-01-11 16:57 UTC (permalink / raw)
  To: u-boot

Hi Mateusz,

On 6 January 2016 at 11:21, Mateusz Kulikowski
<mateusz.kulikowski@gmail.com> wrote:
> Qualcom processors use proprietary bus to talk with PMIC devices -
> SPMI (System Power Management Interface).
>
> On wiring level it is similar to I2C, but on protocol level, it's
> multi-master and has simple autodetection capabilities.
> This commit adds simple uclass that provides bus read/write interface.
>
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> ---
>
> Changes in v1:
> - Reorder includes
> - Add read/write arguments documentation
>
>  drivers/Kconfig            |  2 ++
>  drivers/Makefile           |  1 +
>  drivers/spmi/Kconfig       | 10 ++++++++++
>  drivers/spmi/Makefile      |  7 +++++++
>  drivers/spmi/spmi-uclass.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++
>  include/dm/uclass-id.h     |  1 +
>  include/spmi/spmi.h        | 47 +++++++++++++++++++++++++++++++++++++++++++++
>  7 files changed, 116 insertions(+)
>  create mode 100644 drivers/spmi/Kconfig
>  create mode 100644 drivers/spmi/Makefile
>  create mode 100644 drivers/spmi/spmi-uclass.c
>  create mode 100644 include/spmi/spmi.h
>

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

with nits...

> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index c481e93..4cbe976 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -52,6 +52,8 @@ source "drivers/remoteproc/Kconfig"
>
>  source "drivers/rtc/Kconfig"
>
> +source "drivers/spmi/Kconfig"
> +

spmi comes after sound, so please move it down a bit.

>  source "drivers/serial/Kconfig"
>
>  source "drivers/sound/Kconfig"
> diff --git a/drivers/Makefile b/drivers/Makefile
> index c9031f2..7ae72c0 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -53,6 +53,7 @@ obj-y += pcmcia/
>  obj-y += dfu/
>  obj-y += rtc/
>  obj-y += sound/
> +obj-y += spmi/

like you have here

>  obj-y += timer/
>  obj-y += tpm/
>  obj-y += twserial/
> diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
> new file mode 100644
> index 0000000..440431a
> --- /dev/null
> +++ b/drivers/spmi/Kconfig
> @@ -0,0 +1,10 @@
> +menu "SPMI support"
> +
> +config DM_SPMI

Can we just use SPMI, or is that is use? We want to remove all the DM_
options when everything is converted to driver model. So if you are
adding a new class you should be able to avoid the DM_ prefix.

> +       bool "Enable SPMI bus support"
> +       depends on DM
> +       ---help---
> +         Select this to enable to support SPMI bus.
> +         SPMI (System Power Management Interface) bus is used
> +         to connect PMIC devices on various SoCs.
> +endmenu
> diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
> new file mode 100644
> index 0000000..2015b1a
> --- /dev/null
> +++ b/drivers/spmi/Makefile
> @@ -0,0 +1,7 @@
> +#
> +# (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> +#
> +# SPDX-License-Identifier:     GPL-2.0+
> +#
> +
> +obj-$(CONFIG_DM_SPMI)  += spmi-uclass.o
> diff --git a/drivers/spmi/spmi-uclass.c b/drivers/spmi/spmi-uclass.c
> new file mode 100644
> index 0000000..7d5429a
> --- /dev/null
> +++ b/drivers/spmi/spmi-uclass.c
> @@ -0,0 +1,48 @@
> +/*
> + * SPMI bus uclass driver
> + *
> + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/root.h>
> +#include <errno.h>
> +#include <spmi/spmi.h>
> +#include <linux/ctype.h>

http://www.denx.de/wiki/U-Boot/CodingStyle

common.h
dm.h
errno.h
dm/...
spmi/...
linux/...

> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +int spmi_reg_read(struct udevice *dev, int usid, int pid, int reg)
> +{
> +       const struct dm_spmi_ops *ops = dev_get_driver_ops(dev);
> +
> +       if (!ops || !ops->read)
> +               return -ENOSYS;
> +
> +       return ops->read(dev, usid, pid, reg);
> +}
> +
> +int spmi_reg_write(struct udevice *dev, int usid, int pid, int reg,
> +                  uint8_t value)
> +{
> +       const struct dm_spmi_ops *ops = dev_get_driver_ops(dev);
> +
> +       if (!ops || !ops->write)
> +               return -ENOSYS;
> +
> +       return ops->write(dev, usid, pid, reg, value);
> +}
> +
> +static int spmi_post_bind(struct udevice *dev)
> +{
> +       return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
> +}
> +
> +UCLASS_DRIVER(spmi) = {
> +       .id             = UCLASS_SPMI,
> +       .name           = "spmi",
> +       .post_bind      = spmi_post_bind,
> +};
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index 27fa0b6..772e780 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -57,6 +57,7 @@ enum uclass_id {
>         UCLASS_RTC,             /* Real time clock device */
>         UCLASS_SERIAL,          /* Serial UART */
>         UCLASS_SPI,             /* SPI bus */
> +       UCLASS_SPMI,            /* System Power Management Interface bus */
>         UCLASS_SPI_FLASH,       /* SPI flash */
>         UCLASS_SPI_GENERIC,     /* Generic SPI flash target */
>         UCLASS_SYSCON,          /* System configuration device */
> diff --git a/include/spmi/spmi.h b/include/spmi/spmi.h
> new file mode 100644
> index 0000000..65a49bd
> --- /dev/null
> +++ b/include/spmi/spmi.h
> @@ -0,0 +1,47 @@
> +#ifndef _SPMI_SPMI_H
> +#define _SPMI_SPMI_H
> +
> +/**
> + * struct dm_spmi_ops - SPMI device I/O interface
> + *
> + * Should be implemented by UCLASS_SPMI device drivers. The standard
> + * device operations provides the I/O interface for it's childs.
> + *
> + * @read:      read register 'reg' of slave 'usid' and peripheral 'pid'
> + * @write:     write register 'reg' of slave 'usid' and peripheral 'pid'
> + *
> + * Each register is 8-bit, both read and write can return negative values
> + * on error.
> + */
> +struct dm_spmi_ops {
> +       int (*read)(struct udevice *dev, int usid, int pid, int reg);
> +       int (*write)(struct udevice *dev, int usid, int pid, int reg,
> +                    uint8_t value);
> +};
> +
> +/**
> + * spmi_reg_read() - read a register from specific slave/peripheral
> + *
> + * @dev:       SPMI bus to read
> + * @usid       SlaveID
> + * @pid                Peripheral ID
> + * @reg:       Register to read
> + * @return value read on success or negative value of errno.
> + */
> +int spmi_reg_read(struct udevice *dev, int usid, int pid, int reg);
> +
> +/**
> + * spmi_reg_write() - write a register of specific slave/peripheral
> + *
> + * @dev:       SPMI bus to write
> + * @usid       SlaveID
> + * @pid                Peripheral ID
> + * @reg:       Register to write
> + * @value:     Value to write
> + * @return 0 on success or negative value of errno.
> + */
> +int spmi_reg_write(struct udevice *dev, int usid, int pid, int reg,
> +                  uint8_t value);
> +
> +#endif
> +
> --
> 2.5.0
>

Regards,
Simon

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

* [U-Boot] [PATCH v1 12/16] drivers: spmi: Add support for Qualcomm SPMI bus driver
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 12/16] drivers: spmi: Add support for Qualcomm SPMI bus driver Mateusz Kulikowski
@ 2016-01-11 16:57   ` Simon Glass
  0 siblings, 0 replies; 49+ messages in thread
From: Simon Glass @ 2016-01-11 16:57 UTC (permalink / raw)
  To: u-boot

On 6 January 2016 at 11:21, Mateusz Kulikowski
<mateusz.kulikowski@gmail.com> wrote:
> Support SPMI arbiter on Qualcomm Snapdragon devices.
>
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> ---
>
> Changes in v1:
> - add binding documentation and better Kconfig help
> - Changed a bit mapping
> - Change include order
> - Use clrsetbits* where possible
> - Add one more supported dts id
> - Handle missing fields in dt properly
>
>  doc/device-tree-bindings/spmi/spmi-msm.txt |  26 ++++
>  drivers/spmi/Kconfig                       |   7 +-
>  drivers/spmi/Makefile                      |   1 +
>  drivers/spmi/spmi-msm.c                    | 188 +++++++++++++++++++++++++++++
>  4 files changed, 221 insertions(+), 1 deletion(-)
>  create mode 100644 doc/device-tree-bindings/spmi/spmi-msm.txt
>  create mode 100644 drivers/spmi/spmi-msm.c
>

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

> diff --git a/doc/device-tree-bindings/spmi/spmi-msm.txt b/doc/device-tree-bindings/spmi/spmi-msm.txt
> new file mode 100644
> index 0000000..ae47673
> --- /dev/null
> +++ b/doc/device-tree-bindings/spmi/spmi-msm.txt
> @@ -0,0 +1,26 @@
> +Qualcomm SPMI arbiter/bus driver
> +
> +This is bus driver for Qualcomm chips that use SPMI to communicate with PMICs.
> +
> +Required properties:
> +- compatible: "qcom,spmi-pmic-arb"
> +- reg: Register block adresses and sizes for various parts of device:
> +   1) PMIC arbiter channel mapping base (PMIC_ARB_REG_CHNLn)
> +   2) SPMI write command (master) registers (PMIC_ARB_CORE_SW_DEC_CHANNELS)
> +   3) SPMI read command (observer) registers (PMIC_ARB_CORE_REGISTERS_OBS)
> +
> +Optional properties (if not set by parent):
> +- #address-cells: 0x1 - childs slave ID address
> +- #size-cells: 0x1
> +
> +All PMICs should be placed as a child nodes of bus arbiter.
> +Automatic detection of childs is currently not supported.
> +
> +Example:
> +
> +spmi at 200f000 {
> +       compatible = "qcom,spmi-pmic-arb";
> +       reg = <0x200f800 0x200 0x2400000 0x400000 0x2c00000 0x400000>;
> +       #address-cells = <0x1>;
> +       #size-cells = <0x1>;
> +};
> diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
> index e3e8216..9632b14 100644
> --- a/drivers/spmi/Kconfig
> +++ b/drivers/spmi/Kconfig
> @@ -8,11 +8,16 @@ config DM_SPMI
>           SPMI (System Power Management Interface) bus is used
>           to connect PMIC devices on various SoCs.
>
> +config SPMI_MSM
> +       boolean "Support Qualcomm SPMI bus"
> +       depends on DM_SPMI
> +       ---help---
> +         Support SPMI bus implementation found on Qualcomm Snapdragon SoCs.
> +
>  config SPMI_SANDBOX
>         boolean "Support for Sandbox SPMI bus"
>         depends on DM_SPMI
>         ---help---
>           Demo SPMI bus implementation. Emulates part of PM8916 as single
>            slave (0) on bus. It has 4 GPIO peripherals, pid 0xC0-0xC3.
> -
>  endmenu
> diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
> index 035d466..caad96f 100644
> --- a/drivers/spmi/Makefile
> +++ b/drivers/spmi/Makefile
> @@ -5,4 +5,5 @@
>  #
>
>  obj-$(CONFIG_DM_SPMI)  += spmi-uclass.o
> +obj-$(CONFIG_SPMI_MSM) += spmi-msm.o
>  obj-$(CONFIG_SPMI_SANDBOX) += spmi-sandbox.o
> diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c
> new file mode 100644
> index 0000000..c1e7a3d
> --- /dev/null
> +++ b/drivers/spmi/spmi-msm.c
> @@ -0,0 +1,188 @@
> +/*
> + * Qualcomm SPMI bus driver
> + *
> + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> + *
> + * Loosely based on Little Kernel driver
> + *
> + * SPDX-License-Identifier:    BSD-3-Clause
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <fdtdec.h>
> +#include <spmi/spmi.h>
> +#include <asm/io.h>

swap those two lines

> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define ARB_CHANNEL_OFFSET(n)          (0x4 * (n))
> +#define SPMI_CH_OFFSET(chnl)           ((chnl) * 0x8000)
> +
> +#define SPMI_REG_CMD0                  0x0
> +#define SPMI_REG_CONFIG                        0x4
> +#define SPMI_REG_STATUS                        0x8
> +#define SPMI_REG_WDATA                 0x10
> +#define SPMI_REG_RDATA                 0x18
> +
> +#define SPMI_CMD_OPCODE_SHIFT          27
> +#define SPMI_CMD_SLAVE_ID_SHIFT                20
> +#define SPMI_CMD_ADDR_SHIFT            12
> +#define SPMI_CMD_ADDR_OFFSET_SHIFT     4
> +#define SPMI_CMD_BYTE_CNT_SHIFT                0
> +
> +#define SPMI_CMD_EXT_REG_WRITE_LONG    0x00
> +#define SPMI_CMD_EXT_REG_READ_LONG     0x01
> +
> +#define SPMI_STATUS_DONE               0x1
> +
> +#define SPMI_MAX_CHANNELS      128
> +#define SPMI_MAX_SLAVES                16
> +#define SPMI_MAX_PERIPH                256
> +
> +struct msm_spmi_priv {
> +       phys_addr_t arb_chnl; /* ARB channel mapping base */
> +       phys_addr_t spmi_core; /* SPMI core */
> +       phys_addr_t spmi_obs; /* SPMI observer */
> +       /* SPMI channel map */
> +       uint8_t channel_map[SPMI_MAX_SLAVES][SPMI_MAX_PERIPH];
> +};
> +
> +static int msm_spmi_write(struct udevice *dev, int usid, int pid, int off,
> +                         uint8_t val)
> +{
> +       struct msm_spmi_priv *p = dev_get_priv(dev);
> +       unsigned channel;
> +       uint32_t reg = 0;
> +
> +       if (usid >= SPMI_MAX_SLAVES)
> +               return -EIO;
> +       if (pid >= SPMI_MAX_PERIPH)
> +               return -EIO;
> +
> +       channel = p->channel_map[usid][pid];
> +
> +       /* Disable IRQ mode for the current channel*/
> +       writel(0x0, p->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_CONFIG);
> +
> +       /* Write single byte */
> +       writel(val, p->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_WDATA);
> +
> +       /* Prepare write command */
> +       reg |= SPMI_CMD_EXT_REG_WRITE_LONG << SPMI_CMD_OPCODE_SHIFT;
> +       reg |= (usid << SPMI_CMD_SLAVE_ID_SHIFT);
> +       reg |= (pid << SPMI_CMD_ADDR_SHIFT);
> +       reg |= (off << SPMI_CMD_ADDR_OFFSET_SHIFT);
> +       reg |= 1; /* byte count */
> +
> +       /* Send write command */
> +       writel(reg, p->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_CMD0);
> +
> +       /* Wait till CMD DONE status */
> +       reg = 0;
> +       while (!reg) {
> +               reg = readl(p->spmi_core + SPMI_CH_OFFSET(channel) +
> +                           SPMI_REG_STATUS);
> +       }
> +
> +       if (reg ^ SPMI_STATUS_DONE) {
> +               printf("SPMI write failure.\n");
> +               return -EIO;
> +       }
> +
> +       return 0;
> +}
> +
> +static int msm_spmi_read(struct udevice *dev, int usid, int pid, int off)
> +{
> +       struct msm_spmi_priv *p = dev_get_priv(dev);

s/p/priv/

> +       unsigned channel;
> +       uint32_t reg = 0;
> +
> +       if (usid >= SPMI_MAX_SLAVES)
> +               return -EIO;
> +       if (pid >= SPMI_MAX_PERIPH)
> +               return -EIO;
> +
> +       channel = p->channel_map[usid][pid];
> +
> +       /* Disable IRQ mode for the current channel*/
> +       writel(0x0, p->spmi_obs + SPMI_CH_OFFSET(channel) + SPMI_REG_CONFIG);
> +
> +       /* Prepare read command */
> +       reg |= SPMI_CMD_EXT_REG_READ_LONG << SPMI_CMD_OPCODE_SHIFT;
> +       reg |= (usid << SPMI_CMD_SLAVE_ID_SHIFT);
> +       reg |= (pid << SPMI_CMD_ADDR_SHIFT);
> +       reg |= (off << SPMI_CMD_ADDR_OFFSET_SHIFT);
> +       reg |= 1; /* byte count */
> +
> +       /* Request read */
> +       writel(reg, p->spmi_obs + SPMI_CH_OFFSET(channel) + SPMI_REG_CMD0);
> +
> +       /* Wait till CMD DONE status */
> +       reg = 0;
> +       while (!reg) {
> +               reg = readl(p->spmi_obs + SPMI_CH_OFFSET(channel) +
> +                           SPMI_REG_STATUS);
> +       }
> +
> +       if (reg ^ SPMI_STATUS_DONE) {
> +               printf("SPMI read failure.\n");
> +               return -EIO;
> +       }
> +
> +       /* Read the data */
> +       return readl(p->spmi_obs + SPMI_CH_OFFSET(channel) + SPMI_REG_RDATA) &
> +                       0xFF;
> +}
> +
> +static struct dm_spmi_ops msm_spmi_ops = {
> +       .read = msm_spmi_read,
> +       .write = msm_spmi_write,
> +};
> +
> +static int msm_spmi_probe(struct udevice *dev)
> +{
> +       struct udevice *parent = dev->parent;
> +       struct msm_spmi_priv *priv = dev_get_priv(dev);
> +       int i;
> +
> +       priv->arb_chnl = dev_get_addr(dev);
> +       priv->spmi_core = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
> +                                                          parent->of_offset,
> +                                                          dev->of_offset,
> +                                                          "reg", 1, NULL);
> +       priv->spmi_obs = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
> +                                                         parent->of_offset,
> +                                                         dev->of_offset, "reg",
> +                                                         2, NULL);
> +       if (priv->arb_chnl == FDT_ADDR_T_NONE ||
> +           priv->spmi_core == FDT_ADDR_T_NONE ||
> +           priv->spmi_obs == FDT_ADDR_T_NONE)
> +               return -EINVAL;
> +
> +       /* Scan peripherals connected to each SPMI channel */
> +       for (i = 0; i < SPMI_MAX_CHANNELS ; i++) {

BTW index variables like 'i' are fine as single character.

> +               uint32_t periph = readl(priv->arb_chnl + ARB_CHANNEL_OFFSET(i));
> +               uint8_t slave_id = (periph & 0xf0000) >> 16;
> +               uint8_t pid = (periph & 0xff00) >> 8;
> +
> +               priv->channel_map[slave_id][pid] = i;
> +       }
> +       return 0;
> +}
> +
> +static const struct udevice_id msm_spmi_ids[] = {
> +       { .compatible = "qcom,spmi-pmic-arb" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(msm_spmi) = {
> +       .name = "msm_spmi",
> +       .id = UCLASS_SPMI,
> +       .of_match = msm_spmi_ids,
> +       .ops = &msm_spmi_ops,
> +       .probe = msm_spmi_probe,
> +       .priv_auto_alloc_size = sizeof(struct msm_spmi_priv),
> +};
> --
> 2.5.0
>

Regards,
Simon

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

* [U-Boot] [PATCH v1 13/16] pmic: Add support for Qualcomm PM8916 PMIC
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 13/16] pmic: Add support for Qualcomm PM8916 PMIC Mateusz Kulikowski
@ 2016-01-11 16:58   ` Simon Glass
  0 siblings, 0 replies; 49+ messages in thread
From: Simon Glass @ 2016-01-11 16:58 UTC (permalink / raw)
  To: u-boot

On 6 January 2016 at 11:21, Mateusz Kulikowski
<mateusz.kulikowski@gmail.com> wrote:
> This PMIC is connected on SPMI bus so needs SPMI support enabled.
>
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> ---
>
> Changes in v1:
> - Added dt bindings
> - Reoder includes
> - Replaced extract_* macros with ordinary shift/mask
> - Added error checking and whitespaces in probe
>
>  doc/device-tree-bindings/pmic/pm8916.txt | 18 ++++++
>  drivers/power/pmic/Kconfig               | 14 +++++
>  drivers/power/pmic/Makefile              |  1 +
>  drivers/power/pmic/pm8916.c              | 96 ++++++++++++++++++++++++++++++++
>  4 files changed, 129 insertions(+)
>  create mode 100644 doc/device-tree-bindings/pmic/pm8916.txt
>  create mode 100644 drivers/power/pmic/pm8916.c

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

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

* [U-Boot] [PATCH v1 14/16] gpio: Add support for Qualcomm PM8916 gpios
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 14/16] gpio: Add support for Qualcomm PM8916 gpios Mateusz Kulikowski
@ 2016-01-11 16:58   ` Simon Glass
  0 siblings, 0 replies; 49+ messages in thread
From: Simon Glass @ 2016-01-11 16:58 UTC (permalink / raw)
  To: u-boot

On 6 January 2016 at 11:21, Mateusz Kulikowski
<mateusz.kulikowski@gmail.com> wrote:
> This driver supports GPIOs present on PM8916 PMIC.
> There are 2 device drivers inside:
> - GPIO driver (4 "generic" GPIOs)
> - Keypad driver that presents itself as GPIO with 2 inputs (power and reset)
>
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> ---
>
> Changes in v1:
> - Add binding doc
> - Fixed inlcude ordering
> - Merged direction_input and direction_output functions
> - gpio_get: use switch instead of stacked if
> - use pmic_clrsetbits
> - add possibility to change prwkey bank name
> - Handle invalid bindings
> - Sanity HW check (i.e. check type/subtype registers)
>
>  doc/device-tree-bindings/gpio/pm8916_gpio.txt |  48 ++++
>  drivers/gpio/Kconfig                          |  10 +
>  drivers/gpio/Makefile                         |   1 +
>  drivers/gpio/pm8916_gpio.c                    | 302 ++++++++++++++++++++++++++
>  4 files changed, 361 insertions(+)
>  create mode 100644 doc/device-tree-bindings/gpio/pm8916_gpio.txt
>  create mode 100644 drivers/gpio/pm8916_gpio.c

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

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

* [U-Boot] [PATCH v1 15/16] arm: Add support for Qualcomm Snapdragon family
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 15/16] arm: Add support for Qualcomm Snapdragon family Mateusz Kulikowski
@ 2016-01-11 16:58   ` Simon Glass
  0 siblings, 0 replies; 49+ messages in thread
From: Simon Glass @ 2016-01-11 16:58 UTC (permalink / raw)
  To: u-boot

On 6 January 2016 at 11:21, Mateusz Kulikowski
<mateusz.kulikowski@gmail.com> wrote:
> First supported chip is APQ8016 (that is compatible with MSM8916).
> Drivers in SoC code:
> - Reset controller (PSHOLD)
> - Clock controller (very simple clock configuration for MMC and UART)
>
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> ---
>
> Changes in v1:
> - Fix include order
> - Cleanup defines (added spaces for readibility)
> - Base address is integer to avoid casting
> - Use setbits_* family where possible
> - Drop unneded comments, added newlines where needed
> - Check return value of dev_get_addr
> - Add binding for apq8016
> - Cleaned up divider calculation
> - Drop most of gpio.h (only empty file is needed)

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

>
>  arch/arm/Kconfig                                   |  12 +
>  arch/arm/Makefile                                  |   1 +
>  arch/arm/mach-snapdragon/Kconfig                   |   6 +
>  arch/arm/mach-snapdragon/Makefile                  |   8 +
>  arch/arm/mach-snapdragon/clock-apq8016.c           | 262 +++++++++++++++++++++
>  arch/arm/mach-snapdragon/include/mach/gpio.h       |   9 +
>  .../mach-snapdragon/include/mach/sysmap-apq8016.h  |  14 ++
>  arch/arm/mach-snapdragon/reset.c                   |  40 ++++
>  8 files changed, 352 insertions(+)
>  create mode 100644 arch/arm/mach-snapdragon/Kconfig
>  create mode 100644 arch/arm/mach-snapdragon/Makefile
>  create mode 100644 arch/arm/mach-snapdragon/clock-apq8016.c
>  create mode 100644 arch/arm/mach-snapdragon/include/mach/gpio.h
>  create mode 100644 arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h
>  create mode 100644 arch/arm/mach-snapdragon/reset.c
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 9bd6cf1..0b68cb6 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -493,6 +493,16 @@ config OMAP54XX
>         select CPU_V7
>         select SUPPORT_SPL
>
> +config ARCH_SNAPDRAGON
> +       bool "Qualcomm Snapdragon SoCs"
> +       select ARM64
> +       select DM
> +       select DM_GPIO
> +       select DM_SERIAL
> +       select DM_SPMI
> +       select OF_CONTROL
> +       select OF_SEPARATE
> +
>  config RMOBILE
>         bool "Renesas ARM SoCs"
>         select CPU_V7
> @@ -749,6 +759,8 @@ source "arch/arm/mach-rockchip/Kconfig"
>
>  source "arch/arm/mach-s5pc1xx/Kconfig"
>
> +source "arch/arm/mach-snapdragon/Kconfig"
> +
>  source "arch/arm/mach-socfpga/Kconfig"
>
>  source "arch/arm/mach-tegra/Kconfig"
> diff --git a/arch/arm/Makefile b/arch/arm/Makefile
> index 18283d1..b977309 100644
> --- a/arch/arm/Makefile
> +++ b/arch/arm/Makefile
> @@ -54,6 +54,7 @@ machine-$(CONFIG_ARMADA_XP)           += mvebu
>  # TODO: rename CONFIG_ORION5X -> CONFIG_ARCH_ORION5X
>  machine-$(CONFIG_ORION5X)              += orion5x
>  machine-$(CONFIG_ARCH_S5PC1XX)         += s5pc1xx
> +machine-$(CONFIG_ARCH_SNAPDRAGON)      += snapdragon
>  machine-$(CONFIG_ARCH_SOCFPGA)         += socfpga
>  machine-$(CONFIG_ARCH_ROCKCHIP)                += rockchip
>  machine-$(CONFIG_TEGRA)                        += tegra
> diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig
> new file mode 100644
> index 0000000..156e733
> --- /dev/null
> +++ b/arch/arm/mach-snapdragon/Kconfig
> @@ -0,0 +1,6 @@
> +if ARCH_SNAPDRAGON
> +
> +config SYS_SOC
> +       default "snapdragon"
> +
> +endif
> diff --git a/arch/arm/mach-snapdragon/Makefile b/arch/arm/mach-snapdragon/Makefile
> new file mode 100644
> index 0000000..8e84705
> --- /dev/null
> +++ b/arch/arm/mach-snapdragon/Makefile
> @@ -0,0 +1,8 @@
> +#
> +# (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> +#
> +# SPDX-License-Identifier:     GPL-2.0+
> +#
> +
> +obj-y += clock-apq8016.o
> +obj-y += reset.o
> diff --git a/arch/arm/mach-snapdragon/clock-apq8016.c b/arch/arm/mach-snapdragon/clock-apq8016.c
> new file mode 100644
> index 0000000..360064e
> --- /dev/null
> +++ b/arch/arm/mach-snapdragon/clock-apq8016.c
> @@ -0,0 +1,262 @@
> +/*
> + * Clock drivers for Qualcomm APQ8016
> + *
> + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> + *
> + * Based on Little Kernel driver, simplified
> + *
> + * SPDX-License-Identifier:    BSD-3-Clause
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <asm/io.h>
> +#include <linux/bitops.h>
> +
> +/* GPLL0 clock control registers */
> +#define GPLL0_STATUS        0x2101C
> +#define GPLL0_STATUS_ACTIVE BIT(17)
> +
> +#define APCS_GPLL_ENA_VOTE  0x45000
> +#define APCS_GPLL_ENA_VOTE_GPLL0 BIT(0)
> +
> +/* vote reg for blsp1 clock */
> +#define APCS_CLOCK_BRANCH_ENA_VOTE  0x45004
> +#define APCS_CLOCK_BRANCH_ENA_VOTE_BLSP1 BIT(10)
> +
> +/* SDC(n) clock control registers; n=1,2 */
> +
> +/* block control register */
> +#define SDCC_BCR(n)                 ((n * 0x1000) + 0x41000)
> +/* cmd */
> +#define SDCC_CMD_RCGR(n)            ((n * 0x1000) + 0x41004)
> +/* cfg */
> +#define SDCC_CFG_RCGR(n)            ((n * 0x1000) + 0x41008)
> +/* m */
> +#define SDCC_M(n)                   ((n * 0x1000) + 0x4100C)
> +/* n */
> +#define SDCC_N(n)                   ((n * 0x1000) + 0x41010)
> +/* d */
> +#define SDCC_D(n)                   ((n * 0x1000) + 0x41014)
> +/* branch control */
> +#define SDCC_APPS_CBCR(n)           ((n * 0x1000) + 0x41018)
> +#define SDCC_AHB_CBCR(n)            ((n * 0x1000) + 0x4101C)
> +
> +/* BLSP1 AHB clock (root clock for BLSP) */
> +#define BLSP1_AHB_CBCR              0x1008
> +
> +/* Uart clock control registers */
> +#define BLSP1_UART2_BCR             0x3028
> +#define BLSP1_UART2_APPS_CBCR       0x302C
> +#define BLSP1_UART2_APPS_CMD_RCGR   0x3034
> +#define BLSP1_UART2_APPS_CFG_RCGR   0x3038
> +#define BLSP1_UART2_APPS_M          0x303C
> +#define BLSP1_UART2_APPS_N          0x3040
> +#define BLSP1_UART2_APPS_D          0x3044
> +
> +/* CBCR register fields */
> +#define CBCR_BRANCH_ENABLE_BIT  BIT(0)
> +#define CBCR_BRANCH_OFF_BIT     BIT(31)
> +
> +struct msm_clk_priv {
> +       phys_addr_t base;
> +};
> +
> +/* Enable clock controlled by CBC soft macro */
> +static void clk_enable_cbc(phys_addr_t cbcr)
> +{
> +       setbits_le32(cbcr, CBCR_BRANCH_ENABLE_BIT);
> +
> +       while (readl(cbcr) & CBCR_BRANCH_OFF_BIT)
> +               ;
> +}
> +
> +/* clock has 800MHz */
> +static void clk_enable_gpll0(phys_addr_t base)
> +{
> +       if (readl(base + GPLL0_STATUS) & GPLL0_STATUS_ACTIVE)
> +               return; /* clock already enabled */
> +
> +       setbits_le32(base + APCS_GPLL_ENA_VOTE, APCS_GPLL_ENA_VOTE_GPLL0);
> +
> +       while ((readl(base + GPLL0_STATUS) & GPLL0_STATUS_ACTIVE) == 0)
> +               ;
> +}
> +
> +#define APPS_CMD_RGCR_UPDATE BIT(0)
> +
> +/* Update clock command via CMD_RGCR */
> +static void clk_bcr_update(phys_addr_t apps_cmd_rgcr)
> +{
> +       setbits_le32(apps_cmd_rgcr, APPS_CMD_RGCR_UPDATE);
> +
> +       /* Wait for frequency to be updated. */
> +       while (readl(apps_cmd_rgcr) & APPS_CMD_RGCR_UPDATE)
> +               ;
> +}
> +
> +struct bcr_regs {
> +       uintptr_t cfg_rcgr;
> +       uintptr_t cmd_rcgr;
> +       uintptr_t M;
> +       uintptr_t N;
> +       uintptr_t D;
> +};
> +
> +/* RCGR_CFG register fields */
> +#define CFG_MODE_DUAL_EDGE (0x2 << 12) /* Counter mode */
> +
> +/* sources */
> +#define CFG_CLK_SRC_CXO   (0 << 8)
> +#define CFG_CLK_SRC_GPLL0 (1 << 8)
> +#define CFG_CLK_SRC_MASK  (7 << 8)
> +
> +/* Mask for supported fields */
> +#define CFG_MASK 0x3FFF
> +
> +#define CFG_DIVIDER_MASK 0x1F
> +
> +/* root set rate for clocks with half integer and MND divider */
> +static void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs,
> +                                int div, int m, int n, int source)
> +{
> +       uint32_t cfg;
> +       /* This register houses the M value for MND divider. */

s/This register houses //

> +       uint32_t m_val = m;
> +       /* This register houses the NOT(N-M) value for MND divider. */
> +       uint32_t n_val = ~((n)-(m)) * !!(n);
> +       /* This register houses the NOT 2D value for MND divider. */
> +       uint32_t d_val = ~(n);
> +
> +       /* Program MND values */
> +       writel(m_val, base + regs->M);
> +       writel(n_val, base + regs->N);
> +       writel(d_val, base + regs->D);
> +
> +       /* setup src select and divider */
> +       cfg  = readl(base + regs->cfg_rcgr);
> +       cfg &= ~CFG_MASK;
> +       cfg |= source & CFG_CLK_SRC_MASK; /* Select clock source */
> +
> +       /* Set the divider; HW permits fraction dividers (+0.5), but
> +          for simplicity, we will support integers only */
> +       if (div)
> +               cfg |= (2 * div - 1) & CFG_DIVIDER_MASK;
> +
> +       if (n_val)
> +               cfg |= CFG_MODE_DUAL_EDGE;
> +
> +       writel(cfg, base + regs->cfg_rcgr); /* Write new clock configuration */
> +
> +       /* Inform h/w to start using the new config. */
> +       clk_bcr_update(base + regs->cmd_rcgr);
> +}
> +
> +static const struct bcr_regs sdc_regs[] = {
> +       {
> +       .cfg_rcgr = SDCC_CFG_RCGR(1),
> +       .cmd_rcgr = SDCC_CMD_RCGR(1),
> +       .M = SDCC_M(1),
> +       .N = SDCC_N(1),
> +       .D = SDCC_D(1),
> +       },
> +       {
> +       .cfg_rcgr = SDCC_CFG_RCGR(2),
> +       .cmd_rcgr = SDCC_CMD_RCGR(2),
> +       .M = SDCC_M(2),
> +       .N = SDCC_N(2),
> +       .D = SDCC_D(2),
> +       }
> +};
> +
> +/* Init clock for SDHCI controller */
> +static int clk_init_sdc(struct msm_clk_priv *p, int slot, uint rate)

s/p/priv/

> +{
> +       int div = 8; /* 100MHz default */
> +
> +       if (rate == 200000000)
> +               div = 4;
> +
> +       clk_enable_cbc(p->base + SDCC_AHB_CBCR(slot));
> +       /* 800Mhz/div, gpll0 */
> +       clk_rcg_set_rate_mnd(p->base, &sdc_regs[slot], div, 0, 0,
> +                            CFG_CLK_SRC_GPLL0);
> +       clk_enable_gpll0(p->base);
> +       clk_enable_cbc(p->base + SDCC_APPS_CBCR(slot));
> +
> +       return rate;
> +}
> +
> +static const struct bcr_regs uart2_regs = {
> +       .cfg_rcgr = BLSP1_UART2_APPS_CFG_RCGR,
> +       .cmd_rcgr = BLSP1_UART2_APPS_CMD_RCGR,
> +       .M = BLSP1_UART2_APPS_M,
> +       .N = BLSP1_UART2_APPS_N,
> +       .D = BLSP1_UART2_APPS_D,
> +};
> +
> +/* Init UART clock, 115200 */
> +static int clk_init_uart(struct msm_clk_priv *p)
> +{
> +       /* Enable iface clk */
> +       clk_enable_cbc(p->base + BLSP1_AHB_CBCR);
> +       /* 7372800 uart block clock @ GPLL0 */
> +       clk_rcg_set_rate_mnd(p->base, &uart2_regs, 1, 144, 15625,
> +                            CFG_CLK_SRC_GPLL0);
> +       clk_enable_gpll0(p->base);
> +       /* Enable core clk */
> +       clk_enable_cbc(p->base + BLSP1_UART2_APPS_CBCR);
> +
> +       return 0;
> +}
> +
> +ulong msm_set_periph_rate(struct udevice *dev, int periph, ulong rate)
> +{
> +       struct msm_clk_priv *priv = dev_get_priv(dev);
> +
> +       switch (periph) {
> +       case 0: /* SDC1 */
> +               return clk_init_sdc(priv, 0, rate);
> +               break;
> +       case 1: /* SDC2 */
> +               return clk_init_sdc(priv, 1, rate);
> +               break;
> +       case 4: /* UART2 */
> +               return clk_init_uart(priv);
> +               break;
> +       default:
> +               return 0;
> +       }
> +}
> +
> +static int msm_clk_probe(struct udevice *dev)
> +{
> +       struct msm_clk_priv *priv = dev_get_priv(dev);
> +
> +       priv->base = dev_get_addr(dev);
> +       if (priv->base == FDT_ADDR_T_NONE)
> +               return -EINVAL;
> +
> +       return 0;
> +}
> +
> +static struct clk_ops msm_clk_ops = {
> +       .set_periph_rate = msm_set_periph_rate,
> +};
> +
> +static const struct udevice_id msm_clk_ids[] = {
> +       { .compatible = "qcom,gcc-msm8916" },
> +       { .compatible = "qcom,gcc-apq8016" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(clk_msm) = {
> +       .name           = "clk_msm",
> +       .id             = UCLASS_CLK,
> +       .of_match       = msm_clk_ids,
> +       .ops            = &msm_clk_ops,
> +       .priv_auto_alloc_size = sizeof(struct msm_clk_priv),
> +       .probe          = msm_clk_probe,
> +};
> diff --git a/arch/arm/mach-snapdragon/include/mach/gpio.h b/arch/arm/mach-snapdragon/include/mach/gpio.h
> new file mode 100644
> index 0000000..ff949b2
> --- /dev/null
> +++ b/arch/arm/mach-snapdragon/include/mach/gpio.h
> @@ -0,0 +1,9 @@
> +/*
> + * Empty gpio.h
> + *
> + * This file must stay as arch/arm/include/asm/gpio.h requires it.
> + *
> + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> diff --git a/arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h b/arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h
> new file mode 100644
> index 0000000..cdbfad0
> --- /dev/null
> +++ b/arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h
> @@ -0,0 +1,14 @@
> +/*
> + * Qualcomm APQ8916 sysmap
> + *
> + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +#ifndef _MACH_SYSMAP_APQ8016_H
> +#define _MACH_SYSMAP_APQ8016_H
> +
> +#define GICD_BASE 0x0b000000
> +#define GICC_BASE 0x0a20c000
> +
> +#endif
> diff --git a/arch/arm/mach-snapdragon/reset.c b/arch/arm/mach-snapdragon/reset.c
> new file mode 100644
> index 0000000..ade3237
> --- /dev/null
> +++ b/arch/arm/mach-snapdragon/reset.c
> @@ -0,0 +1,40 @@
> +/*
> + * Qualcomm APQ8016 reset controller driver
> + *
> + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <reset.h>
> +#include <asm/io.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static int msm_reset_request(struct udevice *dev, enum reset_t type)
> +{
> +       phys_addr_t addr = dev_get_addr(dev);
> +       if (!addr)
> +               return -EINVAL;
> +       writel(0, addr);
> +       return -EINPROGRESS;
> +}
> +
> +static struct reset_ops msm_reset_ops = {
> +       .request        = msm_reset_request,
> +};
> +
> +static const struct udevice_id msm_reset_ids[] = {
> +       { .compatible = "qcom,pshold" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(reset_sandbox) = {
> +       .name           = "msm_reset",
> +       .id             = UCLASS_RESET,
> +       .of_match       = msm_reset_ids,
> +       .ops            = &msm_reset_ops,
> +};
> --
> 2.5.0
>

Regards,
Simon

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

* [U-Boot] [PATCH v1 16/16] board: Add Qualcomm Dragonboard 410C support
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 16/16] board: Add Qualcomm Dragonboard 410C support Mateusz Kulikowski
  2016-01-07 10:23   ` Sjoerd Simons
@ 2016-01-11 16:58   ` Simon Glass
  2016-01-11 22:01     ` Mateusz Kulikowski
  2016-01-20  4:35   ` Simon Glass
  2 siblings, 1 reply; 49+ messages in thread
From: Simon Glass @ 2016-01-11 16:58 UTC (permalink / raw)
  To: u-boot

Hi,

On 6 January 2016 at 11:21, Mateusz Kulikowski
<mateusz.kulikowski@gmail.com> wrote:
> This commit add support for 96Boards Dragonboard410C.
>
> It is board based on APQ8016 Qualcomm SoC, complying with
> 96boards specification.
>
> Features (present out of the box):
> - 4x Cortex A53 (ARMv8)
> - 2x USB Host port
> - 1x USB Device port
> - 4x LEDs
> - 1x HDMI connector
> - 1x uSD connector
> - 3x buttons (Power, Vol+, Vol-/Reset)
> - WIFI, Bluetooth with integrated antenna
> - 8GiB eMMC
>
> U-Boot boots chained with fastboot in 64-bit mode.
> For detailed build instructions see readme.txt in board directory.
>
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> ---
>
> Changes in v1:
> - Add better help for dragonboard
> - Move static structures to board_prepare_usb
> - Add DM_SPMI to defconfig
>
>  arch/arm/dts/Makefile                            |   2 +
>  arch/arm/dts/dragonboard410c.dts                 | 154 +++++++++++++++++++
>  arch/arm/mach-snapdragon/Kconfig                 |  20 +++
>  board/qualcomm/dragonboard410c/Kconfig           |  15 ++
>  board/qualcomm/dragonboard410c/Makefile          |   8 +
>  board/qualcomm/dragonboard410c/dragonboard410c.c | 111 ++++++++++++++
>  board/qualcomm/dragonboard410c/head.S            |  20 +++
>  board/qualcomm/dragonboard410c/readme.txt        |  40 +++++
>  board/qualcomm/dragonboard410c/u-boot.lds        |  90 +++++++++++
>  configs/dragonboard410c_defconfig                |  30 ++++
>  include/configs/dragonboard410c.h                | 182 +++++++++++++++++++++++
>  11 files changed, 672 insertions(+)
>  create mode 100644 arch/arm/dts/dragonboard410c.dts
>  create mode 100644 board/qualcomm/dragonboard410c/Kconfig
>  create mode 100644 board/qualcomm/dragonboard410c/Makefile
>  create mode 100644 board/qualcomm/dragonboard410c/dragonboard410c.c
>  create mode 100644 board/qualcomm/dragonboard410c/head.S
>  create mode 100644 board/qualcomm/dragonboard410c/readme.txt
>  create mode 100644 board/qualcomm/dragonboard410c/u-boot.lds
>  create mode 100644 configs/dragonboard410c_defconfig
>  create mode 100644 include/configs/dragonboard410c.h

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

But please see my comment below.

>
> diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
> index 0bcd316..47aecf5 100644
> --- a/arch/arm/dts/Makefile
> +++ b/arch/arm/dts/Makefile
> @@ -95,6 +95,8 @@ dtb-$(CONFIG_FSL_LSCH3) += fsl-ls2080a-qds.dtb \
>  dtb-$(CONFIG_FSL_LSCH2) += fsl-ls1043a-qds.dtb \
>         fsl-ls1043a-rdb.dtb
>
> +dtb-$(CONFIG_ARCH_SNAPDRAGON) += dragonboard410c.dtb
> +
>  dtb-$(CONFIG_MACH_SUN4I) += \
>         sun4i-a10-a1000.dtb \
>         sun4i-a10-ba10-tvbox.dtb \
> diff --git a/arch/arm/dts/dragonboard410c.dts b/arch/arm/dts/dragonboard410c.dts
> new file mode 100644
> index 0000000..1de5d23
> --- /dev/null
> +++ b/arch/arm/dts/dragonboard410c.dts
> @@ -0,0 +1,154 @@
> +/dts-v1/;
> +
> +#include "skeleton64.dtsi"
> +
> +/ {
> +       model = "Qualcomm Technologies, Inc. Dragonboard 410c";
> +       compatible = "qcom,dragonboard", "qcom,apq8016-sbc";
> +       qcom,msm-id = <0xce 0x0 0xf8 0x0 0xf9 0x0 0xfa 0x0 0xf7 0x0>;
> +       qcom,board-id = <0x10018 0x0>;
> +       #address-cells = <0x2>;
> +       #size-cells = <0x2>;
> +
> +       memory {
> +               device_type = "memory";
> +               reg = <0 0x80000000 0 0x3da00000>;
> +       };
> +
> +       chosen {
> +               stdout-path = "/soc/serial at 78b0000";
> +       };
> +
> +
> +       soc {
> +               #address-cells = <0x1>;
> +               #size-cells = <0x1>;
> +               ranges = <0x0 0x0 0x0 0xffffffff>;
> +               compatible = "simple-bus";
> +
> +               clkc: qcom,gcc at 1800000 {
> +                       compatible = "qcom,gcc-apq8016";
> +                       reg = <0x1800000 0x80000>;
> +                       #address-cells = <0x1>;
> +                       #size-cells = <0x0>;
> +               };
> +
> +               serial at 78b0000 {
> +                       compatible = "qcom,msm-uartdm-v1.4";
> +                       reg = <0x78b0000 0x200>;
> +                       u-boot,dm-pre-reloc;
> +                       clock = <&clkc 4>;
> +               };
> +
> +               restart at 4ab000 {
> +                       compatible = "qcom,pshold";
> +                       reg = <0x4ab000 0x4>;
> +               };
> +
> +               soc_gpios: pinctrl at 1000000 {
> +                       compatible = "qcom,apq8016-pinctrl";
> +                       reg = <0x1000000 0x300000>;
> +                       gpio-controller;
> +                       gpio-count = <122>;
> +                       gpio-bank-name="soc";
> +                       #gpio-cells = <1>;
> +               };
> +
> +               ehci at 78d9000 {
> +                       compatible = "qcom,ehci-host";
> +                       reg = <0x78d9000 0x400>;
> +               };
> +
> +               sdhci at 07824000 {
> +                       compatible = "qcom,sdhci-msm-v4";
> +                       reg = <0x7824900 0x11c 0x7824000 0x800>;
> +                       bus-width = <0x8>;
> +                       index = <0x0>;
> +                       non-removable;
> +                       clock = <&clkc 0>;
> +                       clock-frequency = <100000000>;
> +               };
> +
> +               sdhci at 07864000 {
> +                       compatible = "qcom,sdhci-msm-v4";
> +                       reg = <0x7864900 0x11c 0x7864000 0x800>;
> +                       index = <0x1>;
> +                       bus-width = <0x4>;
> +                       clock = <&clkc 1>;
> +                       clock-frequency = <200000000>;
> +               };
> +
> +               spmi at 200f000 {
> +                       compatible = "qcom,spmi-pmic-arb";
> +                       reg = <0x200f800 0x200 0x2400000 0x400000 0x2c00000 0x400000>;
> +                       #address-cells = <0x1>;
> +                       #size-cells = <0x1>;
> +                       pm8916 at 0 {
> +                               compatible = "qcom,spmi-pmic";
> +                               reg = <0x0 0x1>;
> +                               #address-cells = <0x1>;
> +                               #size-cells = <0x1>;
> +
> +                               pmic_pon: pon at 800 {
> +                                       compatible = "qcom,pm8916-pwrkey";
> +                                       reg = <0x800 0x96>;
> +                                       #gpio-cells = <2>;
> +                                       gpio-controller;
> +                               };
> +
> +                               pmic_gpios: gpios at c000 {
> +                                       compatible = "qcom,pm8916-gpio";
> +                                       reg = <0xc000 0x400>;
> +                                       gpio-controller;
> +                                       gpio-count = <4>;
> +                                       #gpio-cells = <2>;
> +                                       gpio-bank-name="pmic";
> +                               };
> +                       };
> +
> +                       pm8916 at 1 {
> +                               compatible = "qcom,spmi-pmic";
> +                               reg = <0x1 0x1>;
> +                       };
> +               };
> +       };
> +
> +       leds {
> +               compatible = "gpio-leds";
> +               user1 {
> +                       label = "green:user1";
> +                       gpios = <&soc_gpios 21 0>;
> +               };
> +
> +               user2 {
> +                       label = "green:user2";
> +                       gpios = <&soc_gpios 120 0>;
> +               };
> +
> +               user3 {
> +                       label = "green:user3";
> +                       gpios = <&pmic_gpios 0 0>;
> +               };
> +
> +               user4 {
> +                       label = "green:user4";
> +                       gpios = <&pmic_gpios 1 0>;
> +               };
> +       };
> +
> +       usb_hub_reset_n_pm {
> +               gpios = <&pmic_gpios 2 0>;
> +       };
> +
> +       usb_sw_sel_pm {
> +               gpios = <&pmic_gpios 3 0>;
> +       };
> +
> +       key_vol_down {
> +               gpios = <&pmic_pon 1 0>;
> +       };
> +
> +       key_power {
> +               gpios = <&pmic_pon 0 0>;
> +       };

The above four nodes seems odd in that they don't have compatible
strings. Is this how Linux does it? Also more normally the node name
has hyphens rather than underscores.

Regards,
Simon

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

* [U-Boot] [PATCH v1 02/16] gpio: Add support for Qualcomm gpio controller
  2016-01-11 16:57   ` Simon Glass
@ 2016-01-11 21:27     ` Mateusz Kulikowski
  0 siblings, 0 replies; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-11 21:27 UTC (permalink / raw)
  To: u-boot

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

On 11.01.2016 17:57, Simon Glass wrote:
> Hi,
> 
> On 6 January 2016 at 11:21, Mateusz Kulikowski
> <mateusz.kulikowski@gmail.com> wrote:
[...]
>> +static int msm_gpio_get_function(struct udevice *dev, unsigned offset)
>> +{
>> +       struct msm_gpio_bank *priv = dev_get_priv(dev);
>> +
>> +       if (readl(priv->base + GPIO_CONFIG_OFF(offset)) & GPIO_OE_ENABLE)
>> +               return GPIOF_OUTPUT;
>> +       return GPIOF_INPUT;
> 
> Can it ever be GPIOF_FUNCTION?

For now - not (at least not until I implement pin multiplexing).

This may change once I upgrade the code to replace LittleKernel/fastboot.

[...]
>> +{
>> +       struct msm_gpio_bank *priv = dev_get_priv(dev);
>> +
>> +       priv->base = dev_get_addr(dev);
>> +       return priv->base == FDT_ADDR_T_NONE;
> 
> Maybe you mean:
> 
>       return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0;

Yes I meant that :)

Regards,
Mateusz
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQEcBAEBCAAGBQJWlB5aAAoJELvtohmVtQzBjDoH/RT9FQGlyNs4KFXhmji970cN
snZxfEQ28kW0A3Tzpbw8S36SgPz5Qr/xwUjXWc4pOGQwgnEQRj7IPnPrgVgbdg4c
VZzoLmLFFLJTnvinoYQmEq0uLMZgDaG6YcvCKPEI1N8fBstsa0UOsflwSFFedvJm
CryhDVQMZnn4SD0jhWCcrsGcaddGAbNj0bdTnF3RqnJnBo4/phI2pP+WLxjv67SQ
H/7k9b29dv9i1em2/DY/SKoTasETVEAaMyVF6FjYj2fzAHwTLaFwGSyZivFSzB7W
spPGK3EoHo+NfAmP3MLrk4R8l5LdACB+jBKfDC9BKtzN0ToQhbKyw53fs/C94cI=
=SpRK
-----END PGP SIGNATURE-----

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

* [U-Boot] [PATCH v1 05/16] usb: ulpi: Add Kconfig options for ULPI
  2016-01-07 23:18       ` Simon Glass
@ 2016-01-11 21:30         ` Mateusz Kulikowski
  0 siblings, 0 replies; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-11 21:30 UTC (permalink / raw)
  To: u-boot

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

On 08.01.2016 00:18, Simon Glass wrote:
> Hi,
> 
> On 7 January 2016 at 15:12, Mateusz Kulikowski
[...]

>>> On Wednesday, January 06, 2016 at 07:21:17 PM, Mateusz Kulikowski wrote:
>>>> The following options can be now enabled via defconfig:
>>>> - CONFIG_USB_ULPI
>>>> - CONFIG_USB_ULPI_VIEWPORT
>>>> - CONFIG_USB_ULPI_VIEWPORT_OMAP
>>>>
>> [...]
>>
>>>> +++ b/drivers/usb/ulpi/Kconfig
>>>> @@ -0,0 +1,10 @@
>>>> +comment "ULPI drivers"
>>>> +
>>>> +config USB_ULPI
>>>> +    bool
>>>> +
>>>> +config USB_ULPI_VIEWPORT
>>>> +    bool
>>>> +
>>>> +config USB_ULPI_VIEWPORT_OMAP
>>>> +    bool
>>>
>>> Description of these options is missing.
>>
>> My intention here was to keep it away from "users".
>>
>> This options are not "optional" in any way.
>> They are rather like CPU_something or VBAR_something,
>> that is - they are required and should be selected by drivers that use them,
>> but without this drivers, they are useless.
> 
> Perhaps we don't need the options at all then?
> 
> But there are lots of users in the tree. You should use the
> moveconfig.py script to move them all to Kconfig.
> 
>>
>> But maybe I'm missing something :)
>> If anyone insists on that - I'll make them visible and add description.
> 
> Please add detailed help for all Kconfig options you add.

Will add descriptions as big as I'm able to.

Regards,
Mateusz

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

* [U-Boot] [PATCH v1 09/16] ehci: Add support for Qualcomm EHCI
  2016-01-06 21:04   ` Marek Vasut
@ 2016-01-11 21:39     ` Mateusz Kulikowski
  2016-01-11 22:02       ` Marek Vasut
  0 siblings, 1 reply; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-11 21:39 UTC (permalink / raw)
  To: u-boot

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

On 06.01.2016 22:04, Marek Vasut wrote:
> On Wednesday, January 06, 2016 at 07:21:21 PM, Mateusz Kulikowski wrote:
>> This driver is able to reconfigure OTG controller into HOST mode.
>> Board can add board-specific initialization as board_prepare_usb().
>> It requires USB_ULPI_VIEWPORT enabled in board configuration.
>>
>> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> 
> [...]
> 
>> +static int msm_init_after_reset(struct ehci_ctrl *dev)
>> +{
>> +	struct msm_ehci_priv *p = container_of(dev, struct msm_ehci_priv, ctrl);
>> +	struct usb_ehci *ehci = p->ehci;
>> +
>> +	/* select ULPI phy */
>> +	writel(0x80000000, &ehci->portsc);
> 
> Don't we have macro for this bit ?

hmhm.. I need spoiler..

Did you meant EHCI_PS_* series of #defines from ehci.h?

This bit is not there (header was probably based on EHCI 1.0 spec, where this bit was reserved).
Of course I can add it there and use here :)

Regards,
Mateusz

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQEcBAEBCAAGBQJWlCEeAAoJELvtohmVtQzBkoMH/RSRhWcO2CMdNpsBi38oIXNC
xt7n0Tpilaac/Ch2GaSnY5rsJN9iMGCEgFZbXy+Z05qqFPMBPKPcQ5Bq7cTt2hvM
jLyLknxNAHIfJjGg1RxIpZakXflrt83DZG6mV0jHldFh5Q2+VZtNRCPbpOqBpAzI
mPT1+9SJt9By6LcQfTHjo+45nVvMifw0giKjHNoXadM2a+RHgi+jyeYwa8Vi6XyL
fmv4UfYISrA+fYYxvCANsTcXlyULxiTfzIYA2BzXslYjskEjvha0cqD8gsFpfAqP
AntwSXnOKg7EYkr8IniAxsoITcQKfEi1g9liLLgxOENMpCQLvrUAN6l+6Ma2rI8=
=inLQ
-----END PGP SIGNATURE-----

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

* [U-Boot] [PATCH v1 10/16] drivers: Add SPMI bus uclass
  2016-01-11 16:57   ` Simon Glass
@ 2016-01-11 21:41     ` Mateusz Kulikowski
  0 siblings, 0 replies; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-11 21:41 UTC (permalink / raw)
  To: u-boot

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Hi Simon ,

On 11.01.2016 17:57, Simon Glass wrote:
[...]
>> @@ -0,0 +1,10 @@
>> +menu "SPMI support"
>> +
>> +config DM_SPMI
> 
> Can we just use SPMI, or is that is use? We want to remove all the DM_
> options when everything is converted to driver model. So if you are
> adding a new class you should be able to avoid the DM_ prefix.

Sure, I thought it's mandatory :)

[..]
>> +
>> +#include <common.h>
>> +#include <dm.h>
>> +#include <dm/root.h>
>> +#include <errno.h>
>> +#include <spmi/spmi.h>
>> +#include <linux/ctype.h>
> 
> http://www.denx.de/wiki/U-Boot/CodingStyle
> 
> common.h
> dm.h
> errno.h
> dm/...
> spmi/...
> linux/...

Oops, this slipped - my bad

Regards,
Mateusz

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQEcBAEBCAAGBQJWlCGaAAoJELvtohmVtQzB8HsH/2C5C6qWhUpBlXiyhXLBa7TG
6KWy+NwrGdadwi1IT/UiBbryM7O6YT+H/Ey7MIfC0VNyhPnSiMimCYH7RQoNtoYT
lA5QUb1FAAvVbyypD9t0CRl32uORbG/2WocDdPbAjyTJp3/GldwZ0ZjeQo2uOedv
zUmwEmMiylff7m2wjD4EhEJayyTF/8oVCaqH4OtlxwupIHMgekPNUBjtW5VfjPMP
oldrwD2k2nbAj7Y91nxKPQiMgql4eOdXQCnwkW4ovz6wB1jb9/b8d42W75rhFoDu
2FRcP6NWR9XurMQIjtSz7O587UrGWrKm4ts7MjjhMMt4aPjDVNd+9CE+R8mEu3A=
=gUUy
-----END PGP SIGNATURE-----

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

* [U-Boot] [PATCH v1 16/16] board: Add Qualcomm Dragonboard 410C support
  2016-01-07 10:23   ` Sjoerd Simons
@ 2016-01-11 21:49     ` Mateusz Kulikowski
  0 siblings, 0 replies; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-11 21:49 UTC (permalink / raw)
  To: u-boot

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Hi, 

On 07.01.2016 11:23, Sjoerd Simons wrote:
> On Wed, 2016-01-06 at 19:21 +0100, Mateusz Kulikowski wrote:
>> This commit add support for 96Boards Dragonboard410C.
>>
>> diff --git a/include/configs/dragonboard410c.h
>> b/include/configs/dragonboard410c.h
>> new file mode 100644
>> index 0000000..91f0e02
>> --- /dev/null
>> +++ b/include/configs/dragonboard410c.h
>> @@ -0,0 +1,182 @@
>> +/*
>> + * Board configuration file for Dragonboard 410C
>> + *
>> + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.c
>> om>
>> + *
>> + * SPDX-License-Identifier:	GPL-2.0+
>> + */
>> +
>> +#ifndef __CONFIGS_DRAGONBOARD410C_H
>> +#define __CONFIGS_DRAGONBOARD410C_H
>> +
>> +#include <linux/sizes.h>
>> +#include <asm/arch/sysmap-apq8016.h>
>> +
>> +#define CONFIG_IDENT_STRING		"\nQualcomm-DragonBoard
>> 410C"
>> +
>> +#define CONFIG_MISC_INIT_R /* To stop autoboot */
>> +
>> +/* Flat Device Tree Definitions */
>> +#define CONFIG_OF_LIBFDT
>> +
>> +/* Physical Memory Map */
>> +#define CONFIG_NR_DRAM_BANKS		1
>> +#define PHYS_SDRAM_1			0x80000000
>> +/* 1008 MB (the last ~30Mb are secured for TrustZone by ATF*/
>> +#define PHYS_SDRAM_1_SIZE		0x3da00000
>> +#define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
>> +#define CONFIG_SYS_TEXT_BASE		0x80080000
>> +#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_SDRAM_BAS
>> E + 0x7fff0)
>> +#define CONFIG_SYS_LOAD_ADDR		(CONFIG_SYS_SDRAM_BASE +
>> 0x80000)
>> +#define CONFIG_SYS_BOOTM_LEN		0x1000000 /* 16MB max
>> kernel size */
>> +
>> +/* UART */
>> +#define CONFIG_BAUDRATE			115200
>> +
>> +/* Generic Timer Definitions */
>> +#define COUNTER_FREQUENCY		19000000
>> +
>> +/* This are needed to have proper mmc support */
>> +#define CONFIG_MMC
>> +#define CONFIG_GENERIC_MMC
>> +#define CONFIG_SDHCI
>> +
>> +#define CONFIG_SYS_LDSCRIPT "board/qualcomm/dragonboard410c/u-
>> boot.lds"
>> +
>> +/* Fixup - in init code we switch from device to host mode,
>> + * it has to be done after each HCD reset */
>> +#define CONFIG_EHCI_HCD_INIT_AFTER_RESET
>> +
>> +#define CONFIG_USB_HOST_ETHER /* Enable USB Networking */
>> +
>> +/* Support all possible USB ethernet dongles */
>> +#define CONFIG_USB_ETHER_DM9601
>> +#define CONFIG_USB_ETHER_ASIX
>> +#define CONFIG_USB_ETHER_ASIX88179
>> +#define CONFIG_USB_ETHER_MCS7830
>> +#define CONFIG_USB_ETHER_SMSC95XX
>> +
>> +/* Libraries  */
>> +#define CONFIG_MD5
>> +
>> +/* Extra Commands */
>> +#define CONFIG_CMD_CACHE
>> +#define CONFIG_CMD_DHCP
>> +#define CONFIG_CMD_ENV
>> +#define CONFIG_CMD_FAT		/* FAT support			
>> */
>> +#define CONFIG_CMD_GPIO
>> +#define CONFIG_CMD_GPT
>> +#define CONFIG_CMD_MD5SUM
>> +#define CONFIG_CMD_MEMINFO	/* meminfo			
>> */
>> +#define CONFIG_CMD_MMC
>> +/* Enable that for switching of boot partitions */
>> +/* Disabled by default as some sub-commands can brick eMMC */
>> +/*#define CONFIG_SUPPORT_EMMC_BOOT */
>> +#define CONFIG_CMD_PART
>> +#define CONFIG_CMD_PING
>> +#define CONFIG_CMD_REGINFO	/* Register dump		*/
>> +#define CONFIG_CMD_TFTP
>> +#define CONFIG_CMD_TIMER
>> +#define CONFIG_CMD_UNZIP
>> +#define CONFIG_CMD_BOOTZ
>> +#define CONFIG_CMD_BOOT
> 
> Using config_distro_defaults would give you a nice set of default
> commands to include. May make sense to use that and drop the
> duplicates.

Will do

> 
> Also the 410C is 64 bit arm afaik, so i would hvae expected _CMD_BOOTI
> rather then _CMD_BOOTZ

Booti is there as well; I'll drop bootz for now (I think I added it very early,  
before I knew u-boot has different command for Images and forgot to remove it).

Perhaps later I'll make option to boot 32bit images and then it may be helpful.

But it's bigger task so let's forget about that for now :)

> 
> 
>> +
>> +/* Command line configuration */
>> +#define CONFIG_MENU
>> +#define CONFIG_SYS_LONGHELP
>> +
>> +/* Partition table support */
>> +#define HAVE_BLOCK_DEVICE /* Needed for partition commands */
>> +#define CONFIG_DOS_PARTITION
>> +#define CONFIG_EFI_PARTITION
>> +#define CONFIG_PARTITION_UUIDS
>> +
>> +/* BOOTP options */
>> +#define CONFIG_BOOTP_BOOTFILESIZE
>> +
>> +/* Environment - Boot*/
>> +#define CONFIG_BOOTDELAY		2	/* autoboot after 2
>> seconds */
>> +
>> +#define CONFIG_NFSBOOTCOMMAND ""
>> +#define CONFIG_BOOTCOMMAND "usb start && dhcp && tftp && usb stop &&
>> bootm"
> 
> Any reason for a custom default bootcmd rather then
> using config_distro_bootcmd ? (Especially for board like the 96boards
> ones it seems quite useful to use a standardized boot sequence).

Just personal preferences; Will adjust environment to hikey so we will have unification.

Regards and thanks for hints,
Mateusz

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQEcBAEBCAAGBQJWlCNsAAoJELvtohmVtQzBcz4IAIoN+mFOf8KVx7dfi3VCVxvn
D6W0qAT0DawbRraWeLlIGkTXD+BJzeCK4FNxjeTO0o/OTcAWxfY7hIlNanwEpsSd
t2WBZeXGgruVIVwCc0dCJsG3MNqHprRVVC3kH+vuhPdSDRZF9EyktOz0E37DYNAE
ie/CKuLetDDi8LfNre0Ng0lLR3UX1mkqcepHWpDN608KZW2nlQ1+A2WIhocRtxjz
1BDDkVnMEAIOKfjcWyfn8zvVd1Gg7j12pO5T9kIinasKRFAufaXjLdcPD+44tY4G
4JOzJ2PPiTKCdHbZ1zz28UbseIiXc+Ri80+a87XITFiDx4aw0FPzdIXXk5T+bTs=
=MkIk
-----END PGP SIGNATURE-----

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

* [U-Boot] [PATCH v1 16/16] board: Add Qualcomm Dragonboard 410C support
  2016-01-11 16:58   ` Simon Glass
@ 2016-01-11 22:01     ` Mateusz Kulikowski
  2016-01-13 20:32       ` Simon Glass
  0 siblings, 1 reply; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-11 22:01 UTC (permalink / raw)
  To: u-boot

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Hi,

On 11.01.2016 17:58, Simon Glass wrote:
> Hi,
> 
> On 6 January 2016 at 11:21, Mateusz Kulikowski
> <mateusz.kulikowski@gmail.com> wrote:
>> This commit add support for 96Boards Dragonboard410C.
[...]
>> +       usb_hub_reset_n_pm {
>> +               gpios = <&pmic_gpios 2 0>;
>> +       };
>> +
>> +       usb_sw_sel_pm {
>> +               gpios = <&pmic_gpios 3 0>;
>> +       };
>> +
>> +       key_vol_down {
>> +               gpios = <&pmic_pon 1 0>;
>> +       };
>> +
>> +       key_power {
>> +               gpios = <&pmic_pon 0 0>;
>> +       };
> 
> The above four nodes seems odd in that they don't have compatible
> strings. Is this how Linux does it? Also more normally the node name
> has hyphens rather than underscores.

In Linux nodes are childs of PMIC gpio periperhal (pmic_gpios in my case):
&pm8916_gpios {

	usb_hub_reset_pm: usb_hub_reset_pm {
		pinconf {
			pins = "gpio3";
			function = PMIC_GPIO_FUNC_NORMAL;
			output-low;
		};
	};

(https://github.com/torvalds/linux/blob/master/arch/arm64/boot/dts/qcom/apq8016-sbc-pmic-pins.dtsi)

I decided to move them away from PMIC, as they only use specific gpios.

To be honest they are just a references so I don't have to hardcode gpio names/numbers in 
board sources.

Is it ok if I keep it that way? Could you suggest better approach?

Regards,
Mateusz

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQEcBAEBCAAGBQJWlCYsAAoJELvtohmVtQzBECkH/A5wLQRBfMjnpZubeTpnEfhC
W6M8bOLpjtEPZIHFeoWIblEBoa/M9S0TS1Sx0c/K3E1KwjkfVzs+LiSY/5PTtMqX
82v4qnJSEYtbxtX2WN40Dr+lRdGgHs+h73pHOMoSTGrFsB0sRRDMwurzRDWt2vFc
deirO3Ow6Qyzij2qKjV+28PR9bzHGES0fMXpSACUl/p+3m+hAdbflt12TQOK5f42
t+/O2qwZQg7OGqyANGU3jUjA8uiRiR+2ucvNNkHk2QQvU2TefsbUN1c1Hxz5JgKN
NNnPgwBq0J9+bsdVV8x8cgoTi01uTUX8l2KVUaQHvrGeOic53ulH0DszWz9JXtQ=
=MvsZ
-----END PGP SIGNATURE-----

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

* [U-Boot] [PATCH v1 09/16] ehci: Add support for Qualcomm EHCI
  2016-01-11 21:39     ` Mateusz Kulikowski
@ 2016-01-11 22:02       ` Marek Vasut
  0 siblings, 0 replies; 49+ messages in thread
From: Marek Vasut @ 2016-01-11 22:02 UTC (permalink / raw)
  To: u-boot

On Monday, January 11, 2016 at 10:39:46 PM, Mateusz Kulikowski wrote:
> On 06.01.2016 22:04, Marek Vasut wrote:
> > On Wednesday, January 06, 2016 at 07:21:21 PM, Mateusz Kulikowski wrote:
> >> This driver is able to reconfigure OTG controller into HOST mode.
> >> Board can add board-specific initialization as board_prepare_usb().
> >> It requires USB_ULPI_VIEWPORT enabled in board configuration.
> >> 
> >> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> > 
> > [...]
> > 
> >> +static int msm_init_after_reset(struct ehci_ctrl *dev)
> >> +{
> >> +	struct msm_ehci_priv *p = container_of(dev, struct msm_ehci_priv,
> >> ctrl); +	struct usb_ehci *ehci = p->ehci;
> >> +
> >> +	/* select ULPI phy */
> >> +	writel(0x80000000, &ehci->portsc);
> > 
> > Don't we have macro for this bit ?
> 
> hmhm.. I need spoiler..
> 
> Did you meant EHCI_PS_* series of #defines from ehci.h?
> 
> This bit is not there (header was probably based on EHCI 1.0 spec, where
> this bit was reserved). Of course I can add it there and use here :)

More like include/usb/ehci-fsl.h , there's a bit for it.

Best regards,
Marek Vasut

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

* [U-Boot] [PATCH v1 16/16] board: Add Qualcomm Dragonboard 410C support
  2016-01-11 22:01     ` Mateusz Kulikowski
@ 2016-01-13 20:32       ` Simon Glass
  2016-01-20 21:46         ` Mateusz Kulikowski
  0 siblings, 1 reply; 49+ messages in thread
From: Simon Glass @ 2016-01-13 20:32 UTC (permalink / raw)
  To: u-boot

Hi Mateusz,

On 11 January 2016 at 15:01, Mateusz Kulikowski
<mateusz.kulikowski@gmail.com> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA256
>
> Hi,
>
> On 11.01.2016 17:58, Simon Glass wrote:
>> Hi,
>>
>> On 6 January 2016 at 11:21, Mateusz Kulikowski
>> <mateusz.kulikowski@gmail.com> wrote:
>>> This commit add support for 96Boards Dragonboard410C.
> [...]
>>> +       usb_hub_reset_n_pm {
>>> +               gpios = <&pmic_gpios 2 0>;
>>> +       };
>>> +
>>> +       usb_sw_sel_pm {
>>> +               gpios = <&pmic_gpios 3 0>;
>>> +       };
>>> +
>>> +       key_vol_down {
>>> +               gpios = <&pmic_pon 1 0>;
>>> +       };
>>> +
>>> +       key_power {
>>> +               gpios = <&pmic_pon 0 0>;
>>> +       };
>>
>> The above four nodes seems odd in that they don't have compatible
>> strings. Is this how Linux does it? Also more normally the node name
>> has hyphens rather than underscores.
>
> In Linux nodes are childs of PMIC gpio periperhal (pmic_gpios in my case):
> &pm8916_gpios {
>
>         usb_hub_reset_pm: usb_hub_reset_pm {
>                 pinconf {
>                         pins = "gpio3";
>                         function = PMIC_GPIO_FUNC_NORMAL;
>                         output-low;
>                 };
>         };
>
> (https://github.com/torvalds/linux/blob/master/arch/arm64/boot/dts/qcom/apq8016-sbc-pmic-pins.dtsi)
>
> I decided to move them away from PMIC, as they only use specific gpios.
>
> To be honest they are just a references so I don't have to hardcode gpio names/numbers in
> board sources.
>
> Is it ok if I keep it that way? Could you suggest better approach?

We should avoid forking the device tree and making up bindings.

Really it looks like qcom,qpnp-pin should be a pinctrl driver. Then
pinctrl-0 in your device node will automatically pick up the correct
function.

Regards,
Simon

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

* [U-Boot] [PATCH v1 16/16] board: Add Qualcomm Dragonboard 410C support
  2016-01-06 18:21 ` [U-Boot] [PATCH v1 16/16] board: Add Qualcomm Dragonboard 410C support Mateusz Kulikowski
  2016-01-07 10:23   ` Sjoerd Simons
  2016-01-11 16:58   ` Simon Glass
@ 2016-01-20  4:35   ` Simon Glass
  2016-01-20 22:00     ` Mateusz Kulikowski
  2 siblings, 1 reply; 49+ messages in thread
From: Simon Glass @ 2016-01-20  4:35 UTC (permalink / raw)
  To: u-boot

Hi Mateusz,

On 6 January 2016 at 11:21, Mateusz Kulikowski
<mateusz.kulikowski@gmail.com> wrote:
> This commit add support for 96Boards Dragonboard410C.
>
> It is board based on APQ8016 Qualcomm SoC, complying with
> 96boards specification.
>
> Features (present out of the box):
> - 4x Cortex A53 (ARMv8)
> - 2x USB Host port
> - 1x USB Device port
> - 4x LEDs
> - 1x HDMI connector
> - 1x uSD connector
> - 3x buttons (Power, Vol+, Vol-/Reset)
> - WIFI, Bluetooth with integrated antenna
> - 8GiB eMMC
>
> U-Boot boots chained with fastboot in 64-bit mode.
> For detailed build instructions see readme.txt in board directory.
>
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> ---
>
> Changes in v1:
> - Add better help for dragonboard
> - Move static structures to board_prepare_usb
> - Add DM_SPMI to defconfig
>
>  arch/arm/dts/Makefile                            |   2 +
>  arch/arm/dts/dragonboard410c.dts                 | 154 +++++++++++++++++++
>  arch/arm/mach-snapdragon/Kconfig                 |  20 +++
>  board/qualcomm/dragonboard410c/Kconfig           |  15 ++
>  board/qualcomm/dragonboard410c/Makefile          |   8 +
>  board/qualcomm/dragonboard410c/dragonboard410c.c | 111 ++++++++++++++
>  board/qualcomm/dragonboard410c/head.S            |  20 +++
>  board/qualcomm/dragonboard410c/readme.txt        |  40 +++++
>  board/qualcomm/dragonboard410c/u-boot.lds        |  90 +++++++++++
>  configs/dragonboard410c_defconfig                |  30 ++++
>  include/configs/dragonboard410c.h                | 182 +++++++++++++++++++++++
>  11 files changed, 672 insertions(+)
>  create mode 100644 arch/arm/dts/dragonboard410c.dts
>  create mode 100644 board/qualcomm/dragonboard410c/Kconfig
>  create mode 100644 board/qualcomm/dragonboard410c/Makefile
>  create mode 100644 board/qualcomm/dragonboard410c/dragonboard410c.c
>  create mode 100644 board/qualcomm/dragonboard410c/head.S
>  create mode 100644 board/qualcomm/dragonboard410c/readme.txt
>  create mode 100644 board/qualcomm/dragonboard410c/u-boot.lds
>  create mode 100644 configs/dragonboard410c_defconfig
>  create mode 100644 include/configs/dragonboard410c.h

Can you please add a MAINTAINERS file also?

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

>
> diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
> index 0bcd316..47aecf5 100644
> --- a/arch/arm/dts/Makefile
> +++ b/arch/arm/dts/Makefile
> @@ -95,6 +95,8 @@ dtb-$(CONFIG_FSL_LSCH3) += fsl-ls2080a-qds.dtb \
>  dtb-$(CONFIG_FSL_LSCH2) += fsl-ls1043a-qds.dtb \
>         fsl-ls1043a-rdb.dtb
>
> +dtb-$(CONFIG_ARCH_SNAPDRAGON) += dragonboard410c.dtb
> +
>  dtb-$(CONFIG_MACH_SUN4I) += \
>         sun4i-a10-a1000.dtb \
>         sun4i-a10-ba10-tvbox.dtb \
> diff --git a/arch/arm/dts/dragonboard410c.dts b/arch/arm/dts/dragonboard410c.dts
> new file mode 100644
> index 0000000..1de5d23
> --- /dev/null
> +++ b/arch/arm/dts/dragonboard410c.dts
> @@ -0,0 +1,154 @@
> +/dts-v1/;
> +
> +#include "skeleton64.dtsi"
> +
> +/ {
> +       model = "Qualcomm Technologies, Inc. Dragonboard 410c";
> +       compatible = "qcom,dragonboard", "qcom,apq8016-sbc";
> +       qcom,msm-id = <0xce 0x0 0xf8 0x0 0xf9 0x0 0xfa 0x0 0xf7 0x0>;
> +       qcom,board-id = <0x10018 0x0>;
> +       #address-cells = <0x2>;
> +       #size-cells = <0x2>;
> +
> +       memory {
> +               device_type = "memory";
> +               reg = <0 0x80000000 0 0x3da00000>;
> +       };
> +
> +       chosen {
> +               stdout-path = "/soc/serial at 78b0000";
> +       };
> +
> +
> +       soc {
> +               #address-cells = <0x1>;
> +               #size-cells = <0x1>;
> +               ranges = <0x0 0x0 0x0 0xffffffff>;
> +               compatible = "simple-bus";
> +
> +               clkc: qcom,gcc at 1800000 {
> +                       compatible = "qcom,gcc-apq8016";
> +                       reg = <0x1800000 0x80000>;
> +                       #address-cells = <0x1>;
> +                       #size-cells = <0x0>;
> +               };
> +
> +               serial at 78b0000 {
> +                       compatible = "qcom,msm-uartdm-v1.4";
> +                       reg = <0x78b0000 0x200>;
> +                       u-boot,dm-pre-reloc;
> +                       clock = <&clkc 4>;
> +               };
> +
> +               restart at 4ab000 {
> +                       compatible = "qcom,pshold";
> +                       reg = <0x4ab000 0x4>;
> +               };
> +
> +               soc_gpios: pinctrl at 1000000 {
> +                       compatible = "qcom,apq8016-pinctrl";
> +                       reg = <0x1000000 0x300000>;
> +                       gpio-controller;
> +                       gpio-count = <122>;
> +                       gpio-bank-name="soc";
> +                       #gpio-cells = <1>;
> +               };
> +
> +               ehci at 78d9000 {
> +                       compatible = "qcom,ehci-host";
> +                       reg = <0x78d9000 0x400>;
> +               };
> +
> +               sdhci at 07824000 {
> +                       compatible = "qcom,sdhci-msm-v4";
> +                       reg = <0x7824900 0x11c 0x7824000 0x800>;
> +                       bus-width = <0x8>;
> +                       index = <0x0>;
> +                       non-removable;
> +                       clock = <&clkc 0>;
> +                       clock-frequency = <100000000>;
> +               };
> +
> +               sdhci at 07864000 {
> +                       compatible = "qcom,sdhci-msm-v4";
> +                       reg = <0x7864900 0x11c 0x7864000 0x800>;
> +                       index = <0x1>;
> +                       bus-width = <0x4>;
> +                       clock = <&clkc 1>;
> +                       clock-frequency = <200000000>;
> +               };
> +
> +               spmi at 200f000 {
> +                       compatible = "qcom,spmi-pmic-arb";
> +                       reg = <0x200f800 0x200 0x2400000 0x400000 0x2c00000 0x400000>;
> +                       #address-cells = <0x1>;
> +                       #size-cells = <0x1>;
> +                       pm8916 at 0 {
> +                               compatible = "qcom,spmi-pmic";
> +                               reg = <0x0 0x1>;
> +                               #address-cells = <0x1>;
> +                               #size-cells = <0x1>;
> +
> +                               pmic_pon: pon at 800 {
> +                                       compatible = "qcom,pm8916-pwrkey";
> +                                       reg = <0x800 0x96>;
> +                                       #gpio-cells = <2>;
> +                                       gpio-controller;
> +                               };
> +
> +                               pmic_gpios: gpios at c000 {
> +                                       compatible = "qcom,pm8916-gpio";
> +                                       reg = <0xc000 0x400>;
> +                                       gpio-controller;
> +                                       gpio-count = <4>;
> +                                       #gpio-cells = <2>;
> +                                       gpio-bank-name="pmic";
> +                               };
> +                       };
> +
> +                       pm8916 at 1 {
> +                               compatible = "qcom,spmi-pmic";
> +                               reg = <0x1 0x1>;
> +                       };
> +               };
> +       };
> +
> +       leds {
> +               compatible = "gpio-leds";
> +               user1 {
> +                       label = "green:user1";
> +                       gpios = <&soc_gpios 21 0>;
> +               };
> +
> +               user2 {
> +                       label = "green:user2";
> +                       gpios = <&soc_gpios 120 0>;
> +               };
> +
> +               user3 {
> +                       label = "green:user3";
> +                       gpios = <&pmic_gpios 0 0>;
> +               };
> +
> +               user4 {
> +                       label = "green:user4";
> +                       gpios = <&pmic_gpios 1 0>;
> +               };
> +       };
> +
> +       usb_hub_reset_n_pm {
> +               gpios = <&pmic_gpios 2 0>;
> +       };
> +
> +       usb_sw_sel_pm {
> +               gpios = <&pmic_gpios 3 0>;
> +       };
> +
> +       key_vol_down {
> +               gpios = <&pmic_pon 1 0>;
> +       };
> +
> +       key_power {
> +               gpios = <&pmic_pon 0 0>;
> +       };
> +};
> diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig
> index 156e733..dc7ba21 100644
> --- a/arch/arm/mach-snapdragon/Kconfig
> +++ b/arch/arm/mach-snapdragon/Kconfig
> @@ -3,4 +3,24 @@ if ARCH_SNAPDRAGON
>  config SYS_SOC
>         default "snapdragon"
>
> +choice
> +       prompt "Snapdragon board select"
> +
> +config TARGET_DRAGONBOARD410C
> +       bool "96Boards Dragonboard 410C"
> +       help
> +         Support for 96Boards Dragonboard 410C. This board complies with
> +         96Board Open Platform Specifications. Features:
> +         - Qualcomm Snapdragon 410C SoC - APQ8016 (4xCortex A53, Adreno 306)
> +         - 1GiB RAM
> +         - 8GiB eMMC, uSD slot
> +         - WiFi, Bluetooth and GPS module
> +         - 2x Host, 1x Device USB port
> +         - HDMI
> +         - 20-pin low speed and 40-pin high speed expanders, 4 LED, 3 buttons
> +
> +endchoice
> +
> +source "board/qualcomm/dragonboard410c/Kconfig"
> +
>  endif
> diff --git a/board/qualcomm/dragonboard410c/Kconfig b/board/qualcomm/dragonboard410c/Kconfig
> new file mode 100644
> index 0000000..03bd7ae
> --- /dev/null
> +++ b/board/qualcomm/dragonboard410c/Kconfig
> @@ -0,0 +1,15 @@
> +if TARGET_DRAGONBOARD410C
> +
> +config SYS_BOARD
> +       default "dragonboard410c"
> +
> +config SYS_VENDOR
> +       default "qualcomm"
> +
> +config SYS_SOC
> +       default "apq8016"
> +
> +config SYS_CONFIG_NAME
> +       default "dragonboard410c"
> +
> +endif
> diff --git a/board/qualcomm/dragonboard410c/Makefile b/board/qualcomm/dragonboard410c/Makefile
> new file mode 100644
> index 0000000..cd67808
> --- /dev/null
> +++ b/board/qualcomm/dragonboard410c/Makefile
> @@ -0,0 +1,8 @@
> +#
> +# (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> +#
> +# SPDX-License-Identifier:     GPL-2.0+
> +#
> +
> +obj-y  := dragonboard410c.o
> +extra-y += head.o
> diff --git a/board/qualcomm/dragonboard410c/dragonboard410c.c b/board/qualcomm/dragonboard410c/dragonboard410c.c
> new file mode 100644
> index 0000000..5ca9659
> --- /dev/null
> +++ b/board/qualcomm/dragonboard410c/dragonboard410c.c
> @@ -0,0 +1,111 @@
> +/*
> + * Board init file for Dragonboard 410C
> + *
> + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> +
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <usb.h>
> +#include <asm/gpio.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +int dram_init(void)
> +{
> +       gd->ram_size = PHYS_SDRAM_1_SIZE;
> +       return 0;
> +}
> +
> +void dram_init_banksize(void)
> +{
> +       gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
> +       gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
> +}
> +
> +
> +int board_prepare_usb(enum usb_init_type type)
> +{
> +       static struct gpio_desc hub_reset, usb_sel;
> +       int ret = 0, node;
> +
> +       /* Try to request gpios needed to start usb host on dragonboard */
> +       if (!dm_gpio_is_valid(&hub_reset)) {
> +               node = fdt_subnode_offset(gd->fdt_blob, 0,
> +                                         "usb_hub_reset_n_pm");
> +               if (node < 0) {
> +                       printf("Failed to find usb_hub_reset_n_pm dt node.\n");
> +                       return node;
> +               }
> +               ret = gpio_request_by_name_nodev(gd->fdt_blob, node, "gpios", 0,
> +                                                &hub_reset, 0);
> +               if (ret < 0) {
> +                       printf("Failed to request usb_hub_reset_n_pm gpio.\n");
> +                       return ret;
> +               }
> +       }
> +
> +       if (!dm_gpio_is_valid(&usb_sel)) {
> +               node = fdt_subnode_offset(gd->fdt_blob, 0, "usb_sw_sel_pm");
> +               if (node < 0) {
> +                       printf("Failed to find usb_sw_sel_pm dt node.\n");
> +                       return 0;
> +               }
> +               ret = gpio_request_by_name_nodev(gd->fdt_blob, node, "gpios", 0,
> +                                                &usb_sel, 0);
> +               if (ret < 0) {
> +                       printf("Failed to request usb_sw_sel_pm gpio.\n");
> +                       return ret;
> +               }
> +       }
> +
> +       if (type == USB_INIT_HOST) {
> +               /* Start USB Hub */
> +               dm_gpio_set_dir_flags(&hub_reset,
> +                                     GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
> +               mdelay(100);
> +               /* Switch usb to host connectors */
> +               dm_gpio_set_dir_flags(&usb_sel,
> +                                     GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
> +               mdelay(100);
> +       } else { /* Device */
> +               /* Disable hub */
> +               dm_gpio_set_dir_flags(&hub_reset, GPIOD_IS_OUT);
> +               /* Switch back to device connector */
> +               dm_gpio_set_dir_flags(&usb_sel, GPIOD_IS_OUT);
> +       }
> +       return 0;
> +}
> +
> +int board_init(void)
> +{
> +       return 0;
> +}
> +
> +/* Check for vol- button - if pressed - stop autoboot */
> +int misc_init_r(void)
> +{
> +       int node;
> +       struct gpio_desc resin;
> +
> +       node = fdt_subnode_offset(gd->fdt_blob, 0, "key_vol_down");
> +       if (node < 0) {
> +               printf("Failed to find key_vol_down node. Check device tree\n");
> +               return 0;
> +       }
> +
> +       if (gpio_request_by_name_nodev(gd->fdt_blob, node, "gpios", 0, &resin,
> +                                      0)) {
> +               printf("Failed to request key_vol_down button.\n");
> +               return 0;
> +       }
> +
> +       if (dm_gpio_get_value(&resin)) {
> +               setenv("bootdelay", "-1");
> +               printf("Power button pressed - dropping to console.\n");
> +       }
> +
> +       return 0;
> +}
> diff --git a/board/qualcomm/dragonboard410c/head.S b/board/qualcomm/dragonboard410c/head.S
> new file mode 100644
> index 0000000..00d6d97
> --- /dev/null
> +++ b/board/qualcomm/dragonboard410c/head.S
> @@ -0,0 +1,20 @@
> +#include <config.h>
> +
> +.global _fastboot_header
> +_fastboot_header:
> +       b _start
> +       add     x13, x18, #0x16
> +       // Image load offset from start of RAM, little-endian
> +       .quad   CONFIG_SYS_TEXT_BASE-PHYS_SDRAM_1
> +       // Effective size of kernel image, little-endian
> +       .quad   0 //0x60000
> +       // Informative flags, little-endian
> +       .quad   0
> +       .quad   0                               // reserved
> +       .quad   0                               // reserved
> +       .quad   0                               // reserved
> +       .byte   0x41                            // Magic number, "ARM\x64"
> +       .byte   0x52
> +       .byte   0x4d
> +       .byte   0x64
> +       .word   0                               // reserved
> diff --git a/board/qualcomm/dragonboard410c/readme.txt b/board/qualcomm/dragonboard410c/readme.txt
> new file mode 100644
> index 0000000..0f575db
> --- /dev/null
> +++ b/board/qualcomm/dragonboard410c/readme.txt
> @@ -0,0 +1,40 @@
> +#
> +# (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> +#
> +# SPDX-License-Identifier:     GPL-2.0+
> +#
> +
> +Build & Run instructions:
> +
> +1) Install mkbootimg from git://codeaurora.org/quic/kernel/skales (15ece94f09 worked for me)
> +2) Setup CROSS_COMPILE to aarch64 compiler
> +3) make dragonboard410c_config
> +4) make
> +5) generate fake, empty ramdisk (can have 0 bytes)
> +$ touch rd
> +
> +6) generate qualcomm device tree, use dtbTool to generate it
> +$ dtbTool -o dt.img arch/arm/dts

What is this file?

> +
> +7) generate image with mkbootimg:
> +$ mkbootimg --kernel=u-boot-dtb.bin --output=u-boot.img --dt=dt.img  --pagesize 2048 --base 0x80000000 --ramdisk=rd --cmdline=""

Is it possible to add this functionality to mkimage? Is this building
a fastboot image?

> +
> +Boot it with fastboot:
> +fastboot boot u-boot.img
> +or flash as kernel:
> +fastboot flash boot u-boot.img
> +fastboot reboot
> +
> +
> +What is working:
> +- UART
> +- GPIO (SoC)
> +- SD
> +- eMMC
> +- Reset
> +- USB in EHCI mode (usb starts does switch device->host, usb stop does the opposite)
> +- PMIC GPIOS (but not in generic subsystem)
> +- PMIC "special" buttons (power, vol-)
> +
> +What is not working / known bugs:
> +- SDHCI is slow (~2.5MiB/s for SD and eMMC)

[snip]

Regards,
Simon

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

* [U-Boot] [PATCH v1 16/16] board: Add Qualcomm Dragonboard 410C support
  2016-01-13 20:32       ` Simon Glass
@ 2016-01-20 21:46         ` Mateusz Kulikowski
  0 siblings, 0 replies; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-20 21:46 UTC (permalink / raw)
  To: u-boot

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Hi Simon,

On 13.01.2016 21:32, Simon Glass wrote:
[...]
> On 11 January 2016 at 15:01, Mateusz Kulikowski
> <mateusz.kulikowski@gmail.com> wrote:
[...]

>> &pm8916_gpios {
>>
>>         usb_hub_reset_pm: usb_hub_reset_pm {
>>                 pinconf {
>>                         pins = "gpio3";
>>                         function = PMIC_GPIO_FUNC_NORMAL;
>>                         output-low;
>>                 };
>>         };
>>
>> (https://github.com/torvalds/linux/blob/master/arch/arm64/boot/dts/qcom/apq8016-sbc-pmic-pins.dtsi)
>>
>> I decided to move them away from PMIC, as they only use specific gpios.
>>
>> To be honest they are just a references so I don't have to hardcode gpio names/numbers in
>> board sources.
>>
>> Is it ok if I keep it that way? Could you suggest better approach?
> 
> We should avoid forking the device tree and making up bindings.
> 
> Really it looks like qcom,qpnp-pin should be a pinctrl driver. Then
> pinctrl-0 in your device node will automatically pick up the correct
> function.

I gave it a bit thought played a bit (perhaps small bit) with pinctl, 
did Phone-a-Friend, looked at rockchip @ your tree and:

1. I agree that it's good idea to have the same bindings in U-Boot & Linux.

2. Perhaps in "generic" solution (say for all qcom pmics) it would be nice 
to have possibility to configure some functions of this pins, but all I need 
for now is to change value of 2 gpio pins to 1/0. 

3. Learning/writing "proper" pinctrl driver will take me some time (and probably
few patch versions).

4. In my (very) humble opinion, there are few improvements that I consider more important 
and would like to do first (for example usb device controller or ADMA support for sdhci).
Also Syed would probably like to have support for his Dragonboard 810 that is 
similar (and kind-of blocked by this release).

My proposal is to use mainline Linux entries for hub/switch pins and then do 
addition as in (for example) exynos 4210: 
add dragonboard410c-uboot.dtsi that will have u-boot specific extension.
In this case - gpio handle so I can query gpio the same way I did in the past.

Of course I will upgrade dt bindings documentation.

And in future I will have to master pinmux/pinctrl as I will need it to get 
rid of Little Kernel (and do pin configuration for UART, MMC etc.) - I can then
"upgrade" this code.


Just FYI: I don't plan to abandon board the day it gets to mainline ;)

Regards,
Mateusz

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQEcBAEBCAAGBQJWoAAYAAoJELvtohmVtQzBKi8H/0QVrJH+aeDL59G/fOrXMzk5
uPeNAJJ4nEmp2ueLZ5LIZp3fgvMiTre70WjpiWrt521o1HchZ4IjRwh76RWI4Svy
jd12u4PgTnEOYAUDxYIuxS3rePE7dgDbdjWNoU4pjlG9uq+oK4w1QoYGVgbmTiF9
3EnhgIp+FY8dilkfpFp8rPLLH2xbdFwOhzJ2BSTJzt/ubMzHYDKYM/6QTRiuLHoC
ndfKnVPP2vrLLbQIQKkNyHGOgYvyJSWx9oTrDu0Pkoq09heGvcksio1t8AKZDyUH
RNFB2LPvU/wcYjf5NmF0nYHpgB/mwq9bG/PFkGNoi74/jEPtN9+mFZNah8XBB+g=
=okES
-----END PGP SIGNATURE-----

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

* [U-Boot] [PATCH v1 16/16] board: Add Qualcomm Dragonboard 410C support
  2016-01-20  4:35   ` Simon Glass
@ 2016-01-20 22:00     ` Mateusz Kulikowski
  2016-01-20 23:49       ` Andreas Färber
  0 siblings, 1 reply; 49+ messages in thread
From: Mateusz Kulikowski @ 2016-01-20 22:00 UTC (permalink / raw)
  To: u-boot

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Hi (again),

On 20.01.2016 05:35, Simon Glass wrote:
> On 6 January 2016 at 11:21, Mateusz Kulikowski
> <mateusz.kulikowski@gmail.com> wrote:

> 
> Can you please add a MAINTAINERS file also?
Of course, 

I will also add myself somewhere as a maintainer for SPMI/SoC and all the drivers that I did
(at least if it will be possible).

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

Great! 

>> +       .quad   0                               // reserved
>> +       .quad   0                               // reserved
>> +       .quad   0                               // reserved
>> +       .byte   0x41                            // Magic number, "ARM\x64"
>> +       .byte   0x52
>> +       .byte   0x4d
>> +       .byte   0x64
>> +       .word   0                               // reserved
>> diff --git a/board/qualcomm/dragonboard410c/readme.txt b/board/qualcomm/dragonboard410c/readme.txt
>> new file mode 100644
>> index 0000000..0f575db
>> --- /dev/null
>> +++ b/board/qualcomm/dragonboard410c/readme.txt
>> @@ -0,0 +1,40 @@
>> +#
>> +# (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
>> +#
>> +# SPDX-License-Identifier:     GPL-2.0+
>> +#
>> +
>> +Build & Run instructions:
>> +
>> +1) Install mkbootimg from git://codeaurora.org/quic/kernel/skales (15ece94f09 worked for me)
>> +2) Setup CROSS_COMPILE to aarch64 compiler
>> +3) make dragonboard410c_config
>> +4) make
>> +5) generate fake, empty ramdisk (can have 0 bytes)
>> +$ touch rd
>> +
>> +6) generate qualcomm device tree, use dtbTool to generate it
>> +$ dtbTool -o dt.img arch/arm/dts
> 
> What is this file?

This tool that packs device tree into some proprietary (qcom) format.

Both (with ramdisk) must be in boot image (below) otherwise Little Kernel will refuse to load it.

It seems (although I'm not an Android guy) Litlle Kernel is unable to accept the fact that 
kernel image may not need ramdisk (or device tree).

> 
>> +
>> +7) generate image with mkbootimg:
>> +$ mkbootimg --kernel=u-boot-dtb.bin --output=u-boot.img --dt=dt.img  --pagesize 2048 --base 0x80000000 --ramdisk=rd --cmdline=""
> 
> Is it possible to add this functionality to mkimage? Is this building
> a fastboot image?

Yes, it's building fastboot/Android image; It even adds nice "ANDROID!" string in binary.

It probably can be added to u-boot build system, but I'm not sure if we really want it -
at least for the dragonboard my goal is to get rid of Little Kernel.


Regards,
Mateusz

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQEcBAEBCAAGBQJWoANoAAoJELvtohmVtQzBH6wH/2eRPDryFshrkshRoH9R7GZg
qoFk4UbHoSIh8+JpD2OsHAJI6SBao9Z/0bzdTm+7gLU7+tf8pYeU32/fzFGBjRCo
Tvm/mBMJaz55SRWWdAdeNaCQEO/cG+B2PuZeZTur0buiJymDdQ8QeIEz2Treah1P
CJ1XTsKWBdlJWjkQYnZ+JYTS4nlolK0P0FIVNavWEYtlgVmOidJRBJLFMjJ8dGaa
VhR/W1/hboTFN6QBwiBuo/36jX2Sobj4HJ1VHJ/hvNH3QzBtG+n/64Gi5bctPrWp
LKyuq0ZA15z1PquG9XrhYc8LoYgJyvfQhTAPh4cPn5zRPme/SMeIxAsQ5BR1U0s=
=1PpF
-----END PGP SIGNATURE-----

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

* [U-Boot] [PATCH v1 16/16] board: Add Qualcomm Dragonboard 410C support
  2016-01-20 22:00     ` Mateusz Kulikowski
@ 2016-01-20 23:49       ` Andreas Färber
  0 siblings, 0 replies; 49+ messages in thread
From: Andreas Färber @ 2016-01-20 23:49 UTC (permalink / raw)
  To: u-boot

Hi Mateusz,

Am 20.01.2016 um 23:00 schrieb Mateusz Kulikowski:
> On 20.01.2016 05:35, Simon Glass wrote:
>> Tested-by: Simon Glass <sjg@chromium.org>
> 
> Great! 

Which Git branch can we use to test this? I spotted no final v1 branch
matching this series. Among others, I tried your
dragonboard-for-mainline-v2 branch but that reboots after:

U-Boot 2016.01-01877-gb3bcc5a (Jan 20 2016 - 23:11:25 +0100)
Qualcomm-DragonBoard 410C

DRAM:  986 MiB
pm8916_probe()
pm8916_gpio_probe():220 00000000bd15f460 c000
pm8916_probe()

If I revert the last "WIP pinctrl" patch then it proceeds to:

U-Boot 2016.01-01878-g6f1bb04 (Jan 21 2016 - 00:27:37 +0100)
Qualcomm-DragonBoard 410C

DRAM:  986 MiB
MMC:   sdhci at 07824000: 0, sdhci at 07864000: 1
Using default environment

In:    serial at 78b0000
Out:   serial at 78b0000
Err:   serial at 78b0000

but again reboots without reaching a prompt. Is either working for you?

Regards,
Andreas

-- 
SUSE Linux GmbH, Maxfeldstr. 5, 90409 N?rnberg, Germany
GF: Felix Imend?rffer, Jane Smithard, Graham Norton; HRB 21284 (AG N?rnberg)

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

end of thread, other threads:[~2016-01-20 23:49 UTC | newest]

Thread overview: 49+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-06 18:21 [U-Boot] [PATCH v1 00/16] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
2016-01-06 18:21 ` [U-Boot] [PATCH v1 01/16] serial: Add support for Qualcomm serial port Mateusz Kulikowski
2016-01-11 16:57   ` Simon Glass
2016-01-06 18:21 ` [U-Boot] [PATCH v1 02/16] gpio: Add support for Qualcomm gpio controller Mateusz Kulikowski
2016-01-11 16:57   ` Simon Glass
2016-01-11 21:27     ` Mateusz Kulikowski
2016-01-06 18:21 ` [U-Boot] [PATCH v1 03/16] mmc: Add support for Qualcomm SDHCI controller Mateusz Kulikowski
2016-01-11 16:57   ` Simon Glass
2016-01-06 18:21 ` [U-Boot] [PATCH v1 04/16] ehci-hcd: Add init_after_reset Mateusz Kulikowski
2016-01-11 16:57   ` Simon Glass
2016-01-06 18:21 ` [U-Boot] [PATCH v1 05/16] usb: ulpi: Add Kconfig options for ULPI Mateusz Kulikowski
2016-01-06 20:49   ` Marek Vasut
2016-01-07 22:12     ` Mateusz Kulikowski
2016-01-07 22:50       ` Marek Vasut
2016-01-07 23:18       ` Simon Glass
2016-01-11 21:30         ` Mateusz Kulikowski
2016-01-06 18:21 ` [U-Boot] [PATCH v1 06/16] usb: Rename ehci-fsl.h to ehci-ci.h Mateusz Kulikowski
2016-01-06 20:51   ` Marek Vasut
2016-01-06 18:21 ` [U-Boot] [PATCH v1 07/16] usb: ehci-ci: Add missing registers Mateusz Kulikowski
2016-01-06 20:53   ` Marek Vasut
2016-01-06 18:21 ` [U-Boot] [PATCH v1 08/16] ehci-ci.h: drop generic USBCMD fields Mateusz Kulikowski
2016-01-06 20:54   ` Marek Vasut
2016-01-06 18:21 ` [U-Boot] [PATCH v1 09/16] ehci: Add support for Qualcomm EHCI Mateusz Kulikowski
2016-01-06 21:04   ` Marek Vasut
2016-01-11 21:39     ` Mateusz Kulikowski
2016-01-11 22:02       ` Marek Vasut
2016-01-06 18:21 ` [U-Boot] [PATCH v1 10/16] drivers: Add SPMI bus uclass Mateusz Kulikowski
2016-01-11 16:57   ` Simon Glass
2016-01-11 21:41     ` Mateusz Kulikowski
2016-01-06 18:21 ` [U-Boot] [PATCH v1 11/16] spmi: Add sandbox test driver Mateusz Kulikowski
2016-01-11 16:57   ` Simon Glass
2016-01-06 18:21 ` [U-Boot] [PATCH v1 12/16] drivers: spmi: Add support for Qualcomm SPMI bus driver Mateusz Kulikowski
2016-01-11 16:57   ` Simon Glass
2016-01-06 18:21 ` [U-Boot] [PATCH v1 13/16] pmic: Add support for Qualcomm PM8916 PMIC Mateusz Kulikowski
2016-01-11 16:58   ` Simon Glass
2016-01-06 18:21 ` [U-Boot] [PATCH v1 14/16] gpio: Add support for Qualcomm PM8916 gpios Mateusz Kulikowski
2016-01-11 16:58   ` Simon Glass
2016-01-06 18:21 ` [U-Boot] [PATCH v1 15/16] arm: Add support for Qualcomm Snapdragon family Mateusz Kulikowski
2016-01-11 16:58   ` Simon Glass
2016-01-06 18:21 ` [U-Boot] [PATCH v1 16/16] board: Add Qualcomm Dragonboard 410C support Mateusz Kulikowski
2016-01-07 10:23   ` Sjoerd Simons
2016-01-11 21:49     ` Mateusz Kulikowski
2016-01-11 16:58   ` Simon Glass
2016-01-11 22:01     ` Mateusz Kulikowski
2016-01-13 20:32       ` Simon Glass
2016-01-20 21:46         ` Mateusz Kulikowski
2016-01-20  4:35   ` Simon Glass
2016-01-20 22:00     ` Mateusz Kulikowski
2016-01-20 23:49       ` Andreas Färber

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.