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

Hi All,

With a slight delay (Sorry Syed) I'm finally ready to show code
I've been working recently on.

This series add support for:
- New board - 96board Dragonboard 410C (ARMv8)
- Qualcomm snapdragon architecture (for now only single SoC)
- Some Qualcomm peripherals (UART, GPIO, PMIC including bus, SDHCI, USB...)
- New bus (SPMI)
- It also adds minor function to ehci HCD

Please take a look at it and give me feedback what can be changed so
it will be ready for submission.

I'd like to thank Przemyslaw Marczak for doing initial reviews and
helping me figure out what is the best approach in some cases.

Notes/Design decisions I made/Issues I have/had (please comment them as well)
0) If I missed someone on CC - please let me know;
   If I misused patman - apologize for that - It's my first time with patman.

1) Documentation is missing - dt-bindings, spmi bus documentation.
   I left it as I expect some redesign after your review.

2) I tried to use DM and Kconfig where possible, but some drivers (USB)
   depend on subsystems that don't support Kconfig yet

3) There are 3 long-line warnings and some complains about too short Kconfig
   - is it ok to ignore lines that are 1-2 characters longer (and
   making them shorter will cause code to be less readable)?

4) Licensing (@trini)
   My code is based on 2 trees:
   Linux: https://git.linaro.org/landing-teams/working/qualcomm/kernel.git
   LittleKernel: https://git.linaro.org/people/nicolas.dechesne/lk.git
   One is GPLv2, other BSD(-clause3 I think).
   When tried to figure out how to write drivers, I looked at both drivers,
   and even if some drivers are totally different than their originals,
   they are derivative work.
   I decided to use Linux license where possible (where I was almost sure
   I copied/analyzed Linux drivers), left BSD only for SPMI code.
   Is it ok? Or should I run tool like Protex and drop references where
   code no longer matches linux/lk codebase (not that I have Protex at home)

5) Clock mapping - I need advice on how to properly access clock controller
   from devices that need some clocks to be enabled. I want clock controller
   code to be as simple as possible, but am not sure how to add links to
   a specific clocks.

6) SPMI: I decided to add new bus. Contrary to other vendors, Qualcomm
   SoCs use SPMI to talk with PMICs. This is "closed" bus (you need
   to pay membership to get specification), and I need it to properly
   describe pmics inside device tree.

7) Snapdragon mach: I added new MACH as my plan is to support more than
   one Qualcomm SoC/board - hopefully days where U-Boot had no Qualcomm support
   will be over soon :)

8) I didn't modified Maintainers files - will do that for PATCH v1

9) I moved register offsets to driver files (didn't put them in one big header
   file. I know it's not common but IMO it's better if drivers are
   self contained (and there are not many registers anyways).

10) Compilation causes 8 warnings, none in my code:
  - 1x in asix88179 driver (format %u expects...)
  - 7x in ulpi-viewport code
  The problem is - this drivers are handling poorly ARMv8 processors,
  where sizeof(int) < sizeof(void*) and
  sizeof(int) < sizeof(long).
  Fix for asix would be trivial, with ULPI it's worse as in my opinion
  it needs slight redesign (use phaddr_t or something).
  Is it ok if I redesign that? Or just ignore warnings or write
  my own ulpi code (I wanted to avoid code duplication)

Best Regards,
Mateusz


Mateusz Kulikowski (11):
  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
  ehci: Add support for Qualcomm EHCI
  drivers: Add SPMI bus uclass
  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                   | 157 +++++++++++
 arch/arm/mach-snapdragon/Kconfig                   |  15 +
 arch/arm/mach-snapdragon/Makefile                  |   8 +
 arch/arm/mach-snapdragon/clock-apq8016.c           | 262 ++++++++++++++++++
 arch/arm/mach-snapdragon/include/mach/gpio.h       |  25 ++
 .../mach-snapdragon/include/mach/sysmap-apq8016.h  |  15 +
 arch/arm/mach-snapdragon/reset.c                   |  40 +++
 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                  |  29 ++
 drivers/Kconfig                                    |   2 +
 drivers/Makefile                                   |   1 +
 drivers/gpio/Kconfig                               |  14 +
 drivers/gpio/Makefile                              |   3 +-
 drivers/gpio/msm_gpio.c                            | 115 ++++++++
 drivers/gpio/pm8916_gpio.c                         | 306 +++++++++++++++++++++
 drivers/mmc/Kconfig                                |   6 +
 drivers/mmc/Makefile                               |   1 +
 drivers/mmc/msm_sdhci.c                            | 149 ++++++++++
 drivers/power/pmic/Kconfig                         |  14 +
 drivers/power/pmic/Makefile                        |   1 +
 drivers/power/pmic/pm8916.c                        |  92 +++++++
 drivers/serial/Kconfig                             |   5 +
 drivers/serial/Makefile                            |   1 +
 drivers/serial/serial_msm.c                        | 204 ++++++++++++++
 drivers/spmi/Kconfig                               |  16 ++
 drivers/spmi/Makefile                              |   8 +
 drivers/spmi/spmi-msm.c                            | 183 ++++++++++++
 drivers/spmi/spmi-uclass.c                         |  53 ++++
 drivers/usb/host/Kconfig                           |   8 +
 drivers/usb/host/Makefile                          |   1 +
 drivers/usb/host/ehci-hcd.c                        |   6 +
 drivers/usb/host/ehci-msm.c                        | 198 +++++++++++++
 drivers/usb/host/ehci.h                            |   1 +
 include/configs/dragonboard410c.h                  | 184 +++++++++++++
 include/dm/uclass-id.h                             |   1 +
 include/spmi/spmi.h                                |  44 +++
 44 files changed, 2466 insertions(+), 1 deletion(-)
 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 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-uclass.c
 create mode 100644 drivers/usb/host/ehci-msm.c
 create mode 100644 include/configs/dragonboard410c.h
 create mode 100644 include/spmi/spmi.h

-- 
2.5.0

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

* [U-Boot] [RFC PATCH 01/11] serial: Add support for Qualcomm serial port
  2015-12-10 21:41 [U-Boot] [RFC PATCH 00/11] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
@ 2015-12-10 21:41 ` Mateusz Kulikowski
  2015-12-15 18:58   ` Simon Glass
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 02/11] gpio: Add support for Qualcomm gpio controller Mateusz Kulikowski
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-10 21:41 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>
---

 drivers/serial/Kconfig      |   5 ++
 drivers/serial/Makefile     |   1 +
 drivers/serial/serial_msm.c | 204 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 210 insertions(+)
 create mode 100644 drivers/serial/serial_msm.c

diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 1fc287e..f28c093 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -223,4 +223,9 @@ 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.
 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..13dad33
--- /dev/null
+++ b/drivers/serial/serial_msm.c
@@ -0,0 +1,204 @@
+/*
+ * 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 <asm/io.h>
+#include <common.h>
+#include <dm.h>
+#include <clk.h>
+#include <errno.h>
+#include <linux/compiler.h>
+#include <serial.h>
+#include <watchdog.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);
+	unsigned sr;
+	char c;
+
+	/* There was something buffered */
+	if (p->chars_cnt) {
+		c = p->chars_buf & 0xFF;
+		p->chars_buf >>= 8;
+		p->chars_cnt--;
+		return c;
+	}
+
+	/* 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);
+
+	/* There are at least 4 bytes in fifo */
+	if (sr & UARTDM_SR_RX_READY) {
+		p->chars_buf = readl(p->base + UARTDM_RF);
+		c = p->chars_buf & 0xFF;
+		p->chars_cnt = 3; /* 4 - one read */
+		p->chars_buf >>= 8;
+		return c;
+	}
+
+	/* 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 */
+	fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "clock", clkd, 2);
+	clkd[0] = fdt_node_offset_by_phandle(gd->fdt_blob, clkd[0]);
+
+	struct udevice *clk = NULL;
+	uclass_get_device_by_of_offset(UCLASS_CLK, clkd[0], &clk);
+	if (clk)
+		clk_set_periph_rate(clk, clkd[1], clk_rate);
+
+	return 0;
+}
+
+static int msm_serial_probe(struct udevice *dev)
+{
+	struct msm_serial_data *p = dev_get_priv(dev);
+
+	msm_uart_clk_init(dev);
+
+	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);
+
+	p->chars_buf = 0;
+	p->chars_cnt = 0;
+	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,
+	.flags = DM_FLAG_PRE_RELOC,
+};
-- 
2.5.0

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

* [U-Boot] [RFC PATCH 02/11] gpio: Add support for Qualcomm gpio controller
  2015-12-10 21:41 [U-Boot] [RFC PATCH 00/11] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 01/11] serial: Add support for Qualcomm serial port Mateusz Kulikowski
@ 2015-12-10 21:41 ` Mateusz Kulikowski
  2015-12-15 18:58   ` Simon Glass
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 03/11] mmc: Add support for Qualcomm SDHCI controller Mateusz Kulikowski
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-10 21:41 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>
---

 drivers/gpio/Kconfig    |   7 +++
 drivers/gpio/Makefile   |   2 +-
 drivers/gpio/msm_gpio.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 123 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpio/msm_gpio.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index e60e9fd..1d9443b 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -46,6 +46,13 @@ 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.
+
 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..9bb9e89
--- /dev/null
+++ b/drivers/gpio/msm_gpio.c
@@ -0,0 +1,115 @@
+/*
+ * 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 <asm/gpio.h>
+#include <asm/io.h>
+#include <errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+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 */
+	writel((readl(reg) & ~GPIO_OE_MASK) | GPIO_OE_DISABLE , reg);
+	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 */
+	writel((readl(reg) & ~GPIO_OE_MASK) | GPIO_OE_ENABLE , reg);
+	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" },
+	{ }
+};
+
+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] 43+ messages in thread

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

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

 drivers/mmc/Kconfig     |   6 ++
 drivers/mmc/Makefile    |   1 +
 drivers/mmc/msm_sdhci.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 156 insertions(+)
 create mode 100644 drivers/mmc/msm_sdhci.c

diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index ceae7bc..3f75fa7 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -16,6 +16,12 @@ 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 manufactured by Qualcomm.
+
 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..96119f0
--- /dev/null
+++ b/drivers/mmc/msm_sdhci.c
@@ -0,0 +1,149 @@
+/*
+ * 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 <asm/io.h>
+#include <common.h>
+#include <dm.h>
+#include <linux/bitops.h>
+#include <sdhci.h>
+#include <clk.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_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;
+	phys_addr_t base;
+	unsigned width;
+};
+
+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 */
+	fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "clock", clkd, 2);
+	clkd[0] = fdt_node_offset_by_phandle(gd->fdt_blob, clkd[0]);
+
+	struct udevice *clk = NULL;
+	uclass_get_device_by_of_offset(UCLASS_CLK, clkd[0], &clk);
+	if (clk)
+		clk_set_periph_rate(clk, clkd[1], clk_rate);
+
+	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;
+
+	host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B;
+
+	/* Init clocks */
+	if (msm_sdc_clk_init(dev))
+		return -EIO;
+
+	/* Reset the core and Enable SDHC mode */
+	writel(readl(prv->base + SDCC_MCI_POWER) | SDCC_MCI_POWER_SW_RST,
+	       prv->base + SDCC_MCI_POWER);
+
+	/* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */
+	mdelay(2);
+
+	if (readl(prv->base + SDCC_MCI_POWER) & SDCC_MCI_POWER_SW_RST) {
+		printf("msm_sdhci: stuck in reset\n");
+		return -1;
+	}
+
+	/* 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 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 = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
+						      dev->parent->of_offset,
+						      dev->of_offset, "reg",
+						      1, NULL);
+	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] 43+ messages in thread

* [U-Boot] [RFC PATCH 04/11] ehci-hcd: Add init_after_reset
  2015-12-10 21:41 [U-Boot] [RFC PATCH 00/11] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (2 preceding siblings ...)
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 03/11] mmc: Add support for Qualcomm SDHCI controller Mateusz Kulikowski
@ 2015-12-10 21:41 ` Mateusz Kulikowski
  2015-12-10 23:14   ` Marek Vasut
  2015-12-16 22:30   ` Tom Rini
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 05/11] ehci: Add support for Qualcomm EHCI Mateusz Kulikowski
                   ` (7 subsequent siblings)
  11 siblings, 2 replies; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-10 21:41 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>
---

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

* [U-Boot] [RFC PATCH 05/11] ehci: Add support for Qualcomm EHCI
  2015-12-10 21:41 [U-Boot] [RFC PATCH 00/11] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (3 preceding siblings ...)
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 04/11] ehci-hcd: Add init_after_reset Mateusz Kulikowski
@ 2015-12-10 21:41 ` Mateusz Kulikowski
  2015-12-10 23:22   ` Marek Vasut
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 06/11] drivers: Add SPMI bus uclass Mateusz Kulikowski
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-10 21:41 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>
---

 drivers/usb/host/Kconfig    |   8 ++
 drivers/usb/host/Makefile   |   1 +
 drivers/usb/host/ehci-msm.c | 198 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 207 insertions(+)
 create mode 100644 drivers/usb/host/ehci-msm.c

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 0096a2f..5a63475 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -66,6 +66,14 @@ 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
+	default n
+	---help---
+	  Enables support for the on-chip EHCI controller on Qualcomm
+	  Snapdragon SoCs.
+
 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 0b4b458..d4a556a 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -42,6 +42,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..d17a29a
--- /dev/null
+++ b/drivers/usb/host/ehci-msm.c
@@ -0,0 +1,198 @@
+/*
+ * 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 <asm/gpio.h>
+#include <asm-generic/errno.h>
+#include <linux/compat.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <asm/io.h>
+#include <usb.h>
+#include <usb/ulpi.h>
+#include "ehci.h"
+
+#ifndef CONFIG_USB_ULPI_VIEWPORT
+#error Please enable CONFIG_USB_ULPI_VIEWPORT
+#endif
+
+#define MSM_USB_ULPI_OFFSET 0x170 /* ULPI viewport (PHY) */
+#define MSM_USB_EHCI_OFFSET 0x100 /* Start of EHCI registers */
+
+/* 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)
+
+/* qcom specific registers (OTG) */
+#define USB_GENCONFIG_2      0x00A0
+#define GEN2_SESS_VLD_CTRL_EN (1 << 7)
+
+#define USB_USBCMD           (0x0140)
+#define SESS_VLD_CTRL         (1 << 25)
+#define USBCMD_RESET   2
+#define USBCMD_ATTACH  1
+
+/* USB2_HSIC_USB_OTG_HS_BASE_USB_OTG_HS_PORTSC */
+#define USB_PORTSC           0x0184
+#define USB_SBUSCFG          0x0090
+#define USB_AHB_MODE         0x0098
+
+#define USB_USBMODE          0x01A8
+#define USBMODE_DEVICE 2
+#define USBMODE_HOST   3
+
+struct msm_ehci_priv {
+	struct ehci_ctrl ctrl; /* Needed by EHCI */
+	phys_addr_t base;
+	phys_addr_t ehci_base;
+	u32 ulpi_base;
+	u32 ulpi_port;
+};
+
+int __weak board_prepare_usb(enum usb_init_type type)
+{
+	return 0;
+}
+
+static void setup_usb_phy(struct msm_ehci_priv *priv)
+{
+	struct ulpi_viewport ulpi_vp = {.port_num = priv->ulpi_port,
+					.viewport_addr = priv->ulpi_base};
+
+	/* Select and enable external configuration with USB PHY */
+	ulpi_write(&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)
+{
+	struct ulpi_viewport ulpi_vp = {.port_num = priv->ulpi_port,
+					.viewport_addr = priv->ulpi_base};
+
+	/* Disable VBUS mimicing in the controller. */
+	ulpi_write(&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);
+	uint32_t val;
+
+	/* select ULPI phy */
+	writel(0x80000000, p->base + USB_PORTSC);
+	setup_usb_phy(p);
+
+	/* Enable sess_vld */
+	val = readl(p->base + USB_GENCONFIG_2) | GEN2_SESS_VLD_CTRL_EN;
+	writel(val, p->base + USB_GENCONFIG_2);
+
+	/* Enable external vbus configuration in the LINK */
+	val = readl(p->base + USB_USBCMD);
+	val |= SESS_VLD_CTRL;
+	writel(val, p->base + USB_USBCMD);
+
+	/* USB_OTG_HS_AHB_BURST */
+	writel(0x0, p->base + USB_SBUSCFG);
+
+	/* USB_OTG_HS_AHB_MODE: HPROT_MODE */
+	/* Bus access related config. */
+	writel(0x08, p->base + USB_AHB_MODE);
+
+	/* set mode to host controller */
+	writel(USBMODE_HOST, p->base + USB_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 ehci_hccr *cr;
+	struct ehci_hcor *or;
+	int ret;
+
+	cr = (struct ehci_hccr *)p->ehci_base;
+	or = (struct ehci_hcor *)(p->ehci_base +
+				  HC_LENGTH(readl(p->ehci_base)));
+
+	ret = board_prepare_usb(USB_INIT_HOST);
+	if (ret < 0)
+		return ret;
+
+
+	return ehci_register(dev, cr, or, &msm_ehci_ops, 0, USB_INIT_HOST);
+}
+
+static int ehci_usb_remove(struct udevice *dev)
+{
+	struct msm_ehci_priv *p = dev_get_priv(dev);
+	phys_addr_t reg = p->base + USB_USBCMD;
+	int ret;
+
+	ret = ehci_deregister(dev);
+	if (ret)
+		return ret;
+
+	/* Stop controller. */
+	writel(readl(reg) & ~USBCMD_ATTACH, reg);
+
+	reset_usb_phy(p);
+
+	ret = board_prepare_usb(USB_INIT_DEVICE); /* Board specific hook */
+	if (ret < 0)
+		return ret;
+
+	/* Reset controller */
+	writel(0x00080002, reg); /* reset usb */
+	mdelay(20);
+	/* Wait for completion */
+	while (readl(reg) & 2)
+		;
+
+	return 0;
+}
+
+static int ehci_usb_ofdata_to_platdata(struct udevice *dev)
+{
+	struct msm_ehci_priv *priv = dev_get_priv(dev);
+
+	priv->base = dev_get_addr(dev);
+	priv->ehci_base = priv->base + MSM_USB_EHCI_OFFSET;
+	priv->ulpi_base = priv->base + MSM_USB_ULPI_OFFSET;
+	priv->ulpi_port = 0;
+	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] 43+ messages in thread

* [U-Boot] [RFC PATCH 06/11] drivers: Add SPMI bus uclass
  2015-12-10 21:41 [U-Boot] [RFC PATCH 00/11] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (4 preceding siblings ...)
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 05/11] ehci: Add support for Qualcomm EHCI Mateusz Kulikowski
@ 2015-12-10 21:41 ` Mateusz Kulikowski
  2015-12-15 18:58   ` Simon Glass
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 07/11] drivers: spmi: Add support for Qualcomm SPMI bus driver Mateusz Kulikowski
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-10 21:41 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>
---

 drivers/Kconfig            |  2 ++
 drivers/Makefile           |  1 +
 drivers/spmi/Kconfig       | 10 +++++++++
 drivers/spmi/Makefile      |  7 ++++++
 drivers/spmi/spmi-uclass.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h     |  1 +
 include/spmi/spmi.h        | 44 ++++++++++++++++++++++++++++++++++++++
 7 files changed, 118 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..2d8d78b
--- /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..981da68
--- /dev/null
+++ b/drivers/spmi/spmi-uclass.c
@@ -0,0 +1,53 @@
+/*
+ * SPMI bus uclass driver
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <dm/root.h>
+#include <vsprintf.h>
+#include <dm/lists.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+#include <linux/ctype.h>
+#include <spmi/spmi.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 msm_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	= msm_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..e06a79e
--- /dev/null
+++ b/include/spmi/spmi.h
@@ -0,0 +1,44 @@
+#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
+ * @write:     write register
+ */
+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] 43+ messages in thread

* [U-Boot] [RFC PATCH 07/11] drivers: spmi: Add support for Qualcomm SPMI bus driver
  2015-12-10 21:41 [U-Boot] [RFC PATCH 00/11] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (5 preceding siblings ...)
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 06/11] drivers: Add SPMI bus uclass Mateusz Kulikowski
@ 2015-12-10 21:41 ` Mateusz Kulikowski
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 08/11] pmic: Add support for Qualcomm PM8916 PMIC Mateusz Kulikowski
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-10 21:41 UTC (permalink / raw)
  To: u-boot

Support SPMI arbiter on Qualcomm Snapdragon devices.

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

 drivers/spmi/Kconfig    |   6 ++
 drivers/spmi/Makefile   |   1 +
 drivers/spmi/spmi-msm.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 190 insertions(+)
 create mode 100644 drivers/spmi/spmi-msm.c

diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
index 2d8d78b..4f17df0 100644
--- a/drivers/spmi/Kconfig
+++ b/drivers/spmi/Kconfig
@@ -7,4 +7,10 @@ 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_MSM
+	boolean "Support Qualcomm SPMI bus"
+	depends on DM_SPMI
+	---help---
+	Support SPMI implementation found on Qualcomm Snapdragon SoCs.
 endmenu
diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
index 2015b1a..419fe1d 100644
--- a/drivers/spmi/Makefile
+++ b/drivers/spmi/Makefile
@@ -5,3 +5,4 @@
 #
 
 obj-$(CONFIG_DM_SPMI)  += spmi-uclass.o
+obj-$(CONFIG_SPMI_MSM) += spmi-msm.o
diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c
new file mode 100644
index 0000000..6781a92
--- /dev/null
+++ b/drivers/spmi/spmi-msm.c
@@ -0,0 +1,183 @@
+/*
+ * 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 <asm/io.h>
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <spmi/spmi.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define ARB_CHANNEL_OFFSET(n)		(0x800 + 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_core; /* ARB Core 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 msm_spmi_priv *priv = dev_get_priv(dev);
+	int i;
+
+	priv->arb_core = dev_get_addr(dev);
+	priv->spmi_core = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
+							   dev->parent->of_offset,
+							   dev->of_offset, "reg",
+							   1, NULL);
+	priv->spmi_obs = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
+							  dev->parent->of_offset,
+							  dev->of_offset, "reg",
+							  2, NULL);
+
+	/* Scan peripherals connected to each SPMI channel */
+	for (i = 0; i < SPMI_MAX_CHANNELS ; i++) {
+		uint32_t periph = readl(priv->arb_core + 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] 43+ messages in thread

* [U-Boot] [RFC PATCH 08/11] pmic: Add support for Qualcomm PM8916 PMIC
  2015-12-10 21:41 [U-Boot] [RFC PATCH 00/11] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (6 preceding siblings ...)
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 07/11] drivers: spmi: Add support for Qualcomm SPMI bus driver Mateusz Kulikowski
@ 2015-12-10 21:41 ` Mateusz Kulikowski
  2015-12-15 18:58   ` Simon Glass
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 09/11] gpio: Add support for Qualcomm PM8916 gpios Mateusz Kulikowski
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-10 21:41 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>
---

 drivers/power/pmic/Kconfig  | 14 +++++++
 drivers/power/pmic/Makefile |  1 +
 drivers/power/pmic/pm8916.c | 92 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 107 insertions(+)
 create mode 100644 drivers/power/pmic/pm8916.c

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..5fe50ef
--- /dev/null
+++ b/drivers/power/pmic/pm8916.c
@@ -0,0 +1,92 @@
+/*
+ * 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 <asm/io.h>
+#include <linux/bitops.h>
+#include <power/pmic.h>
+#include <spmi/spmi.h>
+#include <asm/gpio.h>
+#include <dm/root.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define EXTRACT_PID(x) (((x) >> 8) & 0xFF)
+#define EXTRACT_REG(x) ((x) & 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, EXTRACT_PID(reg),
+			      EXTRACT_REG(reg), *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, EXTRACT_PID(reg),
+			    EXTRACT_REG(reg));
+
+	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);
+	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] 43+ messages in thread

* [U-Boot] [RFC PATCH 09/11] gpio: Add support for Qualcomm PM8916 gpios
  2015-12-10 21:41 [U-Boot] [RFC PATCH 00/11] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (7 preceding siblings ...)
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 08/11] pmic: Add support for Qualcomm PM8916 PMIC Mateusz Kulikowski
@ 2015-12-10 21:41 ` Mateusz Kulikowski
  2015-12-15 18:58   ` Simon Glass
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 10/11] arm: Add support for Qualcomm Snapdragon family Mateusz Kulikowski
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-10 21:41 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>
---

 drivers/gpio/Kconfig       |   7 ++
 drivers/gpio/Makefile      |   1 +
 drivers/gpio/pm8916_gpio.c | 306 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 314 insertions(+)
 create mode 100644 drivers/gpio/pm8916_gpio.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 1d9443b..1fbdfeb 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -53,6 +53,13 @@ config MSM_GPIO
 	help
 	  Support GPIO controllers on Qualcomm Snapdragon family of SoCs.
 
+config PM8916_GPIO
+	bool "Qualcomm PM8916 PMIC GPIO/keypad driver"
+	depends on DM_GPIO && PMIC_PM8916
+	help
+	  Support for GPIO1-GPIO4 pins and power/reset buttons found on
+	  Qualcomm PM8916 PMIC.
+
 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..9214984
--- /dev/null
+++ b/drivers/gpio/pm8916_gpio.c
@@ -0,0 +1,306 @@
+/*
+ * 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 <asm/io.h>
+#include <linux/bitops.h>
+#include <power/pmic.h>
+#include <spmi/spmi.h>
+#include <asm/gpio.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Register offset for each gpio */
+#define REG_OFFSET(x)          ((x) * 0x100)
+
+/* Register maps */
+#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_direction_input(struct udevice *dev, unsigned offset)
+{
+	struct pm8916_gpio_bank *priv = dev_get_priv(dev);
+	uint32_t gpio_base = priv->pid + REG_OFFSET(offset);
+	int val, ret;
+
+	/* Disable the GPIO */
+	val = pmic_reg_read(dev->parent, gpio_base + REG_EN_CTL);
+	if (val < 0)
+		return val;
+
+	val &= ~REG_EN_CTL_ENABLE;
+	ret = pmic_reg_write(dev->parent, gpio_base + REG_EN_CTL, val);
+	if (ret < 0)
+		return ret;
+
+	/* Select the mode */
+	val = REG_CTL_MODE_INPUT;
+	ret = pmic_reg_write(dev->parent, gpio_base + REG_CTL, val);
+	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;
+
+	/* 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;
+
+	/* Enable the GPIO */
+	val = pmic_reg_read(dev->parent, gpio_base + REG_EN_CTL);
+	if (val < 0)
+		return val;
+
+	val |= REG_EN_CTL_ENABLE;
+
+	ret = pmic_reg_write(dev->parent, gpio_base + REG_EN_CTL, val);
+	return ret;
+}
+
+static int pm8916_gpio_direction_output(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);
+	int val, ret;
+
+	/* Disable the GPIO */
+	val = pmic_reg_read(dev->parent, gpio_base + REG_EN_CTL);
+	if (val < 0)
+		return val;
+
+	val &= REG_EN_CTL_ENABLE;
+	ret = pmic_reg_write(dev->parent, gpio_base + REG_EN_CTL, val);
+	if (ret < 0)
+		return ret;
+
+	/* Select the mode and output value*/
+	val = REG_CTL_MODE_INOUT | (value ? 1 : 0);
+	ret = pmic_reg_write(dev->parent, gpio_base + REG_CTL, val);
+	if (ret < 0)
+		return ret;
+
+	/* Set the right pull */
+	ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_PULL_CTL,
+			     REG_DIG_PULL_NO_PU);
+	if (ret < 0)
+		return ret;
+
+	/* Select the VIN - VIN0*/
+	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 */
+	val = REG_DIG_OUT_CTL_CMOS | REG_DIG_OUT_CTL_DRIVE_L;
+	ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_OUT_CTL, val);
+	if (ret < 0)
+		return ret;
+
+	/* Enable the GPIO */
+	val = pmic_reg_read(dev->parent, gpio_base + REG_EN_CTL);
+	if (val < 0)
+		return val;
+
+	val |= REG_EN_CTL_ENABLE;
+
+	ret = pmic_reg_write(dev->parent, gpio_base + REG_EN_CTL, val);
+	return ret;
+}
+
+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;
+
+	if ((reg & REG_CTL_MODE_MASK) == REG_CTL_MODE_INPUT)
+		return GPIOF_INPUT;
+	if ((reg & REG_CTL_MODE_MASK) == REG_CTL_MODE_INOUT)
+		return GPIOF_OUTPUT;
+	if ((reg & REG_CTL_MODE_MASK) == REG_CTL_MODE_OUTPUT)
+		return GPIOF_OUTPUT;
+	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);
+	int reg;
+
+	/* Set the output value of the gpio */
+	reg = pmic_reg_read(dev->parent, gpio_base + REG_CTL);
+	if (reg < 0)
+		return reg;
+
+	reg = (reg & ~REG_CTL_OUTPUT_MASK) | value;
+
+	return pmic_reg_write(dev->parent, gpio_base + REG_CTL, reg);
+}
+
+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);
+	priv->pid = dev_get_addr(dev);
+	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);
+
+	priv->pid = dev_get_addr(dev);
+	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;
+	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] 43+ messages in thread

* [U-Boot] [RFC PATCH 10/11] arm: Add support for Qualcomm Snapdragon family
  2015-12-10 21:41 [U-Boot] [RFC PATCH 00/11] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (8 preceding siblings ...)
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 09/11] gpio: Add support for Qualcomm PM8916 gpios Mateusz Kulikowski
@ 2015-12-10 21:41 ` Mateusz Kulikowski
  2015-12-16 22:29   ` Simon Glass
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 11/11] board: Add Qualcomm Dragonboard 410C support Mateusz Kulikowski
  2015-12-15 18:57 ` [U-Boot] [RFC PATCH 00/11] Add support for 96boards Dragonboard410C board sk.syed2
  11 siblings, 1 reply; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-10 21:41 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>
---

 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       |  25 ++
 .../mach-snapdragon/include/mach/sysmap-apq8016.h  |  15 ++
 arch/arm/mach-snapdragon/reset.c                   |  40 ++++
 8 files changed, 369 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 fb9176b..0241980 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
@@ -745,6 +755,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..c8c15b4
--- /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 <asm/io.h>
+#include <dm.h>
+#include <clk.h>
+#include <common.h>
+#include <errno.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 reset*/
+#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 {
+	void *base;
+};
+
+/* Enable clock controlled by CBC soft macro */
+static void clk_enable_cbc(void *cbcr)
+{
+	uint32_t val = readl(cbcr);
+	val |= CBCR_BRANCH_ENABLE_BIT;
+	writel(val, cbcr);
+
+	while (readl(cbcr) & CBCR_BRANCH_OFF_BIT)
+		;
+}
+
+/* clock has 800MHz */
+static void clk_enable_gpll0(void *base)
+{
+	uint32_t ena;
+
+	if (readl(base + GPLL0_STATUS) & GPLL0_STATUS_ACTIVE)
+		return; /* clock already enabled */
+
+	ena = readl(base + APCS_GPLL_ENA_VOTE);
+	ena |= APCS_GPLL_ENA_VOTE_GPLL0;
+	writel(ena, base + APCS_GPLL_ENA_VOTE);
+
+	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(void *apps_cmd_rgcr)
+{
+	uint32_t cmd;
+
+	cmd  = readl(apps_cmd_rgcr);
+	cmd |= APPS_CMD_RGCR_UPDATE;
+	writel(cmd, apps_cmd_rgcr);
+
+	/* 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 BM(msb, lsb)     (((((uint32_t)-1) << (31-msb)) >> (31-msb+lsb)) << lsb)
+#define BVAL(msb, lsb, val) (((val) << lsb) & BM(msb, lsb))
+
+/* root set rate for clocks with half integer and MND divider */
+static void clk_rcg_set_rate_mnd(void *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); /* M */
+	writel(n_val, base + regs->N); /* N */
+	writel(d_val, base + regs->D); /* D */
+
+	/* setup src select and divider */
+	cfg  = readl(base + regs->cfg_rcgr);
+	cfg &= ~CFG_MASK;
+	cfg |= source & CFG_CLK_SRC_MASK; /* Select clock source */
+	cfg |= BVAL(4, 0, (int)(2*(div) - 1))  | BVAL(10, 8, source);
+	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;
+	}
+	return 0;
+}
+
+static int msm_clk_probe(struct udevice *dev)
+{
+	struct msm_clk_priv *priv = dev_get_priv(dev);
+	priv->base = (void *)dev_get_addr(dev);
+	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" },
+	{ }
+};
+
+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..e2ce28b
--- /dev/null
+++ b/arch/arm/mach-snapdragon/include/mach/gpio.h
@@ -0,0 +1,25 @@
+/*
+ * Qualcomm GPIO definitions
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#ifndef _MACH_GPIO_H
+#define _MACH_GPIO_H
+
+/* 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
+
+#endif /* _ASM_ARCH_GPIO_H */
+
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..32bc761
--- /dev/null
+++ b/arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h
@@ -0,0 +1,15 @@
+/*
+ * Qualcomm APQ8916 sysmap
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#ifndef _MACH_APQ8016_SYSMAP_H
+#define _MACH_APQ8016_SYSMAP_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] 43+ messages in thread

* [U-Boot] [RFC PATCH 11/11] board: Add Qualcomm Dragonboard 410C support
  2015-12-10 21:41 [U-Boot] [RFC PATCH 00/11] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (9 preceding siblings ...)
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 10/11] arm: Add support for Qualcomm Snapdragon family Mateusz Kulikowski
@ 2015-12-10 21:41 ` Mateusz Kulikowski
  2015-12-16 22:29   ` Simon Glass
  2015-12-15 18:57 ` [U-Boot] [RFC PATCH 00/11] Add support for 96boards Dragonboard410C board sk.syed2
  11 siblings, 1 reply; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-10 21:41 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.

This is code is cleaned-up version of code I did last month
that is already used by some people:
https://github.com/hallor/u-boot

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

 arch/arm/dts/Makefile                            |   2 +
 arch/arm/dts/dragonboard410c.dts                 | 157 +++++++++++++++++++
 arch/arm/mach-snapdragon/Kconfig                 |   9 ++
 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                |  29 ++++
 include/configs/dragonboard410c.h                | 184 +++++++++++++++++++++++
 11 files changed, 665 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 521aa4c..1154993 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..04ad9eb
--- /dev/null
+++ b/arch/arm/dts/dragonboard410c.dts
@@ -0,0 +1,157 @@
+/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-msm8916";
+			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,msm8916-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 = <0x200f000 0x1000 0x2400000 0x400000 0x2c00000 0x400000 0x3800000 0x200000 0x200a000 0x2100>;
+			reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+			#address-cells = <0x1>;
+			#size-cells = <0x1>;
+			pm8916 at 0 {
+				compatible = "qcom,spmi-pmic";
+				reg = <0x0 0x2>;
+				#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>;
+				#address-cells = <0x1>;
+				#size-cells = <0x0>;
+			};
+		};
+	};
+
+	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..61e0e9e 100644
--- a/arch/arm/mach-snapdragon/Kconfig
+++ b/arch/arm/mach-snapdragon/Kconfig
@@ -3,4 +3,13 @@ if ARCH_SNAPDRAGON
 config SYS_SOC
 	default "snapdragon"
 
+choice
+	prompt "Snapdragon board select"
+
+config TARGET_DRAGONBOARD410C
+	bool "96Boards Dragonboard 410C"
+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..7057a2c
--- /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;
+}
+
+static struct gpio_desc hub_reset, usb_sel;
+
+int board_prepare_usb(enum usb_init_type type)
+{
+	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..7dd9aae
--- /dev/null
+++ b/configs/dragonboard410c_defconfig
@@ -0,0 +1,29 @@
+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_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..132ed75
--- /dev/null
+++ b/include/configs/dragonboard410c.h
@@ -0,0 +1,184 @@
+/*
+ * 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
+/* Needed for Host Controller driver */
+#define CONFIG_USB_ULPI_VIEWPORT
+
+#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] 43+ messages in thread

* [U-Boot] [RFC PATCH 04/11] ehci-hcd: Add init_after_reset
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 04/11] ehci-hcd: Add init_after_reset Mateusz Kulikowski
@ 2015-12-10 23:14   ` Marek Vasut
  2015-12-16 22:30   ` Tom Rini
  1 sibling, 0 replies; 43+ messages in thread
From: Marek Vasut @ 2015-12-10 23:14 UTC (permalink / raw)
  To: u-boot

On Thursday, December 10, 2015 at 10:41:40 PM, Mateusz Kulikowski 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>

Best regards,
Marek Vasut

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

* [U-Boot] [RFC PATCH 05/11] ehci: Add support for Qualcomm EHCI
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 05/11] ehci: Add support for Qualcomm EHCI Mateusz Kulikowski
@ 2015-12-10 23:22   ` Marek Vasut
  2015-12-13 12:38     ` Mateusz Kulikowski
  0 siblings, 1 reply; 43+ messages in thread
From: Marek Vasut @ 2015-12-10 23:22 UTC (permalink / raw)
  To: u-boot

On Thursday, December 10, 2015 at 10:41:41 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>

Hi,

minor nits below.

[...]

> diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
> new file mode 100644
> index 0000000..d17a29a
> --- /dev/null
> +++ b/drivers/usb/host/ehci-msm.c
> @@ -0,0 +1,198 @@
> +/*
> + * 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 <asm/gpio.h>
> +#include <asm-generic/errno.h>
> +#include <linux/compat.h>
> +#include <dm.h>
> +#include <fdtdec.h>
> +#include <libfdt.h>
> +#include <asm/io.h>
> +#include <usb.h>
> +#include <usb/ulpi.h>
> +#include "ehci.h"
> +
> +#ifndef CONFIG_USB_ULPI_VIEWPORT
> +#error Please enable CONFIG_USB_ULPI_VIEWPORT
> +#endif

The driver should select this in Kconfig instead of this check, right ?

> +#define MSM_USB_ULPI_OFFSET 0x170 /* ULPI viewport (PHY) */
> +#define MSM_USB_EHCI_OFFSET 0x100 /* Start of EHCI registers */
> +
> +/* 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)
> +
> +/* qcom specific registers (OTG) */
> +#define USB_GENCONFIG_2      0x00A0
> +#define GEN2_SESS_VLD_CTRL_EN (1 << 7)
> +
> +#define USB_USBCMD           (0x0140)

Please drop the parenthesis.

btw. this register layout looks very similar to struct usb_ehci in
include/usb/ehci-fsl.h , can the header be made more universal to
cover your driver as well ? Then these macros here won't be needed.

> +#define SESS_VLD_CTRL         (1 << 25)
> +#define USBCMD_RESET   2
> +#define USBCMD_ATTACH  1
> +
> +/* USB2_HSIC_USB_OTG_HS_BASE_USB_OTG_HS_PORTSC */
> +#define USB_PORTSC           0x0184
> +#define USB_SBUSCFG          0x0090
> +#define USB_AHB_MODE         0x0098
> +
> +#define USB_USBMODE          0x01A8
> +#define USBMODE_DEVICE 2
> +#define USBMODE_HOST   3
> +
> +struct msm_ehci_priv {
> +	struct ehci_ctrl ctrl; /* Needed by EHCI */
> +	phys_addr_t base;
> +	phys_addr_t ehci_base;
> +	u32 ulpi_base;
> +	u32 ulpi_port;
> +};
> +
> +int __weak board_prepare_usb(enum usb_init_type type)
> +{
> +	return 0;
> +}
> +
> +static void setup_usb_phy(struct msm_ehci_priv *priv)
> +{
> +	struct ulpi_viewport ulpi_vp = {.port_num = priv->ulpi_port,
> +					.viewport_addr = priv->ulpi_base};
> +
> +	/* Select and enable external configuration with USB PHY */
> +	ulpi_write(&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)
> +{
> +	struct ulpi_viewport ulpi_vp = {.port_num = priv->ulpi_port,
> +					.viewport_addr = priv->ulpi_base};
> +
> +	/* Disable VBUS mimicing in the controller. */
> +	ulpi_write(&ulpi_vp, (u8 *)ULPI_MISC_A_CLEAR,

This should be a pointer to a field in struct ulpi_regs, so the (u8 *)
cast does not seem right. See for example ehci-zynq.c

> +		   ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT);
> +}


[...]

> +static int ehci_usb_remove(struct udevice *dev)
> +{
> +	struct msm_ehci_priv *p = dev_get_priv(dev);
> +	phys_addr_t reg = p->base + USB_USBCMD;
> +	int ret;
> +
> +	ret = ehci_deregister(dev);
> +	if (ret)
> +		return ret;
> +
> +	/* Stop controller. */
> +	writel(readl(reg) & ~USBCMD_ATTACH, reg);

This should use clrbits_le32() instead.

> +	reset_usb_phy(p);
> +
> +	ret = board_prepare_usb(USB_INIT_DEVICE); /* Board specific hook */
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Reset controller */
> +	writel(0x00080002, reg); /* reset usb */
> +	mdelay(20);
> +	/* Wait for completion */
> +	while (readl(reg) & 2)
> +		;

Look at wait_for_bit() implementations in the U-Boot tree and avoid the 
unbounded waiting here please.

> +	return 0;
> +}
> +
> +static int ehci_usb_ofdata_to_platdata(struct udevice *dev)
> +{
> +	struct msm_ehci_priv *priv = dev_get_priv(dev);
> +
> +	priv->base = dev_get_addr(dev);
> +	priv->ehci_base = priv->base + MSM_USB_EHCI_OFFSET;
> +	priv->ulpi_base = priv->base + MSM_USB_ULPI_OFFSET;
> +	priv->ulpi_port = 0;
> +	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,
> +};

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

* [U-Boot] [RFC PATCH 05/11] ehci: Add support for Qualcomm EHCI
  2015-12-10 23:22   ` Marek Vasut
@ 2015-12-13 12:38     ` Mateusz Kulikowski
  2015-12-13 15:48       ` Marek Vasut
  0 siblings, 1 reply; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-13 12:38 UTC (permalink / raw)
  To: u-boot

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

Hi,

Thanks for quick review;

On 11.12.2015 00:22, Marek Vasut wrote:
> On Thursday, December 10, 2015 at 10:41:41 PM, Mateusz Kulikowski wrote:
[...]
>> +
>> +#ifndef CONFIG_USB_ULPI_VIEWPORT
>> +#error Please enable CONFIG_USB_ULPI_VIEWPORT
>> +#endif
> 
> The driver should select this in Kconfig instead of this check, right ?

That was my first attempt, but ULPI_VIEWPORT is not Kconfig option, 
and it seems it just doesn't work :(

It doesn't matter if I add it as 
select USB_ULPI_VIEWPORT
in usb KConfig, or forcibly add CONFIG_USB_ULPI_VIEWPORT to .config

[...]
>> +#define USB_USBCMD           (0x0140)
> 
> Please drop the parenthesis.

Doh, missed this one - surely will do it.

> 
> btw. this register layout looks very similar to struct usb_ehci in
> include/usb/ehci-fsl.h , can the header be made more universal to
> cover your driver as well ? Then these macros here won't be needed.

You're right.. in fact contrary to what I expected, Qualcomm didn't 
implemented their own USB controller.

It is designed by Chipidea, and PHY as far as I see is made by Synapsys.

I can use fsl headers with little exception that two registers are 
marked as reserved: USB_AHB_MODE (0x98) and USB_GENCONFIG_2 (0xA0)

My guess is that it's just different revision/config of IP core.

Do you think it wouldn't look awkward if I use fsl headers?

I think once this series gets to mainline we can create shared
driver that will support both vendors.

I also noticed that U-Boot have ci_udc already so there is 
a chance I make device controller working pretty fast 
(but I prefer not to include it in this series yet).

[...]
>> +	struct ulpi_viewport ulpi_vp = {.port_num = priv->ulpi_port,
>> +					.viewport_addr = priv->ulpi_base};
>> +
>> +	/* Disable VBUS mimicing in the controller. */
>> +	ulpi_write(&ulpi_vp, (u8 *)ULPI_MISC_A_CLEAR,
> 
> This should be a pointer to a field in struct ulpi_regs, so the (u8 *)
> cast does not seem right. See for example ehci-zynq.c
> 
Perhaps I misussed ulpi_viewport code in that case;

The reason is I need to access MISC_A register (0x96+) that is 
not in ulpi_regs structure - afaik it's vendor-specific.

Any hints how to tackle that properly?

I can of course duplicate ulpi code, but it probably doesn't make much sense.


[...]
>> +
>> +	/* Stop controller. */
>> +	writel(readl(reg) & ~USBCMD_ATTACH, reg);
> 
> This should use clrbits_le32() instead.

Ok

[...]
>> +	/* Wait for completion */
>> +	while (readl(reg) & 2)
>> +		;
> 
> Look at wait_for_bit() implementations in the U-Boot tree and avoid the 
> unbounded waiting here please.

Ok, btw I noticed there are 3 copies of almost the same code that does that :)

Perhaps I can add a patch to add this function to /lib as it seems it's 
common use case?

The following drivers would benefit: ehci-msm, zynq_gem, dwc2, 
ehci-mx6, ohci-lpc32xx


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

iQEcBAEBCAAGBQJWbWbJAAoJELvtohmVtQzBvEEH/iwqONAqWwqQzpUR4izzZ97Y
CAEUWi4GacxwUVt0vZMcK5KV0sRJVP947daMxVkNoDWWkpREuPby+OecFe3mk7iJ
cJzTAlYs/OOIkGBuza2wkfaxXq0AItpn2lBF/Vwe8u5hFGSPgYY0quek8SKma6NQ
rtNFVdc+4+pgGMy1Pl8Fym9UXOJ/aVv806+XS34UrgGSsnv5qWudRiT3HA0ZR38A
VPzgRXs+kIwVAhPe2AlXW0K8w/ipaEF41qAMvHUdXopi0h4Tgsc2QEijC0sIQmBf
kSM6gvzYq+gFOJifxcEt3EJj6hOQ4U7nEOi/PqtjBl3BsTw6IdUWLdakCVzQq1I=
=eUF2
-----END PGP SIGNATURE-----

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

* [U-Boot] [RFC PATCH 05/11] ehci: Add support for Qualcomm EHCI
  2015-12-13 12:38     ` Mateusz Kulikowski
@ 2015-12-13 15:48       ` Marek Vasut
  2015-12-16 22:51         ` Mateusz Kulikowski
  0 siblings, 1 reply; 43+ messages in thread
From: Marek Vasut @ 2015-12-13 15:48 UTC (permalink / raw)
  To: u-boot

On Sunday, December 13, 2015 at 01:38:41 PM, Mateusz Kulikowski wrote:
> Hi,
> 
> Thanks for quick review;
> 
> On 11.12.2015 00:22, Marek Vasut wrote:
> > On Thursday, December 10, 2015 at 10:41:41 PM, Mateusz Kulikowski wrote:
> [...]
> 
> >> +
> >> +#ifndef CONFIG_USB_ULPI_VIEWPORT
> >> +#error Please enable CONFIG_USB_ULPI_VIEWPORT
> >> +#endif
> > 
> > The driver should select this in Kconfig instead of this check, right ?
> 
> That was my first attempt, but ULPI_VIEWPORT is not Kconfig option,
> and it seems it just doesn't work :(
> 
> It doesn't matter if I add it as
> select USB_ULPI_VIEWPORT
> in usb KConfig, or forcibly add CONFIG_USB_ULPI_VIEWPORT to .config

I think it should be quite easily possible to add this to USB Kconfig.

> [...]
> 
> >> +#define USB_USBCMD           (0x0140)
> > 
> > Please drop the parenthesis.
> 
> Doh, missed this one - surely will do it.
> 
> > btw. this register layout looks very similar to struct usb_ehci in
> > include/usb/ehci-fsl.h , can the header be made more universal to
> > cover your driver as well ? Then these macros here won't be needed.
> 
> You're right.. in fact contrary to what I expected, Qualcomm didn't
> implemented their own USB controller.

Well building a chip is like going to a IP block supermarket afterall ;-)

> It is designed by Chipidea, and PHY as far as I see is made by Synapsys.

All of the drivers/usb/host/ehci-{mxs,mx5,mx6,vf}.c are also chipidea
cores. MXS and MX6 have chipidea PHY too.

> I can use fsl headers with little exception that two registers are
> marked as reserved: USB_AHB_MODE (0x98) and USB_GENCONFIG_2 (0xA0)
> 
> My guess is that it's just different revision/config of IP core.
> 
> Do you think it wouldn't look awkward if I use fsl headers?

Just rename them to ehci-ci.h, that should be the quickest.

> I think once this series gets to mainline we can create shared
> driver that will support both vendors.

I'm all for that.

> I also noticed that U-Boot have ci_udc already so there is
> a chance I make device controller working pretty fast
> (but I prefer not to include it in this series yet).

Correct, that works too. I think it was also tested on some marvell chip.

> [...]
> 
> >> +	struct ulpi_viewport ulpi_vp = {.port_num = priv->ulpi_port,
> >> +					.viewport_addr = priv->ulpi_base};
> >> +
> >> +	/* Disable VBUS mimicing in the controller. */
> >> +	ulpi_write(&ulpi_vp, (u8 *)ULPI_MISC_A_CLEAR,
> > 
> > This should be a pointer to a field in struct ulpi_regs, so the (u8 *)
> > cast does not seem right. See for example ehci-zynq.c
> 
> Perhaps I misussed ulpi_viewport code in that case;
> 
> The reason is I need to access MISC_A register (0x96+) that is
> not in ulpi_regs structure - afaik it's vendor-specific.
> 
> Any hints how to tackle that properly?
> 
> I can of course duplicate ulpi code, but it probably doesn't make much
> sense.

I don't have a better suggestion, sorry. Let's keep this as-is unless
someone can come up with something better. Code duplication is not a
good idea, so we won't do that.

> [...]
> 
> >> +
> >> +	/* Stop controller. */
> >> +	writel(readl(reg) & ~USBCMD_ATTACH, reg);
> > 
> > This should use clrbits_le32() instead.
> 
> Ok
> 
> [...]
> 
> >> +	/* Wait for completion */
> >> +	while (readl(reg) & 2)
> >> +		;
> > 
> > Look at wait_for_bit() implementations in the U-Boot tree and avoid the
> > unbounded waiting here please.
> 
> Ok, btw I noticed there are 3 copies of almost the same code that does that
> :)
> 
> Perhaps I can add a patch to add this function to /lib as it seems it's
> common use case?

That'd be great, it was on my list to do it for a while, but I didn't get around 
doing that yet.

> The following drivers would benefit: ehci-msm, zynq_gem, dwc2,
> ehci-mx6, ohci-lpc32xx

Thanks!

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

* [U-Boot] [RFC PATCH 00/11] Add support for 96boards Dragonboard410C board
  2015-12-10 21:41 [U-Boot] [RFC PATCH 00/11] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
                   ` (10 preceding siblings ...)
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 11/11] board: Add Qualcomm Dragonboard 410C support Mateusz Kulikowski
@ 2015-12-15 18:57 ` sk.syed2
  2015-12-15 21:25   ` Mateusz Kulikowski
  11 siblings, 1 reply; 43+ messages in thread
From: sk.syed2 @ 2015-12-15 18:57 UTC (permalink / raw)
  To: u-boot

>
> With a slight delay (Sorry Syed) I'm finally ready to show code
> I've been working recently on.

Thanks for the patches. I will update my git tree for snapdragon_810
with these changes. I only have serial and cache support working on 810
and it boots to u-boot prompt. The
arch/arm/cpu/armv8/cache_v8.c/mmu_setup() causes the board to reset. I
didn't dig deeper. I switched to use
mmu_setup() as implemented in arch/arm/cpu/armv8/zynqmp/cpu.c and
everything works fine.

>create mode 100644 arch/arm/mach-snapdragon/reset.c
Can you rename this  arch/arm/mach-snapdragon/reset-apq8016.c as I
have arch/arm/mach-snapdragon/reset-apq8094.c to be added.

Will provide more feedback going forward.

Thanks
-syed

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

* [U-Boot] [RFC PATCH 01/11] serial: Add support for Qualcomm serial port
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 01/11] serial: Add support for Qualcomm serial port Mateusz Kulikowski
@ 2015-12-15 18:58   ` Simon Glass
  2015-12-16 22:19     ` Mateusz Kulikowski
  2015-12-21  6:50     ` Masahiro Yamada
  0 siblings, 2 replies; 43+ messages in thread
From: Simon Glass @ 2015-12-15 18:58 UTC (permalink / raw)
  To: u-boot

Hi Mateusz,

On 10 December 2015 at 14:41, 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>
> ---
>
>  drivers/serial/Kconfig      |   5 ++
>  drivers/serial/Makefile     |   1 +
>  drivers/serial/serial_msm.c | 204 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 210 insertions(+)
>  create mode 100644 drivers/serial/serial_msm.c
>
> diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
> index 1fc287e..f28c093 100644
> --- a/drivers/serial/Kconfig
> +++ b/drivers/serial/Kconfig
> @@ -223,4 +223,9 @@ 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.

Any more details? What baud rates does it support? What SoCs use it?

>  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..13dad33
> --- /dev/null
> +++ b/drivers/serial/serial_msm.c
> @@ -0,0 +1,204 @@
> +/*
> + * 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 <asm/io.h>
> +#include <common.h>
> +#include <dm.h>
> +#include <clk.h>
> +#include <errno.h>
> +#include <linux/compiler.h>
> +#include <serial.h>
> +#include <watchdog.h>

Ordering:

common.h
clk.h
dm.h
errno.h
serial.h
watchdog.h
asm/
linux/


> +
> +/* 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);
> +       unsigned sr;
> +       char c;
> +
> +       /* There was something buffered */
> +       if (p->chars_cnt) {
> +               c = p->chars_buf & 0xFF;
> +               p->chars_buf >>= 8;
> +               p->chars_cnt--;
> +               return c;
> +       }
> +
> +       /* 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);
> +
> +       /* There are at least 4 bytes in fifo */
> +       if (sr & UARTDM_SR_RX_READY) {
> +               p->chars_buf = readl(p->base + UARTDM_RF);
> +               c = p->chars_buf & 0xFF;
> +               p->chars_cnt = 3; /* 4 - one read */
> +               p->chars_buf >>= 8;
> +               return c;
> +       }
> +
> +       /* 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--;

Can you not rationalise this code a bit? E.g.

if (no chars in fifo) {
   try to get some
}
if (no chars in fifo)
   return -EAGAIN
extract char from fifo
return ch;

You seem to have three copies of the same code.

> +
> +       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 */

blank line

> +       fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "clock", clkd, 2);

check return value and maybe return -EINVAL

> +       clkd[0] = fdt_node_offset_by_phandle(gd->fdt_blob, clkd[0]);
> +
> +       struct udevice *clk = NULL;

Put this decl at the top. Also do you need to assign to NULL?

> +       uclass_get_device_by_of_offset(UCLASS_CLK, clkd[0], &clk);

Check return value. -ENODEV means there is no clk. Is it OK to have no clock?

> +       if (clk)
> +               clk_set_periph_rate(clk, clkd[1], clk_rate);

If is OK to

> +
> +       return 0;
> +}
> +
> +static int msm_serial_probe(struct udevice *dev)
> +{
> +       struct msm_serial_data *p = dev_get_priv(dev);
> +
> +       msm_uart_clk_init(dev);
> +
> +       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);
> +
> +       p->chars_buf = 0;
> +       p->chars_cnt = 0;

No need for the above two lines. Private data is set to 0 by driver model.

> +       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,
> +       .flags = DM_FLAG_PRE_RELOC,

Do you need this? You can specify this with u-boot,dm-pre-reloc in the
device tree.

> +};
> --
> 2.5.0
>

Regards,
Simon

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

* [U-Boot] [RFC PATCH 02/11] gpio: Add support for Qualcomm gpio controller
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 02/11] gpio: Add support for Qualcomm gpio controller Mateusz Kulikowski
@ 2015-12-15 18:58   ` Simon Glass
  0 siblings, 0 replies; 43+ messages in thread
From: Simon Glass @ 2015-12-15 18:58 UTC (permalink / raw)
  To: u-boot

Hi Mateusz,

On 10 December 2015 at 14:41, 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>
> ---
>
>  drivers/gpio/Kconfig    |   7 +++
>  drivers/gpio/Makefile   |   2 +-
>  drivers/gpio/msm_gpio.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 123 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpio/msm_gpio.c
>
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index e60e9fd..1d9443b 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -46,6 +46,13 @@ 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.

Any more details? How many banks? How are they named? What features
does the driver support?

> +
>  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..9bb9e89
> --- /dev/null
> +++ b/drivers/gpio/msm_gpio.c
> @@ -0,0 +1,115 @@
> +/*
> + * 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 <asm/gpio.h>
> +#include <asm/io.h>
> +#include <errno.h>

Put errno.h below dm.h

> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +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 */
> +       writel((readl(reg) & ~GPIO_OE_MASK) | GPIO_OE_DISABLE , reg);

How about:

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 */
> +       writel((readl(reg) & ~GPIO_OE_MASK) | GPIO_OE_ENABLE , reg);
> +       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" },

Is there a device binding tree binding file you can put in
doc/device-tree-bindings?

> +       { }
> +};
> +
> +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] 43+ messages in thread

* [U-Boot] [RFC PATCH 03/11] mmc: Add support for Qualcomm SDHCI controller
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 03/11] mmc: Add support for Qualcomm SDHCI controller Mateusz Kulikowski
@ 2015-12-15 18:58   ` Simon Glass
  2015-12-16 22:46     ` Mateusz Kulikowski
  0 siblings, 1 reply; 43+ messages in thread
From: Simon Glass @ 2015-12-15 18:58 UTC (permalink / raw)
  To: u-boot

Hi Mateusz,

On 10 December 2015 at 14:41, Mateusz Kulikowski
<mateusz.kulikowski@gmail.com> wrote:
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> ---

Please add a commit message.

>
>  drivers/mmc/Kconfig     |   6 ++
>  drivers/mmc/Makefile    |   1 +
>  drivers/mmc/msm_sdhci.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 156 insertions(+)
>  create mode 100644 drivers/mmc/msm_sdhci.c
>
> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
> index ceae7bc..3f75fa7 100644
> --- a/drivers/mmc/Kconfig
> +++ b/drivers/mmc/Kconfig
> @@ -16,6 +16,12 @@ 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 manufactured by Qualcomm.

Can you add any more detail here?

> +
>  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..96119f0
> --- /dev/null
> +++ b/drivers/mmc/msm_sdhci.c
> @@ -0,0 +1,149 @@
> +/*
> + * 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 <asm/io.h>
> +#include <common.h>
> +#include <dm.h>
> +#include <linux/bitops.h>
> +#include <sdhci.h>
> +#include <clk.h>

Ordering:

common.h always goes first
clk.h
dm.h
sdhci.h
asm/
linux/

> +
> +/* 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_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;
> +       phys_addr_t base;
> +       unsigned width;

Comment - what is width?

> +};
> +
> +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 */
> +       fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "clock", clkd, 2);
> +       clkd[0] = fdt_node_offset_by_phandle(gd->fdt_blob, clkd[0]);
> +
> +       struct udevice *clk = NULL;
> +       uclass_get_device_by_of_offset(UCLASS_CLK, clkd[0], &clk);
> +       if (clk)
> +               clk_set_periph_rate(clk, clkd[1], clk_rate);
> +

See comments on the previous patch. Also you could move the DT decode
code all into your ofdata_to_platdata function (if you like).

> +       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;
> +
> +       host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B;
> +
> +       /* Init clocks */
> +       if (msm_sdc_clk_init(dev))
> +               return -EIO;
> +
> +       /* Reset the core and Enable SDHC mode */
> +       writel(readl(prv->base + SDCC_MCI_POWER) | SDCC_MCI_POWER_SW_RST,
> +              prv->base + SDCC_MCI_POWER);
> +
> +       /* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */
> +       mdelay(2);

So why such a long delay? Perhaps you should put the code immediately
below int a timeout loop?

start = get_timer(0);
while (readl...) {
   if (get_timer(start) > 2)
      return -ETIMEDOUT;
}

> +
> +       if (readl(prv->base + SDCC_MCI_POWER) & SDCC_MCI_POWER_SW_RST) {
> +               printf("msm_sdhci: stuck in reset\n");
> +               return -1;

-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);

blank line after decls

> +        /* Disable host-controller mode */
> +       writel(0, priv->base + SDCC_MCI_HC_MODE);

blank line before return

> +       return 0;
> +}
> +
> +static int msm_ofdata_to_platdata(struct udevice *dev)
> +{
> +       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 = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
> +                                                     dev->parent->of_offset,
> +                                                     dev->of_offset, "reg",
> +                                                     1, NULL);

Odd that you are reading the second cell. How come?

> +       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
>

Regards,
Simon

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

* [U-Boot] [RFC PATCH 06/11] drivers: Add SPMI bus uclass
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 06/11] drivers: Add SPMI bus uclass Mateusz Kulikowski
@ 2015-12-15 18:58   ` Simon Glass
  2015-12-16 23:09     ` Mateusz Kulikowski
  0 siblings, 1 reply; 43+ messages in thread
From: Simon Glass @ 2015-12-15 18:58 UTC (permalink / raw)
  To: u-boot

Hi Matheusz,

On 10 December 2015 at 14:41, 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>
> ---
>
>  drivers/Kconfig            |  2 ++
>  drivers/Makefile           |  1 +
>  drivers/spmi/Kconfig       | 10 +++++++++
>  drivers/spmi/Makefile      |  7 ++++++
>  drivers/spmi/spmi-uclass.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++
>  include/dm/uclass-id.h     |  1 +
>  include/spmi/spmi.h        | 44 ++++++++++++++++++++++++++++++++++++++
>  7 files changed, 118 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..2d8d78b
> --- /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..981da68
> --- /dev/null
> +++ b/drivers/spmi/spmi-uclass.c
> @@ -0,0 +1,53 @@
> +/*
> + * SPMI bus uclass driver
> + *
> + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <fdtdec.h>
> +#include <errno.h>
> +#include <dm.h>
> +#include <dm/root.h>
> +#include <vsprintf.h>
> +#include <dm/lists.h>
> +#include <dm/device-internal.h>
> +#include <dm/uclass-internal.h>
> +#include <linux/ctype.h>
> +#include <spmi/spmi.h>

Fix ordering

> +
> +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 msm_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      = msm_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..e06a79e
> --- /dev/null
> +++ b/include/spmi/spmi.h
> @@ -0,0 +1,44 @@
> +#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
> + * @write:     write register

You should describe the args also.

What is different between this and I2C? Could you use that uclass? It
seems to have an additional address value (pid)- is that right?

If you do end up with a new uclass, please add a sandbox driver for it
and a test.

> + */
> +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] 43+ messages in thread

* [U-Boot] [RFC PATCH 08/11] pmic: Add support for Qualcomm PM8916 PMIC
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 08/11] pmic: Add support for Qualcomm PM8916 PMIC Mateusz Kulikowski
@ 2015-12-15 18:58   ` Simon Glass
  0 siblings, 0 replies; 43+ messages in thread
From: Simon Glass @ 2015-12-15 18:58 UTC (permalink / raw)
  To: u-boot

Hi Mateusz,

On 10 December 2015 at 14:41, 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>
> ---
>
>  drivers/power/pmic/Kconfig  | 14 +++++++
>  drivers/power/pmic/Makefile |  1 +
>  drivers/power/pmic/pm8916.c | 92 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 107 insertions(+)
>  create mode 100644 drivers/power/pmic/pm8916.c
>
> 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

Nice help!

> 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..5fe50ef
> --- /dev/null
> +++ b/drivers/power/pmic/pm8916.c
> @@ -0,0 +1,92 @@
> +/*
> + * 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 <asm/io.h>
> +#include <linux/bitops.h>
> +#include <power/pmic.h>
> +#include <spmi/spmi.h>
> +#include <asm/gpio.h>
> +#include <dm/root.h>

Fix ordering

> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define EXTRACT_PID(x) (((x) >> 8) & 0xFF)
> +#define EXTRACT_REG(x) ((x) & 0xFF)

Can you define

#define PID_SHIFT 8
#define PID_MASK (0xff << PID_SHIFT)

and use those? I prefer lower-case hex but there is no convention on that.

> +
> +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, EXTRACT_PID(reg),
> +                             EXTRACT_REG(reg), *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, EXTRACT_PID(reg),
> +                           EXTRACT_REG(reg));
> +
> +       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" },

Binding doc?

> +       { }
> +};
> +
> +static int pm8916_probe(struct udevice *dev)
> +{
> +       struct pm8916_priv *priv = dev_get_priv(dev);

blank line

> +       priv->usid = dev_get_addr(dev);
> +       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
>

Regards,
Simon

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

* [U-Boot] [RFC PATCH 09/11] gpio: Add support for Qualcomm PM8916 gpios
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 09/11] gpio: Add support for Qualcomm PM8916 gpios Mateusz Kulikowski
@ 2015-12-15 18:58   ` Simon Glass
  0 siblings, 0 replies; 43+ messages in thread
From: Simon Glass @ 2015-12-15 18:58 UTC (permalink / raw)
  To: u-boot

Hi Mateusz,

On 10 December 2015 at 14:41, 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>
> ---
>
>  drivers/gpio/Kconfig       |   7 ++
>  drivers/gpio/Makefile      |   1 +
>  drivers/gpio/pm8916_gpio.c | 306 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 314 insertions(+)
>  create mode 100644 drivers/gpio/pm8916_gpio.c
>
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index 1d9443b..1fbdfeb 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -53,6 +53,13 @@ config MSM_GPIO
>         help
>           Support GPIO controllers on Qualcomm Snapdragon family of SoCs.
>
> +config PM8916_GPIO
> +       bool "Qualcomm PM8916 PMIC GPIO/keypad driver"
> +       depends on DM_GPIO && PMIC_PM8916
> +       help
> +         Support for GPIO1-GPIO4 pins and power/reset buttons found on
> +         Qualcomm PM8916 PMIC.
> +
>  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..9214984
> --- /dev/null
> +++ b/drivers/gpio/pm8916_gpio.c
> @@ -0,0 +1,306 @@
> +/*
> + * 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 <asm/io.h>
> +#include <linux/bitops.h>
> +#include <power/pmic.h>
> +#include <spmi/spmi.h>
> +#include <asm/gpio.h>

Ordering

> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* Register offset for each gpio */
> +#define REG_OFFSET(x)          ((x) * 0x100)
> +
> +/* Register maps */
> +#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_direction_input(struct udevice *dev, unsigned offset)
> +{
> +       struct pm8916_gpio_bank *priv = dev_get_priv(dev);
> +       uint32_t gpio_base = priv->pid + REG_OFFSET(offset);
> +       int val, ret;
> +
> +       /* Disable the GPIO */
> +       val = pmic_reg_read(dev->parent, gpio_base + REG_EN_CTL);
> +       if (val < 0)
> +               return val;
> +
> +       val &= ~REG_EN_CTL_ENABLE;
> +       ret = pmic_reg_write(dev->parent, gpio_base + REG_EN_CTL, val);
> +       if (ret < 0)
> +               return ret;

Can you use pmic_clrsetbits()?

> +
> +       /* Select the mode */
> +       val = REG_CTL_MODE_INPUT;
> +       ret = pmic_reg_write(dev->parent, gpio_base + REG_CTL, val);
> +       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;
> +
> +       /* 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;
> +
> +       /* Enable the GPIO */
> +       val = pmic_reg_read(dev->parent, gpio_base + REG_EN_CTL);
> +       if (val < 0)
> +               return val;
> +
> +       val |= REG_EN_CTL_ENABLE;
> +
> +       ret = pmic_reg_write(dev->parent, gpio_base + REG_EN_CTL, val);
> +       return ret;
> +}
> +
> +static int pm8916_gpio_direction_output(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);
> +       int val, ret;
> +
> +       /* Disable the GPIO */
> +       val = pmic_reg_read(dev->parent, gpio_base + REG_EN_CTL);
> +       if (val < 0)
> +               return val;
> +
> +       val &= REG_EN_CTL_ENABLE;
> +       ret = pmic_reg_write(dev->parent, gpio_base + REG_EN_CTL, val);
> +       if (ret < 0)
> +               return ret;
> +
> +       /* Select the mode and output value*/
> +       val = REG_CTL_MODE_INOUT | (value ? 1 : 0);
> +       ret = pmic_reg_write(dev->parent, gpio_base + REG_CTL, val);
> +       if (ret < 0)
> +               return ret;
> +
> +       /* Set the right pull */
> +       ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_PULL_CTL,
> +                            REG_DIG_PULL_NO_PU);
> +       if (ret < 0)
> +               return ret;
> +
> +       /* Select the VIN - VIN0*/
> +       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 */
> +       val = REG_DIG_OUT_CTL_CMOS | REG_DIG_OUT_CTL_DRIVE_L;
> +       ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_OUT_CTL, val);
> +       if (ret < 0)
> +               return ret;
> +
> +       /* Enable the GPIO */
> +       val = pmic_reg_read(dev->parent, gpio_base + REG_EN_CTL);
> +       if (val < 0)
> +               return val;
> +
> +       val |= REG_EN_CTL_ENABLE;
> +
> +       ret = pmic_reg_write(dev->parent, gpio_base + REG_EN_CTL, val);
> +       return ret;
> +}

Any chance that the above two functions have some common elements that
could go in a shared function?

> +
> +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;
> +
> +       if ((reg & REG_CTL_MODE_MASK) == REG_CTL_MODE_INPUT)

How about:

switch (reg & ...) {
case ...
}

> +               return GPIOF_INPUT;
> +       if ((reg & REG_CTL_MODE_MASK) == REG_CTL_MODE_INOUT)
> +               return GPIOF_OUTPUT;
> +       if ((reg & REG_CTL_MODE_MASK) == REG_CTL_MODE_OUTPUT)
> +               return GPIOF_OUTPUT;
> +       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;

Suggest ret as it is not always a register. pmic_reg_read() returns an
error code sometimes.

> +
> +       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);
> +       int reg;
> +
> +       /* Set the output value of the gpio */
> +       reg = pmic_reg_read(dev->parent, gpio_base + REG_CTL);
> +       if (reg < 0)
> +               return reg;
> +
> +       reg = (reg & ~REG_CTL_OUTPUT_MASK) | value;
> +
> +       return pmic_reg_write(dev->parent, gpio_base + REG_CTL, reg);

pmic_clrsetbits()?

> +}
> +
> +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);
> +       priv->pid = dev_get_addr(dev);
> +       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" },

Binding doc?

> +       { }
> +};
> +
> +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);
> +
> +       priv->pid = dev_get_addr(dev);
> +       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;
> +       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
>

Regards,
Simon

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

* [U-Boot] [RFC PATCH 00/11] Add support for 96boards Dragonboard410C board
  2015-12-15 18:57 ` [U-Boot] [RFC PATCH 00/11] Add support for 96boards Dragonboard410C board sk.syed2
@ 2015-12-15 21:25   ` Mateusz Kulikowski
  0 siblings, 0 replies; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-15 21:25 UTC (permalink / raw)
  To: u-boot

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

On 15.12.2015 19:57, sk.syed2 wrote:
>>
>> With a slight delay (Sorry Syed) I'm finally ready to show code
>> I've been working recently on.
> 
> Thanks for the patches. I will update my git tree for snapdragon_810
> with these changes. I only have serial and cache support working on 810
> and it boots to u-boot prompt. The
> arch/arm/cpu/armv8/cache_v8.c/mmu_setup() causes the board to reset. I
> didn't dig deeper. I switched to use
> mmu_setup() as implemented in arch/arm/cpu/armv8/zynqmp/cpu.c and
> everything works fine.

Try to make it able to boot Linux somehow (either via mmc or usb or somehow).

After I'm done with this series for 410C I can take a look at drivers / dts for 
810 and try to give you some hints.

> 
>> create mode 100644 arch/arm/mach-snapdragon/reset.c
> Can you rename this  arch/arm/mach-snapdragon/reset-apq8016.c as I
> have arch/arm/mach-snapdragon/reset-apq8094.c to be added.

Sure - will do that.

> 
> Will provide more feedback going forward.

Great
> 
> Thanks
> -syed
> 

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

iQEcBAEBCAAGBQJWcIVEAAoJELvtohmVtQzB1YIH/i5cO7hcGlDW38FwuKnLe5RH
uq2FgoX4OCHMNMZ86o5qEf61UZqCbeMi6jCzvsSH/9KS62Uwlacnl7yMhec/QQ00
644TyyhchyelVmXfbjTouydCObirIJu2SMwn4bn7ThEnBq+CiIKI5dWFAFALhDVD
wHs9HGBK6F2ypP7adjgTcV5pspKV0vghPIdyQSf+ees5q/dbM3oxnBkTGyj3DvAE
sc/2Ip0yu0whUgX4ra+ZVi7zssOQkbSBJfCTcqXVlDOI7Ct87VKkTCWXT8aS9wLK
KRgP2IEkfDCdqOjC5lrhmqG3BnaabeV6U0dWKAcU/ZdudxCnUrNUy3UsmNJzB6o=
=SxKo
-----END PGP SIGNATURE-----

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

* [U-Boot] [RFC PATCH 01/11] serial: Add support for Qualcomm serial port
  2015-12-15 18:58   ` Simon Glass
@ 2015-12-16 22:19     ` Mateusz Kulikowski
  2015-12-21  6:50     ` Masahiro Yamada
  1 sibling, 0 replies; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-16 22:19 UTC (permalink / raw)
  To: u-boot

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

Hi Simon, 

Thank you for awesome review!

I fully agree with most of the suggestions (for this and following patches), 
so to keep it short will reply only to questions (or where I disagree)

On 15.12.2015 19:58, Simon Glass wrote:
> Hi Mateusz,
> 
> On 10 December 2015 at 14:41, Mateusz Kulikowski
> <mateusz.kulikowski@gmail.com> wrote:
[...]

>> +static int msm_serial_getc(struct udevice *dev)
>> +{
>> +       struct msm_serial_data *p = dev_get_priv(dev);
>> +       unsigned sr;
>> +       char c;
>> +
>> +       /* There was something buffered */
>> +       if (p->chars_cnt) {
>> +               c = p->chars_buf & 0xFF;
>> +               p->chars_buf >>= 8;
>> +               p->chars_cnt--;
>> +               return c;
>> +       }
>> +
>> +       /* 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);
>> +
>> +       /* There are at least 4 bytes in fifo */
>> +       if (sr & UARTDM_SR_RX_READY) {
>> +               p->chars_buf = readl(p->base + UARTDM_RF);
>> +               c = p->chars_buf & 0xFF;
>> +               p->chars_cnt = 3; /* 4 - one read */
>> +               p->chars_buf >>= 8;
>> +               return c;
>> +       }
>> +
>> +       /* 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--;
> 
> Can you not rationalise this code a bit? E.g.
> 
> if (no chars in fifo) {
>    try to get some
> }
> if (no chars in fifo)
>    return -EAGAIN
> extract char from fifo
> return ch;
> 
> You seem to have three copies of the same code.

That is good idea. 
Just be warned that "try to get some" will have most of the current code inside.
Reason: Characters from FIFO are packed into 32-bit register.
There are different ways for extracting >=4 chars, and <4 chars.

> 
>> +       uclass_get_device_by_of_offset(UCLASS_CLK, clkd[0], &clk);
> 
> Check return value. -ENODEV means there is no clk. Is it OK to have no clock?
> 
>> +       if (clk)
>> +               clk_set_periph_rate(clk, clkd[1], clk_rate);
> 
> If is OK to

Of course will check ret value; 

For now (at least when it comes to default UART) it's OK not to have clock, 
as U-Boot is chain-loaded from fastboot, but this will change once I get rid 
of fastboot dependency.

[...]

>> +       .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,
>> +       .flags = DM_FLAG_PRE_RELOC,
> 
> Do you need this? You can specify this with u-boot,dm-pre-reloc in the
> device tree.

Probably not, as I do it in dts :)

Regards,
Mateusz

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

iQEcBAEBCAAGBQJWceN5AAoJELvtohmVtQzBvvkH/21bJ573Y+MwKoFeezuupO9p
/kmLNmJ3hNYFjoLv837wW2zNqrbyu5SLnM/Udm8ttbqBcbXWZUIjLhdHZLxGhXiR
X0Zu/yXncb4MRua8QvTpsuuPlEHWqFsLc0XCYzgelwllbkhmC4430HDXuyEdY8+F
iHhuDRTnRdvfUmby4VGwGCoAmpcn30TEcbyffjSnGjXTd+SQ3Vi/sHY+0qTIpSVS
QRWwnQX3WqC0hK6nleLaNXymVzarZANzhMgP6G/aAiPk7GKvExZYJ5Ilko+Iewns
z/bF0FX8bUXU/Yq4opgaTNQlcifQqjr8QIUqbEnSQNHVynoP3FAZj0dsZUVrJ28=
=Nj9Z
-----END PGP SIGNATURE-----

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

* [U-Boot] [RFC PATCH 10/11] arm: Add support for Qualcomm Snapdragon family
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 10/11] arm: Add support for Qualcomm Snapdragon family Mateusz Kulikowski
@ 2015-12-16 22:29   ` Simon Glass
  2015-12-19 12:12     ` Mateusz Kulikowski
  0 siblings, 1 reply; 43+ messages in thread
From: Simon Glass @ 2015-12-16 22:29 UTC (permalink / raw)
  To: u-boot

Hi Mateusz,

On 10 December 2015 at 14:41, 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>
> ---
>
>  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       |  25 ++
>  .../mach-snapdragon/include/mach/sysmap-apq8016.h  |  15 ++
>  arch/arm/mach-snapdragon/reset.c                   |  40 ++++
>  8 files changed, 369 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 fb9176b..0241980 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
> @@ -745,6 +755,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..c8c15b4
> --- /dev/null
> +++ b/arch/arm/mach-snapdragon/clock-apq8016.c

Can this go in drivers/clk?

> @@ -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 <asm/io.h>
> +#include <dm.h>
> +#include <clk.h>
> +#include <common.h>
> +#include <errno.h>
> +#include <linux/bitops.h>

Ordering - please fix globally.

> +
> +/* 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 reset*/

/* block reset */

> +#define SDCC_BCR(n)                 (((n*0x1000)) + 0x41000)

Can you put spaces around operators? (n * 0x1000)

> +/* 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 {
> +       void *base;

You might consider using a struct to access registers to avoid all the
void * but it is up to you - we do both now.

> +};
> +
> +/* Enable clock controlled by CBC soft macro */
> +static void clk_enable_cbc(void *cbcr)
> +{
> +       uint32_t val = readl(cbcr);

blank line

> +       val |= CBCR_BRANCH_ENABLE_BIT;
> +       writel(val, cbcr);
> +
> +       while (readl(cbcr) & CBCR_BRANCH_OFF_BIT)
> +               ;
> +}
> +
> +/* clock has 800MHz */
> +static void clk_enable_gpll0(void *base)
> +{
> +       uint32_t ena;
> +
> +       if (readl(base + GPLL0_STATUS) & GPLL0_STATUS_ACTIVE)
> +               return; /* clock already enabled */
> +
> +       ena = readl(base + APCS_GPLL_ENA_VOTE);
> +       ena |= APCS_GPLL_ENA_VOTE_GPLL0;
> +       writel(ena, base + APCS_GPLL_ENA_VOTE);

setbits_le32(base + APCS_GPLL_ENA_VOTE, APCS_GPLL_ENA_VOTE_GPLL0)

Similarly below.

> +
> +       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(void *apps_cmd_rgcr)
> +{
> +       uint32_t cmd;
> +
> +       cmd  = readl(apps_cmd_rgcr);
> +       cmd |= APPS_CMD_RGCR_UPDATE;
> +       writel(cmd, apps_cmd_rgcr);
> +
> +       /* 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 BM(msb, lsb)     (((((uint32_t)-1) << (31-msb)) >> (31-msb+lsb)) << lsb)
> +#define BVAL(msb, lsb, val) (((val) << lsb) & BM(msb, lsb))

Best to avoid these sorts of things if possible, and just use MASK and
SHIFT #defines.

> +
> +/* root set rate for clocks with half integer and MND divider */
> +static void clk_rcg_set_rate_mnd(void *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); /* M */
> +       writel(n_val, base + regs->N); /* N */
> +       writel(d_val, base + regs->D); /* D */

Those 3 comments don't seem useful.

> +
> +       /* setup src select and divider */
> +       cfg  = readl(base + regs->cfg_rcgr);
> +       cfg &= ~CFG_MASK;
> +       cfg |= source & CFG_CLK_SRC_MASK; /* Select clock source */
> +       cfg |= BVAL(4, 0, (int)(2*(div) - 1))  | BVAL(10, 8, source);
> +       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));

blank line before return

> +       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;
> +       }
> +       return 0;
> +}
> +
> +static int msm_clk_probe(struct udevice *dev)
> +{
> +       struct msm_clk_priv *priv = dev_get_priv(dev);
> +       priv->base = (void *)dev_get_addr(dev);
> +       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" },
> +       { }
> +};
> +
> +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..e2ce28b
> --- /dev/null
> +++ b/arch/arm/mach-snapdragon/include/mach/gpio.h

Should this go in a different patch? I thought you had a GPIO driver earlier?

> @@ -0,0 +1,25 @@
> +/*
> + * Qualcomm GPIO definitions
> + *
> + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +#ifndef _MACH_GPIO_H
> +#define _MACH_GPIO_H
> +
> +/* 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
> +
> +#endif /* _ASM_ARCH_GPIO_H */
> +
> 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..32bc761
> --- /dev/null
> +++ b/arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h
> @@ -0,0 +1,15 @@
> +/*
> + * Qualcomm APQ8916 sysmap
> + *
> + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +#ifndef _MACH_APQ8016_SYSMAP_H
> +#define _MACH_APQ8016_SYSMAP_H
> +
> +#define GICD_BASE 0x0b000000
> +#define GICC_BASE 0x0a20c000

Do you need these? Perhaps they can go in the device tree?

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

* [U-Boot] [RFC PATCH 11/11] board: Add Qualcomm Dragonboard 410C support
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 11/11] board: Add Qualcomm Dragonboard 410C support Mateusz Kulikowski
@ 2015-12-16 22:29   ` Simon Glass
  2015-12-19 12:24     ` Mateusz Kulikowski
  0 siblings, 1 reply; 43+ messages in thread
From: Simon Glass @ 2015-12-16 22:29 UTC (permalink / raw)
  To: u-boot

Hi Mateusz,

On 10 December 2015 at 14:41, 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.
>
> This is code is cleaned-up version of code I did last month
> that is already used by some people:
> https://github.com/hallor/u-boot
>
> Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
> ---
>
>  arch/arm/dts/Makefile                            |   2 +
>  arch/arm/dts/dragonboard410c.dts                 | 157 +++++++++++++++++++
>  arch/arm/mach-snapdragon/Kconfig                 |   9 ++
>  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                |  29 ++++
>  include/configs/dragonboard410c.h                | 184 +++++++++++++++++++++++
>  11 files changed, 665 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 521aa4c..1154993 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..04ad9eb
> --- /dev/null
> +++ b/arch/arm/dts/dragonboard410c.dts
> @@ -0,0 +1,157 @@
> +/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-msm8916";
> +                       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,msm8916-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 = <0x200f000 0x1000 0x2400000 0x400000 0x2c00000 0x400000 0x3800000 0x200000 0x200a000 0x2100>;
> +                       reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
> +                       #address-cells = <0x1>;
> +                       #size-cells = <0x1>;
> +                       pm8916 at 0 {
> +                               compatible = "qcom,spmi-pmic";
> +                               reg = <0x0 0x2>;
> +                               #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>;
> +                               #address-cells = <0x1>;
> +                               #size-cells = <0x0>;
> +                       };
> +               };
> +       };
> +
> +       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..61e0e9e 100644
> --- a/arch/arm/mach-snapdragon/Kconfig
> +++ b/arch/arm/mach-snapdragon/Kconfig
> @@ -3,4 +3,13 @@ if ARCH_SNAPDRAGON
>  config SYS_SOC
>         default "snapdragon"
>
> +choice
> +       prompt "Snapdragon board select"
> +
> +config TARGET_DRAGONBOARD410C
> +       bool "96Boards Dragonboard 410C"

help

Rough description of the board and its peripherals. Should be 3-4 lines.

> +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..7057a2c
> --- /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;
> +}
> +
> +static struct gpio_desc hub_reset, usb_sel;

Can these just be local variables in the function below? I doubt the
function is called more than once.

> +
> +int board_prepare_usb(enum usb_init_type type)
> +{
> +       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");

Is this really the standard binding? I would expect a USB node with a
reset-gpios property.

> +               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");

Should this be a GPIO key?

> +       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)

I wonder if you could use the standard .lds file and amend it to
support fastboot?

> +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..7dd9aae
> --- /dev/null
> +++ b/configs/dragonboard410c_defconfig
> @@ -0,0 +1,29 @@
> +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_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

CONFIG_DM_ETH=y

> diff --git a/include/configs/dragonboard410c.h b/include/configs/dragonboard410c.h
> new file mode 100644
> index 0000000..132ed75
> --- /dev/null
> +++ b/include/configs/dragonboard410c.h
> @@ -0,0 +1,184 @@
> +/*
> + * 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
> +/* Needed for Host Controller driver */
> +#define CONFIG_USB_ULPI_VIEWPORT
> +
> +#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
>

Regards,
Simon

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

* [U-Boot] [RFC PATCH 04/11] ehci-hcd: Add init_after_reset
  2015-12-10 21:41 ` [U-Boot] [RFC PATCH 04/11] ehci-hcd: Add init_after_reset Mateusz Kulikowski
  2015-12-10 23:14   ` Marek Vasut
@ 2015-12-16 22:30   ` Tom Rini
  1 sibling, 0 replies; 43+ messages in thread
From: Tom Rini @ 2015-12-16 22:30 UTC (permalink / raw)
  To: u-boot

On Thu, Dec 10, 2015 at 10:41:40PM +0100, Mateusz Kulikowski 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>

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20151216/324262fe/attachment.sig>

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

* [U-Boot] [RFC PATCH 03/11] mmc: Add support for Qualcomm SDHCI controller
  2015-12-15 18:58   ` Simon Glass
@ 2015-12-16 22:46     ` Mateusz Kulikowski
  2015-12-18 22:41       ` Simon Glass
  0 siblings, 1 reply; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-16 22:46 UTC (permalink / raw)
  To: u-boot

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

Hi Simon, 

On 15.12.2015 19:58, Simon Glass wrote:
> Hi Mateusz,
> 
> On 10 December 2015 at 14:41, Mateusz Kulikowski
> <mateusz.kulikowski@gmail.com> wrote:
[...]
>> +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 */
>> +       fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "clock", clkd, 2);
>> +       clkd[0] = fdt_node_offset_by_phandle(gd->fdt_blob, clkd[0]);
>> +
>> +       struct udevice *clk = NULL;
>> +       uclass_get_device_by_of_offset(UCLASS_CLK, clkd[0], &clk);
>> +       if (clk)
>> +               clk_set_periph_rate(clk, clkd[1], clk_rate);
>> +
> 
> See comments on the previous patch. Also you could move the DT decode
> code all into your ofdata_to_platdata function (if you like).

But requesting clock must be handled in probe (i.e. when clock is 
already bound) right?

> 
>> +       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;
>> +
>> +       host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B;
>> +
>> +       /* Init clocks */
>> +       if (msm_sdc_clk_init(dev))
>> +               return -EIO;
>> +
>> +       /* Reset the core and Enable SDHC mode */
>> +       writel(readl(prv->base + SDCC_MCI_POWER) | SDCC_MCI_POWER_SW_RST,
>> +              prv->base + SDCC_MCI_POWER);
>> +
>> +       /* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */
>> +       mdelay(2);
> 
> So why such a long delay? Perhaps you should put the code immediately
> below int a timeout loop?
> 
> start = get_timer(0);
> while (readl...) {
>    if (get_timer(start) > 2)
>       return -ETIMEDOUT;
> }
> 
I'm not sure if I can do that - I can test it, perhaps it will even work on 
my board, but it was put explicitly in Linux driver (1-5ms delay).

Documentation says:
"SW should wait until bit 0 (MCLK_REG_WR_ACTIVE) of MCI_STATUS2 register 
is 0, after writing to MCI_POWER register and before accessing this 
register again."

But this applies to all writes, not to reset request - I'm not sure 
how MCI_STATUS2 will behave during reset (it may get zeroed earlier).

Do you really think I should try to decrease this delay?

[...]
>> +}
>> +
>> +static int msm_ofdata_to_platdata(struct udevice *dev)
>> +{
>> +       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 = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
>> +                                                     dev->parent->of_offset,
>> +                                                     dev->of_offset, "reg",
>> +                                                     1, NULL);
> 
> Odd that you are reading the second cell. How come?

I tried to use as much parts of original qcom Linux dts as possible.
For mmc controller, there are 2 addresses needed:
- - SDCC base (i.e. base of IP block with vendor-specific regs etc.)
- - SDHCI base (i.e. place where SDHCI "standard" registers start)

My assumption is that SDHCI offset may be different on different 
SoCs, and wanted to have generic driver.

[...]
Regards,
Mateusz

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

iQEcBAEBCAAGBQJWcenTAAoJELvtohmVtQzBddYH+waGw+OePJ8MdeMgI8BYJ295
3l+Op/2FGquWNIIoJRlO59JOeZqVkJJWOph19DQWpmybIra1HoRRmVTVqY2l2Fon
vTdzZ+cZ3jY2bzLGzYARXCEJ4jNxUILkPS/r/SrRfhDVC4vxSROSA7Jh6EmnssDm
kktzR98/o834uDQc0niGWYi9K1hpUnwQ3m8b1e8LmwdH3LcuHH7+UWntTnEesBai
Ox3ES6y5S9VtCBnyZ/LSilqe30AVB4ccKlk69G41AQYPI5u5CZEfm1OP8AGjpkfV
0D4WrErh/CGmYpG0b4G14CYe39GekCmD9IAnMC4zxjRwwZCmp1kGoeunNwpiLjk=
=scwU
-----END PGP SIGNATURE-----

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

* [U-Boot] [RFC PATCH 05/11] ehci: Add support for Qualcomm EHCI
  2015-12-13 15:48       ` Marek Vasut
@ 2015-12-16 22:51         ` Mateusz Kulikowski
  0 siblings, 0 replies; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-16 22:51 UTC (permalink / raw)
  To: u-boot

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

Hi Marek,

On 13.12.2015 16:48, Marek Vasut wrote:
> On Sunday, December 13, 2015 at 01:38:41 PM, Mateusz Kulikowski wrote:
[...]
>> It doesn't matter if I add it as
>> select USB_ULPI_VIEWPORT
>> in usb KConfig, or forcibly add CONFIG_USB_ULPI_VIEWPORT to .config
> 
> I think it should be quite easily possible to add this to USB Kconfig.

Will do.

>> I can use fsl headers with little exception that two registers are
>> marked as reserved: USB_AHB_MODE (0x98) and USB_GENCONFIG_2 (0xA0)
>>
>> My guess is that it's just different revision/config of IP core.
>>
>> Do you think it wouldn't look awkward if I use fsl headers?
> 
> Just rename them to ehci-ci.h, that should be the quickest.

Will do.

[...]
>>>> +	struct ulpi_viewport ulpi_vp = {.port_num = priv->ulpi_port,
>>>> +					.viewport_addr = priv->ulpi_base};
>>>> +
>>>> +	/* Disable VBUS mimicing in the controller. */
>>>> +	ulpi_write(&ulpi_vp, (u8 *)ULPI_MISC_A_CLEAR,
>>>
>>> This should be a pointer to a field in struct ulpi_regs, so the (u8 *)
>>> cast does not seem right. See for example ehci-zynq.c
>>
>> Perhaps I misussed ulpi_viewport code in that case;
>>
>> The reason is I need to access MISC_A register (0x96+) that is
>> not in ulpi_regs structure - afaik it's vendor-specific.
>>
>> Any hints how to tackle that properly?
>>
>> I can of course duplicate ulpi code, but it probably doesn't make much
>> sense.
> 
> I don't have a better suggestion, sorry. Let's keep this as-is unless
> someone can come up with something better. Code duplication is not a
> good idea, so we won't do that.

OK

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

iQEcBAEBCAAGBQJWcerfAAoJELvtohmVtQzB1AMH/260Ioo6W6+skWJJhmm+g3yD
B3kWhJWWyGPSkY4QcA7O/dgzU9i/n9a6gwlqcwYLhYlzyKG/p0aRBim0RWEFWK+S
V1SMYA3iQhYLkjMdOfqNXdQ5NrG2osll1Nk2GK9wBthVtPkjqfQkOupw7oZq3kd5
3pNpbsREIuxfct26C7kaTJccRf7MIYdlslYu53h4T/t03oO8xBIrSDGAR+9UD841
yCWuATbg461uhPrD1/WBG/wiIzMaOsITyiXIkxr7Z0GNrOeaZ38YqSwASwLTUmxO
NB+UkOvA9eM1oz79Qaoxyrfm/rDtds+CHXuFco2LY2gOl1280ffwKG1UQWCWDsk=
=XMV7
-----END PGP SIGNATURE-----

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

* [U-Boot] [RFC PATCH 06/11] drivers: Add SPMI bus uclass
  2015-12-15 18:58   ` Simon Glass
@ 2015-12-16 23:09     ` Mateusz Kulikowski
  0 siblings, 0 replies; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-16 23:09 UTC (permalink / raw)
  To: u-boot

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

Hi Simon,

On 15.12.2015 19:58, Simon Glass wrote:
> Hi Matheusz,
> 
> On 10 December 2015 at 14:41, Mateusz Kulikowski
> <mateusz.kulikowski@gmail.com> wrote:
[...]
>> +
>> +/**
>> + * 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
>> + * @write:     write register
> 
> You should describe the args also.

OK

> 
> What is different between this and I2C? Could you use that uclass? It
> seems to have an additional address value (pid)- is that right?

That's a difficult question, as my knowledge about this bus is based only
on drivers/SoC documentation/speculation (bus spec is not public :()

At wiring level it looks exactly like multi-master I2C
On logical level:
- - Each bus can have several slaves (up to 16).
- - Each slave can have several peripherals (up to 256),
- - Each peripheral can have up to 256 registers (I think each is 8-bit wide).
- - Each peripheral have 2 ID registers (type/subtype) that can be used
  for probing

PM8916 implements two slaves (but for some reason in Linux they are 
presented as 2 sibling nodes on SPMI bus).

But this is device perspective.

On SoC side, implementation is different and I fully don't understand 
all rationale behind it.

SoC has some kind of arbiter with 127 channels (2x - separate for 
reads called "observers" and separate for writers).

Each peripheral (not slave) has assigned single channel that I have 
to map in probe().
This means that (as far as I understand) there can be no more than
127 peripherals on single bus.

Weird think is that while doing reads/writes I have to use not 
only channel #, but also full slave/peripheral/register address.


Perhaps my driver oversimplified SPMI, or maybe SPMI is just I2C, 
using some simple protocol to charge royalty fees ;)


> 
> If you do end up with a new uclass, please add a sandbox driver for it
> and a test.
OK


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

iQEcBAEBCAAGBQJWce82AAoJELvtohmVtQzBLUIH/1NX6eAd+eh+HTTdntsni109
yQKMJVPEE17znTtcYgW2hpgWLqUa9aZ6n97hWMiWF7N+3879kWJYLTgj2uFBiVgl
nXS8DFdfE7BQlzwVrGLIoaIXC7Jx7w3O/+9k7XsTaU2QcX7E+rWjyj/Y88Uq8oen
M/MdtU2eYY/SggdMd99dEn305LrhRpXhDx0qgPTwGGb7BPwB2Vfrvm7mUrXMGTTY
GMbiKsNuiYzNdXGz65gmZ6fHHQM6Gmm5Lh5GYftMnn0qQA6D8PcDm8h+it1eqoW3
t1VpCmCp7k6eGzM6m+scwFHu0mCeGeYhYD+vRZIbxX0lu5UWIUuakVdjpJmn9Ig=
=iZjm
-----END PGP SIGNATURE-----

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

* [U-Boot] [RFC PATCH 03/11] mmc: Add support for Qualcomm SDHCI controller
  2015-12-16 22:46     ` Mateusz Kulikowski
@ 2015-12-18 22:41       ` Simon Glass
  2015-12-19 11:21         ` Mateusz Kulikowski
  0 siblings, 1 reply; 43+ messages in thread
From: Simon Glass @ 2015-12-18 22:41 UTC (permalink / raw)
  To: u-boot

Hi Mateusz,

On 16 December 2015 at 15:46, Mateusz Kulikowski
<mateusz.kulikowski@gmail.com> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA256
>
> Hi Simon,
>
> On 15.12.2015 19:58, Simon Glass wrote:
>> Hi Mateusz,
>>
>> On 10 December 2015 at 14:41, Mateusz Kulikowski
>> <mateusz.kulikowski@gmail.com> wrote:
> [...]
>>> +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 */
>>> +       fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "clock", clkd, 2);
>>> +       clkd[0] = fdt_node_offset_by_phandle(gd->fdt_blob, clkd[0]);
>>> +
>>> +       struct udevice *clk = NULL;
>>> +       uclass_get_device_by_of_offset(UCLASS_CLK, clkd[0], &clk);
>>> +       if (clk)
>>> +               clk_set_periph_rate(clk, clkd[1], clk_rate);
>>> +
>>
>> See comments on the previous patch. Also you could move the DT decode
>> code all into your ofdata_to_platdata function (if you like).
>
> But requesting clock must be handled in probe (i.e. when clock is
> already bound) right?

Yes. Although bear in mind that the ofdata_to_platdata() call is made
just before probe() so it is OK to put 'get' calls in there. In
general all devices are bound before any are probed.

>
>>
>>> +       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;
>>> +
>>> +       host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B;
>>> +
>>> +       /* Init clocks */
>>> +       if (msm_sdc_clk_init(dev))
>>> +               return -EIO;
>>> +
>>> +       /* Reset the core and Enable SDHC mode */
>>> +       writel(readl(prv->base + SDCC_MCI_POWER) | SDCC_MCI_POWER_SW_RST,
>>> +              prv->base + SDCC_MCI_POWER);
>>> +
>>> +       /* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */
>>> +       mdelay(2);
>>
>> So why such a long delay? Perhaps you should put the code immediately
>> below int a timeout loop?
>>
>> start = get_timer(0);
>> while (readl...) {
>>    if (get_timer(start) > 2)
>>       return -ETIMEDOUT;
>> }
>>
> I'm not sure if I can do that - I can test it, perhaps it will even work on
> my board, but it was put explicitly in Linux driver (1-5ms delay).
>
> Documentation says:
> "SW should wait until bit 0 (MCLK_REG_WR_ACTIVE) of MCI_STATUS2 register
> is 0, after writing to MCI_POWER register and before accessing this
> register again."
>
> But this applies to all writes, not to reset request - I'm not sure
> how MCI_STATUS2 will behave during reset (it may get zeroed earlier).
>
> Do you really think I should try to decrease this delay?

Can you change the code to wait until bit 0 is 0, instead of having a delay?

>
> [...]
>>> +}
>>> +
>>> +static int msm_ofdata_to_platdata(struct udevice *dev)
>>> +{
>>> +       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 = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
>>> +                                                     dev->parent->of_offset,
>>> +                                                     dev->of_offset, "reg",
>>> +                                                     1, NULL);
>>
>> Odd that you are reading the second cell. How come?
>
> I tried to use as much parts of original qcom Linux dts as possible.
> For mmc controller, there are 2 addresses needed:
> - - SDCC base (i.e. base of IP block with vendor-specific regs etc.)
> - - SDHCI base (i.e. place where SDHCI "standard" registers start)
>
> My assumption is that SDHCI offset may be different on different
> SoCs, and wanted to have generic driver.

OK I see, thanks.

Regards,
Simon

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

* [U-Boot] [RFC PATCH 03/11] mmc: Add support for Qualcomm SDHCI controller
  2015-12-18 22:41       ` Simon Glass
@ 2015-12-19 11:21         ` Mateusz Kulikowski
  0 siblings, 0 replies; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-19 11:21 UTC (permalink / raw)
  To: u-boot

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

Hi Simon, 

On 18.12.2015 23:41, Simon Glass wrote:
> Hi Mateusz,
> 
> On 16 December 2015 at 15:46, Mateusz Kulikowski
> <mateusz.kulikowski@gmail.com> wrote:
[...]
>> I'm not sure if I can do that - I can test it, perhaps it will even work on
>> my board, but it was put explicitly in Linux driver (1-5ms delay).
>>
>> Documentation says:
>> "SW should wait until bit 0 (MCLK_REG_WR_ACTIVE) of MCI_STATUS2 register
>> is 0, after writing to MCI_POWER register and before accessing this
>> register again."
>>
>> But this applies to all writes, not to reset request - I'm not sure
>> how MCI_STATUS2 will behave during reset (it may get zeroed earlier).
>>
>> Do you really think I should try to decrease this delay?
> 
> Can you change the code to wait until bit 0 is 0, instead of having a delay?

This seems to work - at least on my board so will do it that way - thanks :)

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

iQEcBAEBCAAGBQJWdT3MAAoJELvtohmVtQzBjRUIAIwoq7nv3Ed/WrDi+azQscUD
RvZe8KGFGy0VOVbrV4iMYmG6SJzN9cxrA4q1oGVsUWZyh1uHuDMlhdPLqaW6EIC5
wQFeY2zWffNKJlx1MGhJKwKB+plYXWzEp6LDYIgB+LaTOUCPZOsnxJvac6bDvXF/
FLR3AXGMzHL1nrty/7MToNB2AtRynBxwEPRmyu5e1aNd9rfq+CrkyIqcsQ9M7VQz
y1UbJCUWDcwKKIDLUMfM9z67xx7O436M1fDSL1ELxuxI8C2UtdiycFu/uKm3XP+o
Nt871BEKLwK5WnkuFERZaXd8kbUYq+j1iOlt+oL7pTOY8+8IBQABnHf3YT1TCUo=
=0ZkP
-----END PGP SIGNATURE-----

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

* [U-Boot] [RFC PATCH 10/11] arm: Add support for Qualcomm Snapdragon family
  2015-12-16 22:29   ` Simon Glass
@ 2015-12-19 12:12     ` Mateusz Kulikowski
  0 siblings, 0 replies; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-19 12:12 UTC (permalink / raw)
  To: u-boot

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

Hi Simon, 

On 16.12.2015 23:29, Simon Glass wrote:
> Hi Mateusz,
> 
> On 10 December 2015 at 14:41, Mateusz Kulikowski
> <mateusz.kulikowski@gmail.com> wrote:
[...]
>> diff --git a/arch/arm/mach-snapdragon/clock-apq8016.c b/arch/arm/mach-snapdragon/clock-apq8016.c
>> new file mode 100644
>> index 0000000..c8c15b4
>> --- /dev/null
>> +++ b/arch/arm/mach-snapdragon/clock-apq8016.c
> 
> Can this go in drivers/clk?

Yes, it can, but it's very SoC specific (at least for now).
That is - it will probably work only on 2 devices (APQ8016 and MSM8916).

[...]
>> +++ b/arch/arm/mach-snapdragon/include/mach/gpio.h
> 
> Should this go in a different patch? I thought you had a GPIO driver earlier?

Ouch... yeah, this should definitely go to msm_gpio

[...]
>> +#define _MACH_APQ8016_SYSMAP_H
>> +
>> +#define GICD_BASE 0x0b000000
>> +#define GICC_BASE 0x0a20c000
> 
> Do you need these? Perhaps they can go in the device tree?

Nope, at least not for now.

It's required by armv8/start.S so must go either to board file or here :(

Regards,
Mateusz

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

iQEcBAEBCAAGBQJWdUmXAAoJELvtohmVtQzBsHwIAIgP+U8rmDlDEGDnFXeN+cuy
xUv5wQQwOWI+KuIQtJnO99UTPmJqNkk/NrnKF5P2p9Mgo/yD3YK3teaaMkrtipbu
D8Aw62XxhPXciy5ZC1pdrKXHt29halZZwSX4BAwf2Drtp7LVZ7UmUDQlQQF4p/9Z
FAr4Ynk8B8Ut0XObX1hjs2IPcdRT2V2wU5Wd/mv4EixH7wfiGMhBmroxg94Y7W2q
ZjlxUNdLmjqJkbDzkXwDv5emil5HWtKkUxe9y4qg7nwGQgOf4NP0r4dUDzGHRrGH
20pr2VfwMS2mR7nfFrLAFxTM1Q/o6e26o5hLtGqvGLzqmEwdHz06zOwzgB0hRlE=
=rcwn
-----END PGP SIGNATURE-----

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

* [U-Boot] [RFC PATCH 11/11] board: Add Qualcomm Dragonboard 410C support
  2015-12-16 22:29   ` Simon Glass
@ 2015-12-19 12:24     ` Mateusz Kulikowski
  2015-12-19 20:29       ` Simon Glass
  0 siblings, 1 reply; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-19 12:24 UTC (permalink / raw)
  To: u-boot

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

Hi Simon,
 
On 16.12.2015 23:29, Simon Glass wrote:
> Hi Mateusz,
> 
> On 10 December 2015 at 14:41, Mateusz Kulikowski
> <mateusz.kulikowski@gmail.com> wrote:
[...]
> 
>> +
>> +int board_prepare_usb(enum usb_init_type type)
>> +{
>> +       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");
> 
> Is this really the standard binding? I would expect a USB node with a
> reset-gpios property.
> 

That's a good idea.

[...]
>> +
>> +/* 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");
> 
> Should this be a GPIO key?

Yes, but I couldn't find something like that in U-Boot.. did I missed it?

[...]
>> +
>> +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
>> +OUTPUT_ARCH(aarch64)
>> +ENTRY(_fastboot_header)
> 
> I wonder if you could use the standard .lds file and amend it to
> support fastboot?

Perhaps it's a good idea to make it generic option (at least for ARMv8 devices).

I'm not sure is it "generic" fastboot header or only works for Little Kernel 
on Qualcomm devices though.

@Albert what do you think?

> 
>> +SECTIONS
>> +{
>> +       . = 0x00000000;
>> +
>> +       . = ALIGN(8);
>> +       .text :
>> +       {
>> +               *(.__image_copy_start)
>> +               board/qualcomm/dragonboard410c/head.o (.text*)
>> +               CPUDIR/start.o (.text*)
>> +               *(.text*)
>> +       }
>> +

Regards,
Mateusz

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

iQEcBAEBCAAGBQJWdUxgAAoJELvtohmVtQzBSV0IAIeIJSDENgvWvR5Q7hkmGYWQ
y+M0QWFaZpAD+iyOsHBelRWpaOTlrjrnG7n9aAsUf6VUJ8d70p8dPDgycxoRyrtw
QdWGTfamlO3V9/cw0iLKlWpz3xXZXIVkMrLyhggZkA4anGMSopvNkuOs42LQSgnp
dOUJAEbLgwZBlALlZH3uAdpSuAYywbfDhyyXGXH4sCHhx2wNnLJjr4sXLoamz8Jd
2o9ITZfr5TAl3fWTxSRN0XHxUeFRYLUywpSyqmI9A3ajtsRSh8uPzde2v3PP6qjI
Qw94RrF2QWKSLu/OMehajcWzG6VYYKaGc0nMMmLV6aHL1VNI9FjRpUcSraHhU0A=
=AVPb
-----END PGP SIGNATURE-----

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

* [U-Boot] [RFC PATCH 11/11] board: Add Qualcomm Dragonboard 410C support
  2015-12-19 12:24     ` Mateusz Kulikowski
@ 2015-12-19 20:29       ` Simon Glass
  0 siblings, 0 replies; 43+ messages in thread
From: Simon Glass @ 2015-12-19 20:29 UTC (permalink / raw)
  To: u-boot

Hi Mateusz,

On 19 December 2015 at 05:24, Mateusz Kulikowski
<mateusz.kulikowski@gmail.com> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA256
>
> Hi Simon,
>
> On 16.12.2015 23:29, Simon Glass wrote:
>> Hi Mateusz,
>>
>> On 10 December 2015 at 14:41, Mateusz Kulikowski
>> <mateusz.kulikowski@gmail.com> wrote:
> [...]
>>
>>> +
>>> +int board_prepare_usb(enum usb_init_type type)
>>> +{
>>> +       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");
>>
>> Is this really the standard binding? I would expect a USB node with a
>> reset-gpios property.
>>
>
> That's a good idea.
>
> [...]
>>> +
>>> +/* 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");
>>
>> Should this be a GPIO key?
>
> Yes, but I couldn't find something like that in U-Boot.. did I missed it?
>
> [...]
>>> +
>>> +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
>>> +OUTPUT_ARCH(aarch64)
>>> +ENTRY(_fastboot_header)
>>
>> I wonder if you could use the standard .lds file and amend it to
>> support fastboot?
>
> Perhaps it's a good idea to make it generic option (at least for ARMv8 devices).
>
> I'm not sure is it "generic" fastboot header or only works for Little Kernel
> on Qualcomm devices though.
>
> @Albert what do you think?

I see later that you plan to remove this one day, so perhaps it is
fine to keep it as it is.

>
>>
>>> +SECTIONS
>>> +{
>>> +       . = 0x00000000;
>>> +
>>> +       . = ALIGN(8);
>>> +       .text :
>>> +       {
>>> +               *(.__image_copy_start)
>>> +               board/qualcomm/dragonboard410c/head.o (.text*)
>>> +               CPUDIR/start.o (.text*)
>>> +               *(.text*)
>>> +       }
>>> +


Regards,
Simon

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

* [U-Boot] [RFC PATCH 01/11] serial: Add support for Qualcomm serial port
  2015-12-15 18:58   ` Simon Glass
  2015-12-16 22:19     ` Mateusz Kulikowski
@ 2015-12-21  6:50     ` Masahiro Yamada
  2015-12-22 20:23       ` Simon Glass
  1 sibling, 1 reply; 43+ messages in thread
From: Masahiro Yamada @ 2015-12-21  6:50 UTC (permalink / raw)
  To: u-boot

2015-12-16 3:58 GMT+09:00 Simon Glass <sjg@chromium.org>:

>> +++ b/drivers/serial/serial_msm.c
>> @@ -0,0 +1,204 @@
>> +/*
>> + * 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 <asm/io.h>
>> +#include <common.h>
>> +#include <dm.h>
>> +#include <clk.h>
>> +#include <errno.h>
>> +#include <linux/compiler.h>
>> +#include <serial.h>
>> +#include <watchdog.h>
>
> Ordering:
>
> common.h
> clk.h
> dm.h
> errno.h
> serial.h
> watchdog.h
> asm/
> linux/
>
>

No.

Put <linux/*.h> above <asm/*.h>, at least.
(the same order in Linux)



BTW, the "Include file order" in
http://www.denx.de/wiki/U-Boot/CodingStyle

Is this your opinion? Or community's opinion.

Did anybody review it?




-- 
Best Regards
Masahiro Yamada

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

* [U-Boot] [RFC PATCH 01/11] serial: Add support for Qualcomm serial port
  2015-12-21  6:50     ` Masahiro Yamada
@ 2015-12-22 20:23       ` Simon Glass
  2015-12-23  3:52         ` Masahiro Yamada
  0 siblings, 1 reply; 43+ messages in thread
From: Simon Glass @ 2015-12-22 20:23 UTC (permalink / raw)
  To: u-boot

Hi Masahiro,

On 20 December 2015 at 23:50, Masahiro Yamada
<yamada.masahiro@socionext.com> wrote:
> 2015-12-16 3:58 GMT+09:00 Simon Glass <sjg@chromium.org>:
>
>>> +++ b/drivers/serial/serial_msm.c
>>> @@ -0,0 +1,204 @@
>>> +/*
>>> + * 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 <asm/io.h>
>>> +#include <common.h>
>>> +#include <dm.h>
>>> +#include <clk.h>
>>> +#include <errno.h>
>>> +#include <linux/compiler.h>
>>> +#include <serial.h>
>>> +#include <watchdog.h>
>>
>> Ordering:
>>
>> common.h
>> clk.h
>> dm.h
>> errno.h
>> serial.h
>> watchdog.h
>> asm/
>> linux/
>>
>>
>
> No.
>
> Put <linux/*.h> above <asm/*.h>, at least.
> (the same order in Linux)
>
>
>
> BTW, the "Include file order" in
> http://www.denx.de/wiki/U-Boot/CodingStyle
>
> Is this your opinion? Or community's opinion.
>
> Did anybody review it?

This came from Mike Frysinger some years ago on the mailing list and I
have followed it since. I took it to be a U-Boot standard and added it
to the Wiki at some point. Linux perhaps has linux/ above asm/ for its
own reasons (e.g. because it is Linux and needs its headers first) but
I don't think that is a good idea for U-Boot. It is unnecessary and
makes the sort order more confusing.

Regards,
Simon

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

* [U-Boot] [RFC PATCH 01/11] serial: Add support for Qualcomm serial port
  2015-12-22 20:23       ` Simon Glass
@ 2015-12-23  3:52         ` Masahiro Yamada
  2015-12-27 16:51           ` Mateusz Kulikowski
  2015-12-28  4:29           ` Simon Glass
  0 siblings, 2 replies; 43+ messages in thread
From: Masahiro Yamada @ 2015-12-23  3:52 UTC (permalink / raw)
  To: u-boot

Hi Simon,



>> BTW, the "Include file order" in
>> http://www.denx.de/wiki/U-Boot/CodingStyle
>>
>> Is this your opinion? Or community's opinion.
>>
>> Did anybody review it?
>
> This came from Mike Frysinger some years ago on the mailing list and I
> have followed it since. I took it to be a U-Boot standard and added it
> to the Wiki at some point. Linux perhaps has linux/ above asm/ for its
> own reasons (e.g. because it is Linux and needs its headers first) but
> I don't think that is a good idea for U-Boot. It is unnecessary and
> makes the sort order more confusing.
>

OK, but I want to know the reason.
Do you remember why Mike Frysinger suggested so?

I guess Linux sorts headers from global to local.

#include <linux/*.h>    global in the project
#include <asm/*.h>      arch-specific
#include "foo.h"        local in the directory


Likewise, the following makes sense for U-Boot

#include <common.h>
#include <*.h>              global in the project (U-boot orignal)
#include <linux/*.h>        global in the project (come from Linux)
#include <asm/*.h>          arch-specific
#include <asm/arch/*.h>     SoC-specific
#include "foo.h"            local in the directory

if I am not missing something...


-- 
Best Regards
Masahiro Yamada

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

* [U-Boot] [RFC PATCH 01/11] serial: Add support for Qualcomm serial port
  2015-12-23  3:52         ` Masahiro Yamada
@ 2015-12-27 16:51           ` Mateusz Kulikowski
  2015-12-28 17:09             ` Masahiro Yamada
  2015-12-28  4:29           ` Simon Glass
  1 sibling, 1 reply; 43+ messages in thread
From: Mateusz Kulikowski @ 2015-12-27 16:51 UTC (permalink / raw)
  To: u-boot

Hi Masahiro,

On 23.12.2015 04:52, Masahiro Yamada wrote:
[..]
> I guess Linux sorts headers from global to local.
> 
> #include <linux/*.h>    global in the project
> #include <asm/*.h>      arch-specific
> #include "foo.h"        local in the directory
> 
> 
> Likewise, the following makes sense for U-Boot
> 
> #include <common.h>
> #include <*.h>              global in the project (U-boot orignal)
> #include <linux/*.h>        global in the project (come from Linux)
> #include <asm/*.h>          arch-specific
> #include <asm/arch/*.h>     SoC-specific
> #include "foo.h"            local in the directory
> 
> if I am not missing something...
> 
> 

Is it OK with you if for V1 (I'd like to post it soon) I'll use order 
proposed by Simon (and U-Boot page in general), and then depending on
your discussion will swap (or not).

Regards,
Mateusz

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

* [U-Boot] [RFC PATCH 01/11] serial: Add support for Qualcomm serial port
  2015-12-23  3:52         ` Masahiro Yamada
  2015-12-27 16:51           ` Mateusz Kulikowski
@ 2015-12-28  4:29           ` Simon Glass
  2015-12-28 17:13             ` Masahiro Yamada
  1 sibling, 1 reply; 43+ messages in thread
From: Simon Glass @ 2015-12-28  4:29 UTC (permalink / raw)
  To: u-boot

Hi Masahiro,

On 22 December 2015 at 20:52, Masahiro Yamada
<yamada.masahiro@socionext.com> wrote:
> Hi Simon,
>
>
>
>>> BTW, the "Include file order" in
>>> http://www.denx.de/wiki/U-Boot/CodingStyle
>>>
>>> Is this your opinion? Or community's opinion.
>>>
>>> Did anybody review it?
>>
>> This came from Mike Frysinger some years ago on the mailing list and I
>> have followed it since. I took it to be a U-Boot standard and added it
>> to the Wiki at some point. Linux perhaps has linux/ above asm/ for its
>> own reasons (e.g. because it is Linux and needs its headers first) but
>> I don't think that is a good idea for U-Boot. It is unnecessary and
>> makes the sort order more confusing.
>>
>
> OK, but I want to know the reason.
> Do you remember why Mike Frysinger suggested so?
>
> I guess Linux sorts headers from global to local.
>
> #include <linux/*.h>    global in the project
> #include <asm/*.h>      arch-specific
> #include "foo.h"        local in the directory
>
>
> Likewise, the following makes sense for U-Boot
>
> #include <common.h>
> #include <*.h>              global in the project (U-boot orignal)
> #include <linux/*.h>        global in the project (come from Linux)
> #include <asm/*.h>          arch-specific
> #include <asm/arch/*.h>     SoC-specific
> #include "foo.h"            local in the directory
>
> if I am not missing something...

The only difference here seems to be the position of the linux
headers. I don't think it is a big deal to change it if you like. The
only think I don't like so much is that it seems easier to put 'linux'
after 'asm', since it matches the alphabetical order and may avoid
confusion. But it's not important to me - mostly we just need to be
consistent. If you want to do this, perhaps get an ack from Tom and
then update the wiki?

>
>
> --
> Best Regards
> Masahiro Yamada

Regards,
Simon

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

* [U-Boot] [RFC PATCH 01/11] serial: Add support for Qualcomm serial port
  2015-12-27 16:51           ` Mateusz Kulikowski
@ 2015-12-28 17:09             ` Masahiro Yamada
  0 siblings, 0 replies; 43+ messages in thread
From: Masahiro Yamada @ 2015-12-28 17:09 UTC (permalink / raw)
  To: u-boot

Hi Mateusz,

2015-12-28 1:51 GMT+09:00 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>:
> Hi Masahiro,
>
> On 23.12.2015 04:52, Masahiro Yamada wrote:
> [..]
>> I guess Linux sorts headers from global to local.
>>
>> #include <linux/*.h>    global in the project
>> #include <asm/*.h>      arch-specific
>> #include "foo.h"        local in the directory
>>
>>
>> Likewise, the following makes sense for U-Boot
>>
>> #include <common.h>
>> #include <*.h>              global in the project (U-boot orignal)
>> #include <linux/*.h>        global in the project (come from Linux)
>> #include <asm/*.h>          arch-specific
>> #include <asm/arch/*.h>     SoC-specific
>> #include "foo.h"            local in the directory
>>
>> if I am not missing something...
>>
>>
>
> Is it OK with you if for V1 (I'd like to post it soon) I'll use order
> proposed by Simon (and U-Boot page in general), and then depending on
> your discussion will swap (or not).


I am OK with that.



-- 
Best Regards
Masahiro Yamada

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

* [U-Boot] [RFC PATCH 01/11] serial: Add support for Qualcomm serial port
  2015-12-28  4:29           ` Simon Glass
@ 2015-12-28 17:13             ` Masahiro Yamada
  0 siblings, 0 replies; 43+ messages in thread
From: Masahiro Yamada @ 2015-12-28 17:13 UTC (permalink / raw)
  To: u-boot

Hi Simon,


2015-12-28 13:29 GMT+09:00 Simon Glass <sjg@chromium.org>:
> Hi Masahiro,
>
> On 22 December 2015 at 20:52, Masahiro Yamada
> <yamada.masahiro@socionext.com> wrote:
>> Hi Simon,
>>
>>
>>
>>>> BTW, the "Include file order" in
>>>> http://www.denx.de/wiki/U-Boot/CodingStyle
>>>>
>>>> Is this your opinion? Or community's opinion.
>>>>
>>>> Did anybody review it?
>>>
>>> This came from Mike Frysinger some years ago on the mailing list and I
>>> have followed it since. I took it to be a U-Boot standard and added it
>>> to the Wiki at some point. Linux perhaps has linux/ above asm/ for its
>>> own reasons (e.g. because it is Linux and needs its headers first) but
>>> I don't think that is a good idea for U-Boot. It is unnecessary and
>>> makes the sort order more confusing.
>>>
>>
>> OK, but I want to know the reason.
>> Do you remember why Mike Frysinger suggested so?
>>
>> I guess Linux sorts headers from global to local.
>>
>> #include <linux/*.h>    global in the project
>> #include <asm/*.h>      arch-specific
>> #include "foo.h"        local in the directory
>>
>>
>> Likewise, the following makes sense for U-Boot
>>
>> #include <common.h>
>> #include <*.h>              global in the project (U-boot orignal)
>> #include <linux/*.h>        global in the project (come from Linux)
>> #include <asm/*.h>          arch-specific
>> #include <asm/arch/*.h>     SoC-specific
>> #include "foo.h"            local in the directory
>>
>> if I am not missing something...
>
> The only difference here seems to be the position of the linux
> headers. I don't think it is a big deal to change it if you like. The
> only think I don't like so much is that it seems easier to put 'linux'
> after 'asm', since it matches the alphabetical order and may avoid
> confusion. But it's not important to me - mostly we just need to be
> consistent. If you want to do this, perhaps get an ack from Tom and
> then update the wiki?
>

OK.

Perhaps, we can continue this discussion in a more suitable subject.


-- 
Best Regards
Masahiro Yamada

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

end of thread, other threads:[~2015-12-28 17:13 UTC | newest]

Thread overview: 43+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-10 21:41 [U-Boot] [RFC PATCH 00/11] Add support for 96boards Dragonboard410C board Mateusz Kulikowski
2015-12-10 21:41 ` [U-Boot] [RFC PATCH 01/11] serial: Add support for Qualcomm serial port Mateusz Kulikowski
2015-12-15 18:58   ` Simon Glass
2015-12-16 22:19     ` Mateusz Kulikowski
2015-12-21  6:50     ` Masahiro Yamada
2015-12-22 20:23       ` Simon Glass
2015-12-23  3:52         ` Masahiro Yamada
2015-12-27 16:51           ` Mateusz Kulikowski
2015-12-28 17:09             ` Masahiro Yamada
2015-12-28  4:29           ` Simon Glass
2015-12-28 17:13             ` Masahiro Yamada
2015-12-10 21:41 ` [U-Boot] [RFC PATCH 02/11] gpio: Add support for Qualcomm gpio controller Mateusz Kulikowski
2015-12-15 18:58   ` Simon Glass
2015-12-10 21:41 ` [U-Boot] [RFC PATCH 03/11] mmc: Add support for Qualcomm SDHCI controller Mateusz Kulikowski
2015-12-15 18:58   ` Simon Glass
2015-12-16 22:46     ` Mateusz Kulikowski
2015-12-18 22:41       ` Simon Glass
2015-12-19 11:21         ` Mateusz Kulikowski
2015-12-10 21:41 ` [U-Boot] [RFC PATCH 04/11] ehci-hcd: Add init_after_reset Mateusz Kulikowski
2015-12-10 23:14   ` Marek Vasut
2015-12-16 22:30   ` Tom Rini
2015-12-10 21:41 ` [U-Boot] [RFC PATCH 05/11] ehci: Add support for Qualcomm EHCI Mateusz Kulikowski
2015-12-10 23:22   ` Marek Vasut
2015-12-13 12:38     ` Mateusz Kulikowski
2015-12-13 15:48       ` Marek Vasut
2015-12-16 22:51         ` Mateusz Kulikowski
2015-12-10 21:41 ` [U-Boot] [RFC PATCH 06/11] drivers: Add SPMI bus uclass Mateusz Kulikowski
2015-12-15 18:58   ` Simon Glass
2015-12-16 23:09     ` Mateusz Kulikowski
2015-12-10 21:41 ` [U-Boot] [RFC PATCH 07/11] drivers: spmi: Add support for Qualcomm SPMI bus driver Mateusz Kulikowski
2015-12-10 21:41 ` [U-Boot] [RFC PATCH 08/11] pmic: Add support for Qualcomm PM8916 PMIC Mateusz Kulikowski
2015-12-15 18:58   ` Simon Glass
2015-12-10 21:41 ` [U-Boot] [RFC PATCH 09/11] gpio: Add support for Qualcomm PM8916 gpios Mateusz Kulikowski
2015-12-15 18:58   ` Simon Glass
2015-12-10 21:41 ` [U-Boot] [RFC PATCH 10/11] arm: Add support for Qualcomm Snapdragon family Mateusz Kulikowski
2015-12-16 22:29   ` Simon Glass
2015-12-19 12:12     ` Mateusz Kulikowski
2015-12-10 21:41 ` [U-Boot] [RFC PATCH 11/11] board: Add Qualcomm Dragonboard 410C support Mateusz Kulikowski
2015-12-16 22:29   ` Simon Glass
2015-12-19 12:24     ` Mateusz Kulikowski
2015-12-19 20:29       ` Simon Glass
2015-12-15 18:57 ` [U-Boot] [RFC PATCH 00/11] Add support for 96boards Dragonboard410C board sk.syed2
2015-12-15 21:25   ` Mateusz Kulikowski

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.