[U-Boot] [PATCH v2 00/18] Add support for 96boards Dragonboard410C board

Hi All,
This is updated series. 99% of review changes are applied, specific changes are (as always) include in each patch.
You can find this series on my github (if anyone just want to try it - that branch has also wait_for_bit applied): https://github.com/hallor/u-boot/tree/dragonboard-for-mainline-v2
I did target tests on Dragonboard410c, and build tested platforms that may be affected by ULPI changes.
@Simon: I decided not to rewrite pm8916_gpio for now, but for sake of "cleannes" moved offending bindings to separate file (and they are now properly childs of pm8916_gpio). I will update it during rework of SoC gpio driver (I will have to create proper pinmux/pinctrl drivers to get rid of Little Kernel eventually).
This series still needs wait_for_bit series that is not included (yet).
Regards, Mateusz
V1 cover contents:
I finally managed to cleanup RFC for submission. I've included changes in each patch, there is a bit of them, but all are needed :)
This series requires wait_for_bit patch that I send few days ago: https://patchwork.ozlabs.org/patch/561185/
RFC cover contents: http://lists.denx.de/pipermail/u-boot/2015-December/237365.html
Changes in v2: - Added newline before return... (globally) - Renamed p to priv (priv data) - it required some rewrapping - Added Reviewed-by - Reordered includes (again) - Added newlines between returns - Fixed error handling in msm_gpio_probe - Added reviewed-by - Add reviewed-by - Add Reviewed-by (sjg) - Add better (any) descriptions for Kconfig items. - New patch, independent of the rest - Should compile cleanly on all affected platforms - Is orthogonal to series (i.e. if get's NAK will not break rest of series) - Add acked-by - Add reviewed-by - Add Acked-by - Use PORT_... macro to write to portsc - Remove extra whitespace in probe() - Add acked-by - Use proper entry order in Kconfig - Rename CONFIG_DM_SPMI -> CONFIG_SPMI - Fix header ordering - Add reviewed-by - Rename CONFIG_DM_SPMI -> CONFIG_SPMI - Rename r -> regs, p -> priv - Add reviewed-by - Update binding doc (drop unused bindig) - Rename DM_SPMI -> SPMI - Rename p -> priv (in write/read) - Fix header ordering (again) - Add reviewed-by - Add reviewed-by - Reordered Kconfig & Makefile (to keep alphabetical ordering) - Added link to dt binding @ help - Add Reviewed-by - Rename DM_SPMI -> SPMI - Make MND divider comments more compact :) - p -> priv - Add reviewed-by - Reordered Kconfig to keep alphabetical order - Renamed reset_sandbox -> msm_reset (typo in reset.c) - Renamed CONFIG_DM_SPMI -> CONFIG_SPMI - Removed extra enter in dragonboard file - Added ULPI* to defconfig - Added MAINTAINERS to board - Cleaned up config file - use distro defaults/environment: - Dropped multiple CONFIG_CMD* and other CONFIG_* - Added distro env/config - Dropped old boot commands - Split dts - pm8916_gpio entries are taken directly from Linux Dragonboard dts; Add handles for u-boot in -uboot.dtsi; They will be removed once gpio drivers are converted to pinctrl. - Renamed some pmic nodes, fixed dragonboard.c to find them properly. - Added header and converted comments to c98-style in head.S - Print error if pmic gpio node is not found. - New patch
Changes in v1: - Added (better) help to KConfig - Added dt binding documentation - Fixed include ordering - Reworked msm_serial_getc - Added error handling to msm_uart_clk_init (that is ignored later for now) - Dropped unneeded DM_FLAG_PRE_RELOC - Added dt binding documentation - Added help to KConfig - Use clrsetbits() to switch direction - Fixed include order - Added #defines for registers/register fields - Added secondary compatible string - Added commit message - Added DT binding documentation - Added Kconfig help - Reordered includes - Dropped redundant fields from msm_sdhc - Cleaned up clock init code (+ added error handling) - Dropped mdelay - use wait_for_bit instead in reset code - Added missing newline after declarations - Added error handling if "reg" is missing - Converted base address to pointer - No changes, just added Acked-by, Reviewed-by - Reordered header files - Removed braces around constant - Added more verbose help to KConfig - Added ULPI dependency to Kconfig - Drop register #defines - use ehci-ci.h instead - Create fixed ulpi viewport for device - Use setbits/clearbits where possible - Use wait_for_bit to reset controller - Add dt binding documents - Reorder includes - Add read/write arguments documentation - add binding documentation and better Kconfig help - Changed a bit mapping - Change include order - Use clrsetbits* where possible - Add one more supported dts id - Handle missing fields in dt properly - Added dt bindings - Reoder includes - Replaced extract_* macros with ordinary shift/mask - Added error checking and whitespaces in probe - Add binding doc - Fixed inlcude ordering - Merged direction_input and direction_output functions - gpio_get: use switch instead of stacked if - use pmic_clrsetbits - add possibility to change prwkey bank name - Handle invalid bindings - Sanity HW check (i.e. check type/subtype registers) - Fix include order - Cleanup defines (added spaces for readibility) - Base address is integer to avoid casting - Use setbits_* family where possible - Drop unneded comments, added newlines where needed - Check return value of dev_get_addr - Add binding for apq8016 - Cleaned up divider calculation - Drop most of gpio.h (only empty file is needed) - Add better help for dragonboard - Move static structures to board_prepare_usb - Add DM_SPMI to defconfig
Mateusz Kulikowski (18): serial: Add support for Qualcomm serial port gpio: Add support for Qualcomm gpio controller mmc: Add support for Qualcomm SDHCI controller ehci-hcd: Add init_after_reset usb: ulpi: Add Kconfig options for ULPI Migrate CONFIG_ULPI* to Kconfig usb: Rename ehci-fsl.h to ehci-ci.h usb: ehci-ci: Add missing registers. ehci-ci.h: drop generic USBCMD fields ehci: Add support for Qualcomm EHCI drivers: Add SPMI bus uclass spmi: Add sandbox test driver drivers: spmi: Add support for Qualcomm SPMI bus driver pmic: Add support for Qualcomm PM8916 PMIC gpio: Add support for Qualcomm PM8916 gpios arm: Add support for Qualcomm Snapdragon family board: Add Qualcomm Dragonboard 410C support Add myself as Snapdragon and SPMI maintainer
MAINTAINERS | 11 + arch/arm/Kconfig | 12 + arch/arm/Makefile | 1 + arch/arm/dts/Makefile | 2 + arch/arm/dts/dragonboard410c-uboot.dtsi | 28 ++ arch/arm/dts/dragonboard410c.dts | 148 ++++++++++ arch/arm/mach-snapdragon/Kconfig | 26 ++ arch/arm/mach-snapdragon/Makefile | 8 + arch/arm/mach-snapdragon/clock-apq8016.c | 262 ++++++++++++++++++ arch/arm/mach-snapdragon/include/mach/gpio.h | 9 + .../mach-snapdragon/include/mach/sysmap-apq8016.h | 14 + arch/arm/mach-snapdragon/reset.c | 40 +++ arch/sandbox/dts/sandbox.dts | 20 ++ board/qualcomm/dragonboard410c/Kconfig | 15 + board/qualcomm/dragonboard410c/MAINTAINERS | 6 + board/qualcomm/dragonboard410c/Makefile | 8 + board/qualcomm/dragonboard410c/dragonboard410c.c | 131 +++++++++ board/qualcomm/dragonboard410c/head.S | 28 ++ board/qualcomm/dragonboard410c/readme.txt | 40 +++ board/qualcomm/dragonboard410c/u-boot.lds | 90 ++++++ configs/colibri_t20_defconfig | 2 + configs/dragonboard410c_defconfig | 31 +++ configs/harmony_defconfig | 2 + configs/mcx_defconfig | 3 + configs/mt_ventoux_defconfig | 3 + configs/sandbox_defconfig | 4 + configs/twister_defconfig | 3 + configs/zynq_picozed_defconfig | 3 + configs/zynq_zc702_defconfig | 3 + configs/zynq_zc706_defconfig | 3 + configs/zynq_zed_defconfig | 3 + configs/zynq_zybo_defconfig | 3 + doc/device-tree-bindings/gpio/gpio-msm.txt | 22 ++ doc/device-tree-bindings/gpio/pm8916_gpio.txt | 48 ++++ doc/device-tree-bindings/mmc/msm_sdhci.txt | 25 ++ doc/device-tree-bindings/pmic/pm8916.txt | 18 ++ doc/device-tree-bindings/serial/msm-serial.txt | 6 + doc/device-tree-bindings/spmi/spmi-msm.txt | 26 ++ doc/device-tree-bindings/spmi/spmi-sandbox.txt | 31 +++ doc/device-tree-bindings/usb/ehci-msm.txt | 10 + doc/git-mailrc | 3 + drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/gpio/Kconfig | 24 ++ drivers/gpio/Makefile | 3 +- drivers/gpio/msm_gpio.c | 135 +++++++++ drivers/gpio/pm8916_gpio.c | 302 +++++++++++++++++++++ drivers/mmc/Kconfig | 9 + drivers/mmc/Makefile | 1 + drivers/mmc/msm_sdhci.c | 180 ++++++++++++ drivers/power/pmic/Kconfig | 16 ++ drivers/power/pmic/Makefile | 1 + drivers/power/pmic/pm8916.c | 96 +++++++ drivers/serial/Kconfig | 8 + drivers/serial/Makefile | 1 + drivers/serial/serial_msm.c | 212 +++++++++++++++ drivers/spmi/Kconfig | 23 ++ drivers/spmi/Makefile | 9 + drivers/spmi/spmi-msm.c | 189 +++++++++++++ drivers/spmi/spmi-sandbox.c | 157 +++++++++++ drivers/spmi/spmi-uclass.c | 48 ++++ drivers/usb/Kconfig | 2 + drivers/usb/host/Kconfig | 11 + drivers/usb/host/Makefile | 1 + drivers/usb/host/ehci-fsl.c | 2 +- drivers/usb/host/ehci-hcd.c | 6 + drivers/usb/host/ehci-mpc512x.c | 6 +- drivers/usb/host/ehci-msm.c | 178 ++++++++++++ drivers/usb/host/ehci-mx5.c | 2 +- drivers/usb/host/ehci-mx6.c | 2 +- drivers/usb/host/ehci-mxc.c | 2 +- drivers/usb/host/ehci-vf.c | 2 +- drivers/usb/host/ehci-zynq.c | 2 +- drivers/usb/host/ehci.h | 1 + drivers/usb/ulpi/Kconfig | 33 +++ include/configs/colibri_t20.h | 2 - include/configs/dragonboard410c.h | 153 +++++++++++ include/configs/harmony.h | 2 - include/configs/mcx.h | 2 - include/configs/tam3517-common.h | 2 - include/configs/zynq-common.h | 2 - include/dm/uclass-id.h | 1 + include/spmi/spmi.h | 47 ++++ include/usb/{ehci-fsl.h => ehci-ci.h} | 16 +- test/dm/Makefile | 1 + test/dm/spmi.c | 115 ++++++++ 86 files changed, 3133 insertions(+), 28 deletions(-) create mode 100644 arch/arm/dts/dragonboard410c-uboot.dtsi 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/MAINTAINERS create mode 100644 board/qualcomm/dragonboard410c/Makefile create mode 100644 board/qualcomm/dragonboard410c/dragonboard410c.c create mode 100644 board/qualcomm/dragonboard410c/head.S create mode 100644 board/qualcomm/dragonboard410c/readme.txt create mode 100644 board/qualcomm/dragonboard410c/u-boot.lds create mode 100644 configs/dragonboard410c_defconfig create mode 100644 doc/device-tree-bindings/gpio/gpio-msm.txt create mode 100644 doc/device-tree-bindings/gpio/pm8916_gpio.txt create mode 100644 doc/device-tree-bindings/mmc/msm_sdhci.txt create mode 100644 doc/device-tree-bindings/pmic/pm8916.txt create mode 100644 doc/device-tree-bindings/serial/msm-serial.txt create mode 100644 doc/device-tree-bindings/spmi/spmi-msm.txt create mode 100644 doc/device-tree-bindings/spmi/spmi-sandbox.txt create mode 100644 doc/device-tree-bindings/usb/ehci-msm.txt create mode 100644 drivers/gpio/msm_gpio.c create mode 100644 drivers/gpio/pm8916_gpio.c create mode 100644 drivers/mmc/msm_sdhci.c create mode 100644 drivers/power/pmic/pm8916.c create mode 100644 drivers/serial/serial_msm.c create mode 100644 drivers/spmi/Kconfig create mode 100644 drivers/spmi/Makefile create mode 100644 drivers/spmi/spmi-msm.c create mode 100644 drivers/spmi/spmi-sandbox.c create mode 100644 drivers/spmi/spmi-uclass.c create mode 100644 drivers/usb/host/ehci-msm.c create mode 100644 drivers/usb/ulpi/Kconfig create mode 100644 include/configs/dragonboard410c.h create mode 100644 include/spmi/spmi.h rename include/usb/{ehci-fsl.h => ehci-ci.h} (96%) create mode 100644 test/dm/spmi.c

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

On 24 January 2016 at 13:52, 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 Reviewed-by: Simon Glass sjg@chromium.org
Changes in v2:
- Added newline before return... (globally)
- Renamed p to priv (priv data) - it required some rewrapping
- Added Reviewed-by
Changes in v1:
- Added (better) help to KConfig
- Added dt binding documentation
- Fixed include ordering
- Reworked msm_serial_getc
- Added error handling to msm_uart_clk_init (that is ignored later for now)
- Dropped unneeded DM_FLAG_PRE_RELOC
doc/device-tree-bindings/serial/msm-serial.txt | 6 + drivers/serial/Kconfig | 8 + drivers/serial/Makefile | 1 + drivers/serial/serial_msm.c | 212 +++++++++++++++++++++++++ 4 files changed, 227 insertions(+) create mode 100644 doc/device-tree-bindings/serial/msm-serial.txt create mode 100644 drivers/serial/serial_msm.c
Tested-by: Simon Glass sjg@chromium.org

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

On 24 January 2016 at 13:52, 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 Reviewed-by: Simon Glass sjg@chromium.org
Changes in v2:
- Reordered includes (again)
- Added newlines between returns
- Fixed error handling in msm_gpio_probe
- Added reviewed-by
Changes in v1:
- Added dt binding documentation
- Added help to KConfig
- Use clrsetbits() to switch direction
- Fixed include order
- Added #defines for registers/register fields
- Added secondary compatible string
doc/device-tree-bindings/gpio/gpio-msm.txt | 22 +++++ drivers/gpio/Kconfig | 14 +++ drivers/gpio/Makefile | 2 +- drivers/gpio/msm_gpio.c | 135 +++++++++++++++++++++++++++++ 4 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 doc/device-tree-bindings/gpio/gpio-msm.txt create mode 100644 drivers/gpio/msm_gpio.c
Tested-by: Simon Glass sjg@chromium.org

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

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

Some host controllers need addidional initialization after ehci_reset() In non-dm implementation it is possible to use CONFIG_EHCI_HCD_INIT_AFTER_RESET. This patch adds similar option to ehci drivers using dm.
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com Acked-by: Marek Vasut marex@denx.de Reviewed-by: Tom Rini trini@konsulko.com Reviewed-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Add Reviewed-by (sjg)
Changes in v1: - No changes, just added Acked-by, Reviewed-by
drivers/usb/host/ehci-hcd.c | 6 ++++++ drivers/usb/host/ehci.h | 1 + 2 files changed, 7 insertions(+)
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c664b16..a4635ef 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1614,6 +1614,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 {

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

The following options can be now enabled via defconfig: - CONFIG_USB_ULPI - CONFIG_USB_ULPI_VIEWPORT - CONFIG_USB_ULPI_VIEWPORT_OMAP
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com ---
Changes in v2: - Add better (any) descriptions for Kconfig items.
Changes in v1: None
drivers/usb/Kconfig | 2 ++ drivers/usb/ulpi/Kconfig | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 drivers/usb/ulpi/Kconfig
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index abb06fc..57b99f2 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -53,6 +53,8 @@ source "drivers/usb/musb-new/Kconfig"
source "drivers/usb/emul/Kconfig"
+source "drivers/usb/ulpi/Kconfig" + comment "USB peripherals"
config USB_STORAGE diff --git a/drivers/usb/ulpi/Kconfig b/drivers/usb/ulpi/Kconfig new file mode 100644 index 0000000..329d2df --- /dev/null +++ b/drivers/usb/ulpi/Kconfig @@ -0,0 +1,33 @@ +comment "ULPI drivers" + +choice + prompt "ULPI Viewport type" + optional + default n + help + Select ULPI viewport (SoC-side interface to ULPI) implementation + appropriate for the device if you want to communicate with + UTMI (USB PHY) via ULPI interface. + +config USB_ULPI_VIEWPORT + bool "Generic ULPI Viewport" + help + Support generic ULPI Viewport implementation that is used on + some Tegra and Snapdragon devices. + +config USB_ULPI_VIEWPORT_OMAP + bool "OMAP ULPI Viewport" + help + Support ULPI Viewport implementation that is used on OMAP devices. + +endchoice + +config USB_ULPI + bool "ULPI support" + depends on (USB_ULPI_VIEWPORT || USB_ULPI_VIEWPORT_OMAP) + help + Select to commnicate with USB PHY via ULPI interface. + ULPI is wrapper on UTMI+ core that is used as + PHY Transreceiver for USB controllers. + + This driver uses ULPI viewports that are specific for each SoC.

On 24 January 2016 at 13:52, Mateusz Kulikowski mateusz.kulikowski@gmail.com wrote:
The following options can be now enabled via defconfig:
- CONFIG_USB_ULPI
- CONFIG_USB_ULPI_VIEWPORT
- CONFIG_USB_ULPI_VIEWPORT_OMAP
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com
Changes in v2:
- Add better (any) descriptions for Kconfig items.
Changes in v1: None
drivers/usb/Kconfig | 2 ++ drivers/usb/ulpi/Kconfig | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 drivers/usb/ulpi/Kconfig
Reviewed-by: Simon Glass sjg@chromium.org

Move CONFIG_USB_ULPI* from headers to defconfigs for boards that use it. Also - add CONFIG_USB where necesarry - all boards use it, but some are not defining it explicitly.
Affected boards: colibri_t20, harmony, mcx, mt_ventoux, twister, zynq_(picozed, zc702, zc706, zed, zybo)
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com ---
Changes in v2: - New patch, independent of the rest - Should compile cleanly on all affected platforms - Is orthogonal to series (i.e. if get's NAK will not break rest of series)
Changes in v1: None
configs/colibri_t20_defconfig | 2 ++ configs/harmony_defconfig | 2 ++ configs/mcx_defconfig | 3 +++ configs/mt_ventoux_defconfig | 3 +++ configs/twister_defconfig | 3 +++ configs/zynq_picozed_defconfig | 3 +++ configs/zynq_zc702_defconfig | 3 +++ configs/zynq_zc706_defconfig | 3 +++ configs/zynq_zed_defconfig | 3 +++ configs/zynq_zybo_defconfig | 3 +++ include/configs/colibri_t20.h | 2 -- include/configs/harmony.h | 2 -- include/configs/mcx.h | 2 -- include/configs/tam3517-common.h | 2 -- include/configs/zynq-common.h | 2 -- 15 files changed, 28 insertions(+), 10 deletions(-)
diff --git a/configs/colibri_t20_defconfig b/configs/colibri_t20_defconfig index 982cee4..143d33a 100644 --- a/configs/colibri_t20_defconfig +++ b/configs/colibri_t20_defconfig @@ -14,4 +14,6 @@ CONFIG_CMD_GPIO=y CONFIG_SYS_NS16550=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y CONFIG_USE_PRIVATE_LIBGCC=y diff --git a/configs/harmony_defconfig b/configs/harmony_defconfig index a3f73cc..1a301f8 100644 --- a/configs/harmony_defconfig +++ b/configs/harmony_defconfig @@ -15,4 +15,6 @@ CONFIG_CMD_GPIO=y CONFIG_SYS_NS16550=y CONFIG_USB=y CONFIG_DM_USB=y +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y CONFIG_USE_PRIVATE_LIBGCC=y diff --git a/configs/mcx_defconfig b/configs/mcx_defconfig index 1e204d5..612bf66 100644 --- a/configs/mcx_defconfig +++ b/configs/mcx_defconfig @@ -10,3 +10,6 @@ CONFIG_SYS_PROMPT="mcx # " CONFIG_CMD_GPIO=y # CONFIG_CMD_SETEXPR is not set CONFIG_SYS_NS16550=y +CONFIG_USB=y +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT_OMAP=y diff --git a/configs/mt_ventoux_defconfig b/configs/mt_ventoux_defconfig index a0153e4..8b3298b 100644 --- a/configs/mt_ventoux_defconfig +++ b/configs/mt_ventoux_defconfig @@ -8,3 +8,6 @@ CONFIG_SYS_PROMPT="mt_ventoux => " CONFIG_CMD_GPIO=y # CONFIG_CMD_SETEXPR is not set CONFIG_SYS_NS16550=y +CONFIG_USB=y +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT_OMAP=y diff --git a/configs/twister_defconfig b/configs/twister_defconfig index e721edb..a1abbe1 100644 --- a/configs/twister_defconfig +++ b/configs/twister_defconfig @@ -8,3 +8,6 @@ CONFIG_SYS_PROMPT="twister => " CONFIG_CMD_GPIO=y # CONFIG_CMD_SETEXPR is not set CONFIG_SYS_NS16550=y +CONFIG_USB=y +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT_OMAP=y diff --git a/configs/zynq_picozed_defconfig b/configs/zynq_picozed_defconfig index 339e399..a3ad3de 100644 --- a/configs/zynq_picozed_defconfig +++ b/configs/zynq_picozed_defconfig @@ -10,3 +10,6 @@ CONFIG_CMD_GPIO=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_ZYNQ_GEM=y +CONFIG_USB=y +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y diff --git a/configs/zynq_zc702_defconfig b/configs/zynq_zc702_defconfig index 065f855..3766ab0 100644 --- a/configs/zynq_zc702_defconfig +++ b/configs/zynq_zc702_defconfig @@ -21,3 +21,6 @@ CONFIG_DEBUG_UART_ZYNQ=y CONFIG_DEBUG_UART_BASE=0xe0001000 CONFIG_DEBUG_UART_CLOCK=50000000 CONFIG_ZYNQ_QSPI=y +CONFIG_USB=y +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y diff --git a/configs/zynq_zc706_defconfig b/configs/zynq_zc706_defconfig index 1059689..96f78bb 100644 --- a/configs/zynq_zc706_defconfig +++ b/configs/zynq_zc706_defconfig @@ -18,3 +18,6 @@ CONFIG_SPI_FLASH_STMICRO=y CONFIG_SPI_FLASH_WINBOND=y CONFIG_ZYNQ_GEM=y CONFIG_ZYNQ_QSPI=y +CONFIG_USB=y +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y diff --git a/configs/zynq_zed_defconfig b/configs/zynq_zed_defconfig index 73b17e2..fe7384f 100644 --- a/configs/zynq_zed_defconfig +++ b/configs/zynq_zed_defconfig @@ -18,3 +18,6 @@ CONFIG_SPI_FLASH_STMICRO=y CONFIG_SPI_FLASH_WINBOND=y CONFIG_ZYNQ_GEM=y CONFIG_ZYNQ_QSPI=y +CONFIG_USB=y +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y diff --git a/configs/zynq_zybo_defconfig b/configs/zynq_zybo_defconfig index 577c5a9..d471c6c 100644 --- a/configs/zynq_zybo_defconfig +++ b/configs/zynq_zybo_defconfig @@ -20,3 +20,6 @@ CONFIG_DEBUG_UART_CLOCK=50000000 CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_ZYNQ_QSPI=y +CONFIG_USB=y +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y diff --git a/include/configs/colibri_t20.h b/include/configs/colibri_t20.h index 7611fc5..270eb1d 100644 --- a/include/configs/colibri_t20.h +++ b/include/configs/colibri_t20.h @@ -36,8 +36,6 @@ /* USB host support */ #define CONFIG_USB_EHCI #define CONFIG_USB_EHCI_TEGRA -#define CONFIG_USB_ULPI -#define CONFIG_USB_ULPI_VIEWPORT #define CONFIG_USB_MAX_CONTROLLER_COUNT 3 #define CONFIG_USB_STORAGE #define CONFIG_CMD_USB diff --git a/include/configs/harmony.h b/include/configs/harmony.h index e0bc7c0..d842ceb 100644 --- a/include/configs/harmony.h +++ b/include/configs/harmony.h @@ -45,8 +45,6 @@ #define CONFIG_USB_MAX_CONTROLLER_COUNT 3 #define CONFIG_USB_EHCI #define CONFIG_USB_EHCI_TEGRA -#define CONFIG_USB_ULPI -#define CONFIG_USB_ULPI_VIEWPORT #define CONFIG_USB_STORAGE #define CONFIG_CMD_USB
diff --git a/include/configs/mcx.h b/include/configs/mcx.h index 4eea06d..7987b2c 100644 --- a/include/configs/mcx.h +++ b/include/configs/mcx.h @@ -105,8 +105,6 @@ #define CONFIG_OMAP3_GPIO_5 #define CONFIG_USB_EHCI #define CONFIG_USB_EHCI_OMAP -#define CONFIG_USB_ULPI -#define CONFIG_USB_ULPI_VIEWPORT_OMAP #define CONFIG_OMAP_EHCI_PHY1_RESET_GPIO 57 #define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 #define CONFIG_USB_HOST_ETHER diff --git a/include/configs/tam3517-common.h b/include/configs/tam3517-common.h index 2d941ca..0a4d3fa 100644 --- a/include/configs/tam3517-common.h +++ b/include/configs/tam3517-common.h @@ -91,8 +91,6 @@ #define CONFIG_OMAP3_GPIO_5 #define CONFIG_USB_EHCI #define CONFIG_USB_EHCI_OMAP -#define CONFIG_USB_ULPI -#define CONFIG_USB_ULPI_VIEWPORT_OMAP #define CONFIG_OMAP_EHCI_PHY1_RESET_GPIO 25 #define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 #define CONFIG_USB_STORAGE diff --git a/include/configs/zynq-common.h b/include/configs/zynq-common.h index 0ab6083..7d55833 100644 --- a/include/configs/zynq-common.h +++ b/include/configs/zynq-common.h @@ -101,8 +101,6 @@ # define CONFIG_CMD_USB # define CONFIG_USB_STORAGE # define CONFIG_USB_EHCI_ZYNQ -# define CONFIG_USB_ULPI_VIEWPORT -# define CONFIG_USB_ULPI # define CONFIG_EHCI_IS_TDI # define CONFIG_USB_MAX_CONTROLLER_COUNT 2

On 24 January 2016 at 13:52, Mateusz Kulikowski mateusz.kulikowski@gmail.com wrote:
Move CONFIG_USB_ULPI* from headers to defconfigs for boards that use it. Also - add CONFIG_USB where necesarry - all boards use it, but some are not defining it explicitly.
Affected boards: colibri_t20, harmony, mcx, mt_ventoux, twister, zynq_(picozed, zc702, zc706, zed, zybo)
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com
Changes in v2:
- New patch, independent of the rest
- Should compile cleanly on all affected platforms
- Is orthogonal to series (i.e. if get's NAK will not break rest of series)
Changes in v1: None
configs/colibri_t20_defconfig | 2 ++ configs/harmony_defconfig | 2 ++ configs/mcx_defconfig | 3 +++ configs/mt_ventoux_defconfig | 3 +++ configs/twister_defconfig | 3 +++ configs/zynq_picozed_defconfig | 3 +++ configs/zynq_zc702_defconfig | 3 +++ configs/zynq_zc706_defconfig | 3 +++ configs/zynq_zed_defconfig | 3 +++ configs/zynq_zybo_defconfig | 3 +++ include/configs/colibri_t20.h | 2 -- include/configs/harmony.h | 2 -- include/configs/mcx.h | 2 -- include/configs/tam3517-common.h | 2 -- include/configs/zynq-common.h | 2 -- 15 files changed, 28 insertions(+), 10 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

Most of ehci-fsl header describe USB controller designed by Chipidea and used by various SoC vendors.
This patch renames it to a generic header: ehci-ci.h Contents of file are not changed (so it contains several references to freescale SoCs).
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com Acked-by: Marek Vasut marex@denx.de ---
Changes in v2: - Add acked-by
Changes in v1: None
drivers/usb/host/ehci-fsl.c | 2 +- drivers/usb/host/ehci-mpc512x.c | 2 +- drivers/usb/host/ehci-mx5.c | 2 +- drivers/usb/host/ehci-mx6.c | 2 +- drivers/usb/host/ehci-mxc.c | 2 +- drivers/usb/host/ehci-vf.c | 2 +- drivers/usb/host/ehci-zynq.c | 2 +- include/usb/{ehci-fsl.h => ehci-ci.h} | 6 +++--- 8 files changed, 10 insertions(+), 10 deletions(-) rename include/usb/{ehci-fsl.h => ehci-ci.h} (99%)
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 97b7f14..4bcea9d 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -12,7 +12,7 @@ #include <pci.h> #include <usb.h> #include <asm/io.h> -#include <usb/ehci-fsl.h> +#include <usb/ehci-ci.h> #include <hwconfig.h> #include <fsl_usb.h> #include <fdt_support.h> diff --git a/drivers/usb/host/ehci-mpc512x.c b/drivers/usb/host/ehci-mpc512x.c index b320c4a..4b50ac8 100644 --- a/drivers/usb/host/ehci-mpc512x.c +++ b/drivers/usb/host/ehci-mpc512x.c @@ -17,7 +17,7 @@ #include <pci.h> #include <usb.h> #include <asm/io.h> -#include <usb/ehci-fsl.h> +#include <usb/ehci-ci.h>
#include "ehci.h"
diff --git a/drivers/usb/host/ehci-mx5.c b/drivers/usb/host/ehci-mx5.c index d319962..2b36ceb 100644 --- a/drivers/usb/host/ehci-mx5.c +++ b/drivers/usb/host/ehci-mx5.c @@ -9,7 +9,7 @@ #include <usb.h> #include <errno.h> #include <linux/compiler.h> -#include <usb/ehci-fsl.h> +#include <usb/ehci-ci.h> #include <asm/io.h> #include <asm/arch/imx-regs.h> #include <asm/arch/clock.h> diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index e1c67f7..a981b50 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -10,7 +10,7 @@ #include <errno.h> #include <wait_bit.h> #include <linux/compiler.h> -#include <usb/ehci-fsl.h> +#include <usb/ehci-ci.h> #include <asm/io.h> #include <asm/arch/imx-regs.h> #include <asm/arch/clock.h> diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index f09c75a..f8324ee 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -9,7 +9,7 @@ #include <usb.h> #include <asm/io.h> #include <asm/arch/imx-regs.h> -#include <usb/ehci-fsl.h> +#include <usb/ehci-ci.h> #include <errno.h>
#include "ehci.h" diff --git a/drivers/usb/host/ehci-vf.c b/drivers/usb/host/ehci-vf.c index 335e303..61789dd 100644 --- a/drivers/usb/host/ehci-vf.c +++ b/drivers/usb/host/ehci-vf.c @@ -17,7 +17,7 @@ #include <asm/arch/crm_regs.h> #include <asm/imx-common/iomux-v3.h> #include <asm/imx-common/regs-usbphy.h> -#include <usb/ehci-fsl.h> +#include <usb/ehci-ci.h>
#include "ehci.h"
diff --git a/drivers/usb/host/ehci-zynq.c b/drivers/usb/host/ehci-zynq.c index 7770d05..37a7935 100644 --- a/drivers/usb/host/ehci-zynq.c +++ b/drivers/usb/host/ehci-zynq.c @@ -11,7 +11,7 @@ #include <asm/arch/sys_proto.h> #include <asm/io.h> #include <usb.h> -#include <usb/ehci-fsl.h> +#include <usb/ehci-ci.h> #include <usb/ulpi.h>
#include "ehci.h" diff --git a/include/usb/ehci-fsl.h b/include/usb/ehci-ci.h similarity index 99% rename from include/usb/ehci-fsl.h rename to include/usb/ehci-ci.h index e9349b5..725aec5 100644 --- a/include/usb/ehci-fsl.h +++ b/include/usb/ehci-ci.h @@ -6,8 +6,8 @@ * SPDX-License-Identifier: GPL-2.0+ */
-#ifndef _EHCI_FSL_H -#define _EHCI_FSL_H +#ifndef _EHCI_CI_H +#define _EHCI_CI_H
#include <asm/processor.h>
@@ -285,4 +285,4 @@ int usb_phy_mode(int port); int board_ehci_hcd_init(int port); int board_usb_phy_mode(int port);
-#endif /* _EHCI_FSL_H */ +#endif /* _EHCI_CI_H */

On 24 January 2016 at 13:52, Mateusz Kulikowski mateusz.kulikowski@gmail.com wrote:
Most of ehci-fsl header describe USB controller designed by Chipidea and used by various SoC vendors.
This patch renames it to a generic header: ehci-ci.h Contents of file are not changed (so it contains several references to freescale SoCs).
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com Acked-by: Marek Vasut marex@denx.de
Changes in v2:
- Add acked-by
Changes in v1: None
drivers/usb/host/ehci-fsl.c | 2 +- drivers/usb/host/ehci-mpc512x.c | 2 +- drivers/usb/host/ehci-mx5.c | 2 +- drivers/usb/host/ehci-mx6.c | 2 +- drivers/usb/host/ehci-mxc.c | 2 +- drivers/usb/host/ehci-vf.c | 2 +- drivers/usb/host/ehci-zynq.c | 2 +- include/usb/{ehci-fsl.h => ehci-ci.h} | 6 +++--- 8 files changed, 10 insertions(+), 10 deletions(-) rename include/usb/{ehci-fsl.h => ehci-ci.h} (99%)
Tested on Dragonboard 410c Tested-by: Simon Glass sjg@chromium.org

Some registers of usb_ehci were marked as reserved. This may be true for some variants of Chipidea USB core, but they have meaning on other devices.
The following registers were added: sbusstatus/sbusmode: AHB-related registers genconfig*: Auxiluary IP core configuration registers.
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com Reviewed-by: Marek Vasut marex@denx.de
---
Changes in v2: - Add reviewed-by
Changes in v1: None
include/usb/ehci-ci.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/include/usb/ehci-ci.h b/include/usb/ehci-ci.h index 725aec5..305b180 100644 --- a/include/usb/ehci-ci.h +++ b/include/usb/ehci-ci.h @@ -191,7 +191,11 @@ struct usb_ehci { u32 gptimer1_ld; /* 0x088 - General Purpose Timer 1 load value */ u32 gptimer1_ctrl; /* 0x08C - General Purpose Timer 1 control */ u32 sbuscfg; /* 0x090 - System Bus Interface Control */ - u8 res2[0x6C]; + u32 sbusstatus; /* 0x094 - System Bus Interface Status */ + u32 sbusmode; /* 0x098 - System Bus Interface Mode */ + u32 genconfig; /* 0x09C - USB Core Configuration */ + u32 genconfig2; /* 0x0A0 - USB Core Configuration 2 */ + u8 res2[0x5c]; u8 caplength; /* 0x100 - Capability Register Length */ u8 res3[0x1]; u16 hciversion; /* 0x102 - Host Interface Version */

On 24 January 2016 at 13:53, Mateusz Kulikowski mateusz.kulikowski@gmail.com wrote:
Some registers of usb_ehci were marked as reserved. This may be true for some variants of Chipidea USB core, but they have meaning on other devices.
The following registers were added: sbusstatus/sbusmode: AHB-related registers genconfig*: Auxiluary IP core configuration registers.
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com Reviewed-by: Marek Vasut marex@denx.de
Changes in v2:
- Add reviewed-by
Changes in v1: None
include/usb/ehci-ci.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
Tested on Dragonboard 410c Tested-by: Simon Glass sjg@chromium.org

Use definitions from ehci.h instead.
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com Acked-by: Marek Vasut marex@denx.de ---
Changes in v2: - Add Acked-by
Changes in v1: None
drivers/usb/host/ehci-mpc512x.c | 4 ++-- include/usb/ehci-ci.h | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/host/ehci-mpc512x.c b/drivers/usb/host/ehci-mpc512x.c index 4b50ac8..bb4f461 100644 --- a/drivers/usb/host/ehci-mpc512x.c +++ b/drivers/usb/host/ehci-mpc512x.c @@ -93,7 +93,7 @@ static int reset_usb_controller(volatile struct usb_ehci *ehci) unsigned int i;
/* Command a reset of the USB Controller */ - out_be32(&(ehci->usbcmd), EHCI_FSL_USBCMD_RST); + out_be32(&(ehci->usbcmd), CMD_RESET);
/* Wait for the reset process to finish */ for (i = 65535 ; i > 0 ; i--) { @@ -101,7 +101,7 @@ static int reset_usb_controller(volatile struct usb_ehci *ehci) * The host will set this bit to zero once the * reset process is complete */ - if ((in_be32(&(ehci->usbcmd)) & EHCI_FSL_USBCMD_RST) == 0) + if ((in_be32(&(ehci->usbcmd)) & CMD_RESET) == 0) return 0; }
diff --git a/include/usb/ehci-ci.h b/include/usb/ehci-ci.h index 305b180..586d32a 100644 --- a/include/usb/ehci-ci.h +++ b/include/usb/ehci-ci.h @@ -97,10 +97,6 @@ #define INTR_DATA_PULSING_EN (0x1<<30) #define INTSTS_MASK (0x00ff0000)
-/* USBCMD Bits of interest */ -#define EHCI_FSL_USBCMD_RST (1 << 1) -#define EHCI_FSL_USBCMD_RS (1 << 0) - #define INTERRUPT_ENABLE_BITS_MASK \ (INTR_USB_ID_EN | \ INTR_1MS_TIMER_EN | \

On 24 January 2016 at 13:53, Mateusz Kulikowski mateusz.kulikowski@gmail.com wrote:
Use definitions from ehci.h instead.
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com Acked-by: Marek Vasut marex@denx.de
Changes in v2:
- Add Acked-by
Changes in v1: None
drivers/usb/host/ehci-mpc512x.c | 4 ++-- include/usb/ehci-ci.h | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-)
Tested on Dragonboard 410c Tested-by: Simon Glass sjg@chromium.org

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

On 24 January 2016 at 13:53, Mateusz Kulikowski mateusz.kulikowski@gmail.com 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 Acked-by: Marek Vasut marex@denx.de
Changes in v2:
- Use PORT_... macro to write to portsc
- Remove extra whitespace in probe()
- Add acked-by
Changes in v1:
- Reordered header files
- Removed braces around constant
- Added more verbose help to KConfig
- Added ULPI dependency to Kconfig
- Drop register #defines - use ehci-ci.h instead
- Create fixed ulpi viewport for device
- Use setbits/clearbits where possible
- Use wait_for_bit to reset controller
- Add dt binding documents
doc/device-tree-bindings/usb/ehci-msm.txt | 10 ++ drivers/usb/host/Kconfig | 11 ++ drivers/usb/host/Makefile | 1 + drivers/usb/host/ehci-msm.c | 178 ++++++++++++++++++++++++++++++ 4 files changed, 200 insertions(+) create mode 100644 doc/device-tree-bindings/usb/ehci-msm.txt create mode 100644 drivers/usb/host/ehci-msm.c
Tested on Dragonboard 410c Tested-by: Simon Glass sjg@chromium.org

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 Reviewed-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Use proper entry order in Kconfig - Rename CONFIG_DM_SPMI -> CONFIG_SPMI - Fix header ordering - Add reviewed-by
Changes in v1: - Reorder includes - Add read/write arguments documentation
drivers/Kconfig | 2 ++ drivers/Makefile | 1 + drivers/spmi/Kconfig | 10 ++++++++++ drivers/spmi/Makefile | 7 +++++++ drivers/spmi/spmi-uclass.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/spmi/spmi.h | 47 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 116 insertions(+) create mode 100644 drivers/spmi/Kconfig create mode 100644 drivers/spmi/Makefile create mode 100644 drivers/spmi/spmi-uclass.c create mode 100644 include/spmi/spmi.h
diff --git a/drivers/Kconfig b/drivers/Kconfig index 70993fd..c82a94b 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -60,6 +60,8 @@ source "drivers/sound/Kconfig"
source "drivers/spi/Kconfig"
+source "drivers/spmi/Kconfig" + source "drivers/thermal/Kconfig"
source "drivers/timer/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 00da40b..2b2a9cf 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..0b9bd31 --- /dev/null +++ b/drivers/spmi/Kconfig @@ -0,0 +1,10 @@ +menu "SPMI support" + +config 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..99092eb --- /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_SPMI) += spmi-uclass.o diff --git a/drivers/spmi/spmi-uclass.c b/drivers/spmi/spmi-uclass.c new file mode 100644 index 0000000..4ddd51b --- /dev/null +++ b/drivers/spmi/spmi-uclass.c @@ -0,0 +1,48 @@ +/* + * SPMI bus uclass driver + * + * (C) Copyright 2015 Mateusz Kulikowski mateusz.kulikowski@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <dm/root.h> +#include <spmi/spmi.h> +#include <linux/ctype.h> + +DECLARE_GLOBAL_DATA_PTR; + +int spmi_reg_read(struct udevice *dev, int usid, int pid, int reg) +{ + const struct dm_spmi_ops *ops = dev_get_driver_ops(dev); + + if (!ops || !ops->read) + return -ENOSYS; + + return ops->read(dev, usid, pid, reg); +} + +int spmi_reg_write(struct udevice *dev, int usid, int pid, int reg, + uint8_t value) +{ + const struct dm_spmi_ops *ops = dev_get_driver_ops(dev); + + if (!ops || !ops->write) + return -ENOSYS; + + return ops->write(dev, usid, pid, reg, value); +} + +static int spmi_post_bind(struct udevice *dev) +{ + return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); +} + +UCLASS_DRIVER(spmi) = { + .id = UCLASS_SPMI, + .name = "spmi", + .post_bind = spmi_post_bind, +}; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 8391e38..e896c2f 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -61,6 +61,7 @@ enum uclass_id { UCLASS_RTC, /* Real time clock device */ UCLASS_SERIAL, /* Serial UART */ UCLASS_SPI, /* SPI bus */ + UCLASS_SPMI, /* System Power Management Interface bus */ UCLASS_SPI_FLASH, /* SPI flash */ UCLASS_SPI_GENERIC, /* Generic SPI flash target */ UCLASS_SYSCON, /* System configuration device */ diff --git a/include/spmi/spmi.h b/include/spmi/spmi.h new file mode 100644 index 0000000..65a49bd --- /dev/null +++ b/include/spmi/spmi.h @@ -0,0 +1,47 @@ +#ifndef _SPMI_SPMI_H +#define _SPMI_SPMI_H + +/** + * struct dm_spmi_ops - SPMI device I/O interface + * + * Should be implemented by UCLASS_SPMI device drivers. The standard + * device operations provides the I/O interface for it's childs. + * + * @read: read register 'reg' of slave 'usid' and peripheral 'pid' + * @write: write register 'reg' of slave 'usid' and peripheral 'pid' + * + * Each register is 8-bit, both read and write can return negative values + * on error. + */ +struct dm_spmi_ops { + int (*read)(struct udevice *dev, int usid, int pid, int reg); + int (*write)(struct udevice *dev, int usid, int pid, int reg, + uint8_t value); +}; + +/** + * spmi_reg_read() - read a register from specific slave/peripheral + * + * @dev: SPMI bus to read + * @usid SlaveID + * @pid Peripheral ID + * @reg: Register to read + * @return value read on success or negative value of errno. + */ +int spmi_reg_read(struct udevice *dev, int usid, int pid, int reg); + +/** + * spmi_reg_write() - write a register of specific slave/peripheral + * + * @dev: SPMI bus to write + * @usid SlaveID + * @pid Peripheral ID + * @reg: Register to write + * @value: Value to write + * @return 0 on success or negative value of errno. + */ +int spmi_reg_write(struct udevice *dev, int usid, int pid, int reg, + uint8_t value); + +#endif +

On 24 January 2016 at 13:53, 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 Reviewed-by: Simon Glass sjg@chromium.org
Changes in v2:
- Use proper entry order in Kconfig
- Rename CONFIG_DM_SPMI -> CONFIG_SPMI
- Fix header ordering
- Add reviewed-by
Changes in v1:
- Reorder includes
- Add read/write arguments documentation
drivers/Kconfig | 2 ++ drivers/Makefile | 1 + drivers/spmi/Kconfig | 10 ++++++++++ drivers/spmi/Makefile | 7 +++++++ drivers/spmi/spmi-uclass.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/spmi/spmi.h | 47 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 116 insertions(+) create mode 100644 drivers/spmi/Kconfig create mode 100644 drivers/spmi/Makefile create mode 100644 drivers/spmi/spmi-uclass.c create mode 100644 include/spmi/spmi.h
Tested on Dragonboard 410c Tested-by: Simon Glass sjg@chromium.org

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

Hi Mateusz,
On 24 January 2016 at 13:53, Mateusz Kulikowski mateusz.kulikowski@gmail.com wrote:
This patch adds emulated spmi bus controller with part of pm8916 pmic on it to sandbox and tests validating SPMI uclass.
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com Reviewed-by: Simon Glass sjg@chromium.org
Changes in v2:
- Rename CONFIG_DM_SPMI -> CONFIG_SPMI
- Rename r -> regs, p -> priv
- Add reviewed-by
- Update binding doc (drop unused bindig)
Changes in v1: None
arch/sandbox/dts/sandbox.dts | 20 ++++
You should add these changes to test.dts also - try running test/dm/test-dm.sh to see the failures.
configs/sandbox_defconfig | 4 + doc/device-tree-bindings/spmi/spmi-sandbox.txt | 31 +++++ drivers/spmi/Kconfig | 8 ++ drivers/spmi/Makefile | 1 + drivers/spmi/spmi-sandbox.c | 157 +++++++++++++++++++++++++ test/dm/Makefile | 1 + test/dm/spmi.c | 115 ++++++++++++++++++ 8 files changed, 337 insertions(+) create mode 100644 doc/device-tree-bindings/spmi/spmi-sandbox.txt create mode 100644 drivers/spmi/spmi-sandbox.c create mode 100644 test/dm/spmi.c
Regards, Simon

Support SPMI arbiter on Qualcomm Snapdragon devices.
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com Reviewed-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Rename DM_SPMI -> SPMI - Rename p -> priv (in write/read) - Fix header ordering (again) - Add reviewed-by
Changes in v1: - add binding documentation and better Kconfig help - Changed a bit mapping - Change include order - Use clrsetbits* where possible - Add one more supported dts id - Handle missing fields in dt properly
doc/device-tree-bindings/spmi/spmi-msm.txt | 26 ++++ drivers/spmi/Kconfig | 7 +- drivers/spmi/Makefile | 1 + drivers/spmi/spmi-msm.c | 189 +++++++++++++++++++++++++++++ 4 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 doc/device-tree-bindings/spmi/spmi-msm.txt create mode 100644 drivers/spmi/spmi-msm.c
diff --git a/doc/device-tree-bindings/spmi/spmi-msm.txt b/doc/device-tree-bindings/spmi/spmi-msm.txt new file mode 100644 index 0000000..ae47673 --- /dev/null +++ b/doc/device-tree-bindings/spmi/spmi-msm.txt @@ -0,0 +1,26 @@ +Qualcomm SPMI arbiter/bus driver + +This is bus driver for Qualcomm chips that use SPMI to communicate with PMICs. + +Required properties: +- compatible: "qcom,spmi-pmic-arb" +- reg: Register block adresses and sizes for various parts of device: + 1) PMIC arbiter channel mapping base (PMIC_ARB_REG_CHNLn) + 2) SPMI write command (master) registers (PMIC_ARB_CORE_SW_DEC_CHANNELS) + 3) SPMI read command (observer) registers (PMIC_ARB_CORE_REGISTERS_OBS) + +Optional properties (if not set by parent): +- #address-cells: 0x1 - childs slave ID address +- #size-cells: 0x1 + +All PMICs should be placed as a child nodes of bus arbiter. +Automatic detection of childs is currently not supported. + +Example: + +spmi@200f000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x200f800 0x200 0x2400000 0x400000 0x2c00000 0x400000>; + #address-cells = <0x1>; + #size-cells = <0x1>; +}; diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig index c70d675..8d25b45 100644 --- a/drivers/spmi/Kconfig +++ b/drivers/spmi/Kconfig @@ -8,11 +8,16 @@ config SPMI SPMI (System Power Management Interface) bus is used to connect PMIC devices on various SoCs.
+config SPMI_MSM + boolean "Support Qualcomm SPMI bus" + depends on SPMI + ---help--- + Support SPMI bus implementation found on Qualcomm Snapdragon SoCs. + config SPMI_SANDBOX boolean "Support for Sandbox SPMI bus" depends on SPMI ---help--- Demo SPMI bus implementation. Emulates part of PM8916 as single slave (0) on bus. It has 4 GPIO peripherals, pid 0xC0-0xC3. - endmenu diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile index 4ca65a9..c0b1220 100644 --- a/drivers/spmi/Makefile +++ b/drivers/spmi/Makefile @@ -5,4 +5,5 @@ #
obj-$(CONFIG_SPMI) += spmi-uclass.o +obj-$(CONFIG_SPMI_MSM) += spmi-msm.o obj-$(CONFIG_SPMI_SANDBOX) += spmi-sandbox.o diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c new file mode 100644 index 0000000..0cef505 --- /dev/null +++ b/drivers/spmi/spmi-msm.c @@ -0,0 +1,189 @@ +/* + * Qualcomm SPMI bus driver + * + * (C) Copyright 2015 Mateusz Kulikowski mateusz.kulikowski@gmail.com + * + * Loosely based on Little Kernel driver + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <fdtdec.h> +#include <asm/io.h> +#include <spmi/spmi.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define ARB_CHANNEL_OFFSET(n) (0x4 * (n)) +#define SPMI_CH_OFFSET(chnl) ((chnl) * 0x8000) + +#define SPMI_REG_CMD0 0x0 +#define SPMI_REG_CONFIG 0x4 +#define SPMI_REG_STATUS 0x8 +#define SPMI_REG_WDATA 0x10 +#define SPMI_REG_RDATA 0x18 + +#define SPMI_CMD_OPCODE_SHIFT 27 +#define SPMI_CMD_SLAVE_ID_SHIFT 20 +#define SPMI_CMD_ADDR_SHIFT 12 +#define SPMI_CMD_ADDR_OFFSET_SHIFT 4 +#define SPMI_CMD_BYTE_CNT_SHIFT 0 + +#define SPMI_CMD_EXT_REG_WRITE_LONG 0x00 +#define SPMI_CMD_EXT_REG_READ_LONG 0x01 + +#define SPMI_STATUS_DONE 0x1 + +#define SPMI_MAX_CHANNELS 128 +#define SPMI_MAX_SLAVES 16 +#define SPMI_MAX_PERIPH 256 + +struct msm_spmi_priv { + phys_addr_t arb_chnl; /* ARB channel mapping base */ + phys_addr_t spmi_core; /* SPMI core */ + phys_addr_t spmi_obs; /* SPMI observer */ + /* SPMI channel map */ + uint8_t channel_map[SPMI_MAX_SLAVES][SPMI_MAX_PERIPH]; +}; + +static int msm_spmi_write(struct udevice *dev, int usid, int pid, int off, + uint8_t val) +{ + struct msm_spmi_priv *priv = 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 = priv->channel_map[usid][pid]; + + /* Disable IRQ mode for the current channel*/ + writel(0x0, priv->spmi_core + SPMI_CH_OFFSET(channel) + + SPMI_REG_CONFIG); + + /* Write single byte */ + writel(val, priv->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, priv->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_CMD0); + + /* Wait till CMD DONE status */ + reg = 0; + while (!reg) { + reg = readl(priv->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 *priv = 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 = priv->channel_map[usid][pid]; + + /* Disable IRQ mode for the current channel*/ + writel(0x0, priv->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, priv->spmi_obs + SPMI_CH_OFFSET(channel) + SPMI_REG_CMD0); + + /* Wait till CMD DONE status */ + reg = 0; + while (!reg) { + reg = readl(priv->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(priv->spmi_obs + SPMI_CH_OFFSET(channel) + + SPMI_REG_RDATA) & 0xFF; +} + +static struct dm_spmi_ops msm_spmi_ops = { + .read = msm_spmi_read, + .write = msm_spmi_write, +}; + +static int msm_spmi_probe(struct udevice *dev) +{ + struct udevice *parent = dev->parent; + struct msm_spmi_priv *priv = dev_get_priv(dev); + int i; + + priv->arb_chnl = dev_get_addr(dev); + priv->spmi_core = fdtdec_get_addr_size_auto_parent(gd->fdt_blob, + parent->of_offset, + dev->of_offset, + "reg", 1, NULL); + priv->spmi_obs = fdtdec_get_addr_size_auto_parent(gd->fdt_blob, + parent->of_offset, + dev->of_offset, "reg", + 2, NULL); + if (priv->arb_chnl == FDT_ADDR_T_NONE || + priv->spmi_core == FDT_ADDR_T_NONE || + priv->spmi_obs == FDT_ADDR_T_NONE) + return -EINVAL; + + /* Scan peripherals connected to each SPMI channel */ + for (i = 0; i < SPMI_MAX_CHANNELS ; i++) { + uint32_t periph = readl(priv->arb_chnl + ARB_CHANNEL_OFFSET(i)); + uint8_t slave_id = (periph & 0xf0000) >> 16; + uint8_t pid = (periph & 0xff00) >> 8; + + priv->channel_map[slave_id][pid] = i; + } + return 0; +} + +static const struct udevice_id msm_spmi_ids[] = { + { .compatible = "qcom,spmi-pmic-arb" }, + { } +}; + +U_BOOT_DRIVER(msm_spmi) = { + .name = "msm_spmi", + .id = UCLASS_SPMI, + .of_match = msm_spmi_ids, + .ops = &msm_spmi_ops, + .probe = msm_spmi_probe, + .priv_auto_alloc_size = sizeof(struct msm_spmi_priv), +};

On 24 January 2016 at 13:53, Mateusz Kulikowski mateusz.kulikowski@gmail.com wrote:
Support SPMI arbiter on Qualcomm Snapdragon devices.
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com Reviewed-by: Simon Glass sjg@chromium.org
Changes in v2:
- Rename DM_SPMI -> SPMI
- Rename p -> priv (in write/read)
- Fix header ordering (again)
- Add reviewed-by
Changes in v1:
- add binding documentation and better Kconfig help
- Changed a bit mapping
- Change include order
- Use clrsetbits* where possible
- Add one more supported dts id
- Handle missing fields in dt properly
doc/device-tree-bindings/spmi/spmi-msm.txt | 26 ++++ drivers/spmi/Kconfig | 7 +- drivers/spmi/Makefile | 1 + drivers/spmi/spmi-msm.c | 189 +++++++++++++++++++++++++++++ 4 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 doc/device-tree-bindings/spmi/spmi-msm.txt create mode 100644 drivers/spmi/spmi-msm.c
Tested on Dragonboard 410c Tested-by: Simon Glass sjg@chromium.org

This PMIC is connected on SPMI bus so needs SPMI support enabled.
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com Reviewed-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Add reviewed-by - Reordered Kconfig & Makefile (to keep alphabetical ordering) - Added link to dt binding @ help
Changes in v1: - Added dt bindings - Reoder includes - Replaced extract_* macros with ordinary shift/mask - Added error checking and whitespaces in probe
doc/device-tree-bindings/pmic/pm8916.txt | 18 ++++++ drivers/power/pmic/Kconfig | 16 ++++++ drivers/power/pmic/Makefile | 1 + drivers/power/pmic/pm8916.c | 96 ++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 doc/device-tree-bindings/pmic/pm8916.txt create mode 100644 drivers/power/pmic/pm8916.c
diff --git a/doc/device-tree-bindings/pmic/pm8916.txt b/doc/device-tree-bindings/pmic/pm8916.txt new file mode 100644 index 0000000..15c598b --- /dev/null +++ b/doc/device-tree-bindings/pmic/pm8916.txt @@ -0,0 +1,18 @@ +Qualcomm pm8916 PMIC + +This PMIC is connected using SPMI bus so should be child of SPMI bus controller. + +Required properties: +- compatible: "qcom,spmi-pmic"; +- reg: SPMI Slave ID, size (ignored) +- #address-cells: 0x1 (peripheral ID) +- #size-cells: 0x1 (size of peripheral register space) + +Example: + +pm8916@0 { + compatible = "qcom,spmi-pmic"; + reg = <0x0 0x1>; + #address-cells = <0x1>; + #size-cells = <0x1>; +}; diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index 7f69ae1..69f8d51 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -54,6 +54,22 @@ config DM_PMIC_MAX77686 This config enables implementation of driver-model pmic uclass features for PMIC MAX77686. The driver implements read/write operations.
+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 + + Driver binding info: doc/device-tree-bindings/pmic/pm8916.txt + config PMIC_RK808 bool "Enable support for Rockchip PMIC RK808" depends on DM_PMIC diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index c6e8d0c..52b4f71 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_DM_PMIC_PFUZE100) += pfuze100.o obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o obj-$(CONFIG_PMIC_ACT8846) += act8846.o +obj-$(CONFIG_PMIC_PM8916) += pm8916.o obj-$(CONFIG_PMIC_RK808) += rk808.o obj-$(CONFIG_PMIC_TPS65090) += tps65090.o obj-$(CONFIG_PMIC_S5M8767) += s5m8767.o diff --git a/drivers/power/pmic/pm8916.c b/drivers/power/pmic/pm8916.c new file mode 100644 index 0000000..9acf5f5 --- /dev/null +++ b/drivers/power/pmic/pm8916.c @@ -0,0 +1,96 @@ +/* + * Qualcomm pm8916 pmic driver + * + * (C) Copyright 2015 Mateusz Kulikowski mateusz.kulikowski@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <dm.h> +#include <dm/root.h> +#include <power/pmic.h> +#include <spmi/spmi.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define PID_SHIFT 8 +#define PID_MASK (0xFF << PID_SHIFT) +#define REG_MASK 0xFF + +struct pm8916_priv { + uint16_t usid; /* Slave ID on SPMI bus */ +}; + +static int pm8916_reg_count(struct udevice *dev) +{ + return 0xFFFF; +} + +static int pm8916_write(struct udevice *dev, uint reg, const uint8_t *buff, + int len) +{ + struct pm8916_priv *priv = dev_get_priv(dev); + + if (len != 1) + return -EINVAL; + + return spmi_reg_write(dev->parent, priv->usid, + (reg & PID_MASK) >> PID_SHIFT, reg & REG_MASK, + *buff); +} + +static int pm8916_read(struct udevice *dev, uint reg, uint8_t *buff, int len) +{ + struct pm8916_priv *priv = dev_get_priv(dev); + int val; + + if (len != 1) + return -EINVAL; + + val = spmi_reg_read(dev->parent, priv->usid, + (reg & PID_MASK) >> PID_SHIFT, reg & REG_MASK); + + if (val < 0) + return val; + *buff = val; + return 0; +} + +static struct dm_pmic_ops pm8916_ops = { + .reg_count = pm8916_reg_count, + .read = pm8916_read, + .write = pm8916_write, +}; + +static const struct udevice_id pm8916_ids[] = { + { .compatible = "qcom,spmi-pmic" }, + { } +}; + +static int pm8916_probe(struct udevice *dev) +{ + struct pm8916_priv *priv = dev_get_priv(dev); + + priv->usid = dev_get_addr(dev); + + if (priv->usid == FDT_ADDR_T_NONE) + return -EINVAL; + + return 0; +} + + +static int pm8916_bind(struct udevice *dev) +{ + return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); +} + +U_BOOT_DRIVER(pmic_pm8916) = { + .name = "pmic_pm8916", + .id = UCLASS_PMIC, + .of_match = pm8916_ids, + .bind = pm8916_bind, + .probe = pm8916_probe, + .ops = &pm8916_ops, + .priv_auto_alloc_size = sizeof(struct pm8916_priv), +};

On 24 January 2016 at 13:53, 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 Reviewed-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add reviewed-by
- Reordered Kconfig & Makefile (to keep alphabetical ordering)
- Added link to dt binding @ help
Changes in v1:
- Added dt bindings
- Reoder includes
- Replaced extract_* macros with ordinary shift/mask
- Added error checking and whitespaces in probe
doc/device-tree-bindings/pmic/pm8916.txt | 18 ++++++ drivers/power/pmic/Kconfig | 16 ++++++ drivers/power/pmic/Makefile | 1 + drivers/power/pmic/pm8916.c | 96 ++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 doc/device-tree-bindings/pmic/pm8916.txt create mode 100644 drivers/power/pmic/pm8916.c
Tested on Dragonboard 410c Tested-by: Simon Glass sjg@chromium.org
Note there is a 'pmic' command that you ca enable.

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

On 24 January 2016 at 13:53, 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 Reviewed-by: Simon Glass sjg@chromium.org
Changes in v2:
- Add Reviewed-by
Changes in v1:
- Add binding doc
- Fixed inlcude ordering
- Merged direction_input and direction_output functions
- gpio_get: use switch instead of stacked if
- use pmic_clrsetbits
- add possibility to change prwkey bank name
- Handle invalid bindings
- Sanity HW check (i.e. check type/subtype registers)
doc/device-tree-bindings/gpio/pm8916_gpio.txt | 48 ++++ drivers/gpio/Kconfig | 10 + drivers/gpio/Makefile | 1 + drivers/gpio/pm8916_gpio.c | 302 ++++++++++++++++++++++++++ 4 files changed, 361 insertions(+) create mode 100644 doc/device-tree-bindings/gpio/pm8916_gpio.txt create mode 100644 drivers/gpio/pm8916_gpio.c
Tested on Dragonboard 410c Tested-by: Simon Glass sjg@chromium.org
(well, I tested the vol- button)

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 Reviewed-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Rename DM_SPMI -> SPMI - Make MND divider comments more compact :) - p -> priv - Add reviewed-by - Reordered Kconfig to keep alphabetical order - Renamed reset_sandbox -> msm_reset (typo in reset.c)
Changes in v1: - Fix include order - Cleanup defines (added spaces for readibility) - Base address is integer to avoid casting - Use setbits_* family where possible - Drop unneded comments, added newlines where needed - Check return value of dev_get_addr - Add binding for apq8016 - Cleaned up divider calculation - Drop most of gpio.h (only empty file is needed)
arch/arm/Kconfig | 12 + arch/arm/Makefile | 1 + arch/arm/mach-snapdragon/Kconfig | 6 + arch/arm/mach-snapdragon/Makefile | 8 + arch/arm/mach-snapdragon/clock-apq8016.c | 262 +++++++++++++++++++++ arch/arm/mach-snapdragon/include/mach/gpio.h | 9 + .../mach-snapdragon/include/mach/sysmap-apq8016.h | 14 ++ arch/arm/mach-snapdragon/reset.c | 40 ++++ 8 files changed, 352 insertions(+) create mode 100644 arch/arm/mach-snapdragon/Kconfig create mode 100644 arch/arm/mach-snapdragon/Makefile create mode 100644 arch/arm/mach-snapdragon/clock-apq8016.c create mode 100644 arch/arm/mach-snapdragon/include/mach/gpio.h create mode 100644 arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h create mode 100644 arch/arm/mach-snapdragon/reset.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 876a620..d0a22ac 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -504,6 +504,16 @@ config RMOBILE bool "Renesas ARM SoCs" select CPU_V7
+config ARCH_SNAPDRAGON + bool "Qualcomm Snapdragon SoCs" + select ARM64 + select DM + select DM_GPIO + select DM_SERIAL + select SPMI + select OF_CONTROL + select OF_SEPARATE + config ARCH_SOCFPGA bool "Altera SOCFPGA family" select CPU_V7 @@ -760,6 +770,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-stm32/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index cd7d880..661de56 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -54,6 +54,7 @@ machine-$(CONFIG_ARCH_MVEBU) += 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_STM32) += stm32 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..d548d75 --- /dev/null +++ b/arch/arm/mach-snapdragon/clock-apq8016.c @@ -0,0 +1,262 @@ +/* + * Clock drivers for Qualcomm APQ8016 + * + * (C) Copyright 2015 Mateusz Kulikowski mateusz.kulikowski@gmail.com + * + * Based on Little Kernel driver, simplified + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <errno.h> +#include <asm/io.h> +#include <linux/bitops.h> + +/* GPLL0 clock control registers */ +#define GPLL0_STATUS 0x2101C +#define GPLL0_STATUS_ACTIVE BIT(17) + +#define APCS_GPLL_ENA_VOTE 0x45000 +#define APCS_GPLL_ENA_VOTE_GPLL0 BIT(0) + +/* vote reg for blsp1 clock */ +#define APCS_CLOCK_BRANCH_ENA_VOTE 0x45004 +#define APCS_CLOCK_BRANCH_ENA_VOTE_BLSP1 BIT(10) + +/* SDC(n) clock control registers; n=1,2 */ + +/* block control register */ +#define SDCC_BCR(n) ((n * 0x1000) + 0x41000) +/* cmd */ +#define SDCC_CMD_RCGR(n) ((n * 0x1000) + 0x41004) +/* cfg */ +#define SDCC_CFG_RCGR(n) ((n * 0x1000) + 0x41008) +/* m */ +#define SDCC_M(n) ((n * 0x1000) + 0x4100C) +/* n */ +#define SDCC_N(n) ((n * 0x1000) + 0x41010) +/* d */ +#define SDCC_D(n) ((n * 0x1000) + 0x41014) +/* branch control */ +#define SDCC_APPS_CBCR(n) ((n * 0x1000) + 0x41018) +#define SDCC_AHB_CBCR(n) ((n * 0x1000) + 0x4101C) + +/* BLSP1 AHB clock (root clock for BLSP) */ +#define BLSP1_AHB_CBCR 0x1008 + +/* Uart clock control registers */ +#define BLSP1_UART2_BCR 0x3028 +#define BLSP1_UART2_APPS_CBCR 0x302C +#define BLSP1_UART2_APPS_CMD_RCGR 0x3034 +#define BLSP1_UART2_APPS_CFG_RCGR 0x3038 +#define BLSP1_UART2_APPS_M 0x303C +#define BLSP1_UART2_APPS_N 0x3040 +#define BLSP1_UART2_APPS_D 0x3044 + +/* CBCR register fields */ +#define CBCR_BRANCH_ENABLE_BIT BIT(0) +#define CBCR_BRANCH_OFF_BIT BIT(31) + +struct msm_clk_priv { + phys_addr_t base; +}; + +/* Enable clock controlled by CBC soft macro */ +static void clk_enable_cbc(phys_addr_t cbcr) +{ + setbits_le32(cbcr, CBCR_BRANCH_ENABLE_BIT); + + while (readl(cbcr) & CBCR_BRANCH_OFF_BIT) + ; +} + +/* clock has 800MHz */ +static void clk_enable_gpll0(phys_addr_t base) +{ + if (readl(base + GPLL0_STATUS) & GPLL0_STATUS_ACTIVE) + return; /* clock already enabled */ + + setbits_le32(base + APCS_GPLL_ENA_VOTE, APCS_GPLL_ENA_VOTE_GPLL0); + + while ((readl(base + GPLL0_STATUS) & GPLL0_STATUS_ACTIVE) == 0) + ; +} + +#define APPS_CMD_RGCR_UPDATE BIT(0) + +/* Update clock command via CMD_RGCR */ +static void clk_bcr_update(phys_addr_t apps_cmd_rgcr) +{ + setbits_le32(apps_cmd_rgcr, APPS_CMD_RGCR_UPDATE); + + /* Wait for frequency to be updated. */ + while (readl(apps_cmd_rgcr) & APPS_CMD_RGCR_UPDATE) + ; +} + +struct bcr_regs { + uintptr_t cfg_rcgr; + uintptr_t cmd_rcgr; + uintptr_t M; + uintptr_t N; + uintptr_t D; +}; + +/* RCGR_CFG register fields */ +#define CFG_MODE_DUAL_EDGE (0x2 << 12) /* Counter mode */ + +/* sources */ +#define CFG_CLK_SRC_CXO (0 << 8) +#define CFG_CLK_SRC_GPLL0 (1 << 8) +#define CFG_CLK_SRC_MASK (7 << 8) + +/* Mask for supported fields */ +#define CFG_MASK 0x3FFF + +#define CFG_DIVIDER_MASK 0x1F + +/* root set rate for clocks with half integer and MND divider */ +static void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs, + int div, int m, int n, int source) +{ + uint32_t cfg; + /* M value for MND divider. */ + uint32_t m_val = m; + /* NOT(N-M) value for MND divider. */ + uint32_t n_val = ~((n)-(m)) * !!(n); + /* NOT 2D value for MND divider. */ + uint32_t d_val = ~(n); + + /* Program MND values */ + writel(m_val, base + regs->M); + writel(n_val, base + regs->N); + writel(d_val, base + regs->D); + + /* setup src select and divider */ + cfg = readl(base + regs->cfg_rcgr); + cfg &= ~CFG_MASK; + cfg |= source & CFG_CLK_SRC_MASK; /* Select clock source */ + + /* Set the divider; HW permits fraction dividers (+0.5), but + for simplicity, we will support integers only */ + if (div) + cfg |= (2 * div - 1) & CFG_DIVIDER_MASK; + + if (n_val) + cfg |= CFG_MODE_DUAL_EDGE; + + writel(cfg, base + regs->cfg_rcgr); /* Write new clock configuration */ + + /* Inform h/w to start using the new config. */ + clk_bcr_update(base + regs->cmd_rcgr); +} + +static const struct bcr_regs sdc_regs[] = { + { + .cfg_rcgr = SDCC_CFG_RCGR(1), + .cmd_rcgr = SDCC_CMD_RCGR(1), + .M = SDCC_M(1), + .N = SDCC_N(1), + .D = SDCC_D(1), + }, + { + .cfg_rcgr = SDCC_CFG_RCGR(2), + .cmd_rcgr = SDCC_CMD_RCGR(2), + .M = SDCC_M(2), + .N = SDCC_N(2), + .D = SDCC_D(2), + } +}; + +/* Init clock for SDHCI controller */ +static int clk_init_sdc(struct msm_clk_priv *priv, int slot, uint rate) +{ + int div = 8; /* 100MHz default */ + + if (rate == 200000000) + div = 4; + + clk_enable_cbc(priv->base + SDCC_AHB_CBCR(slot)); + /* 800Mhz/div, gpll0 */ + clk_rcg_set_rate_mnd(priv->base, &sdc_regs[slot], div, 0, 0, + CFG_CLK_SRC_GPLL0); + clk_enable_gpll0(priv->base); + clk_enable_cbc(priv->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 *priv) +{ + /* Enable iface clk */ + clk_enable_cbc(priv->base + BLSP1_AHB_CBCR); + /* 7372800 uart block clock @ GPLL0 */ + clk_rcg_set_rate_mnd(priv->base, &uart2_regs, 1, 144, 15625, + CFG_CLK_SRC_GPLL0); + clk_enable_gpll0(priv->base); + /* Enable core clk */ + clk_enable_cbc(priv->base + BLSP1_UART2_APPS_CBCR); + + return 0; +} + +ulong msm_set_periph_rate(struct udevice *dev, int periph, ulong rate) +{ + struct msm_clk_priv *priv = dev_get_priv(dev); + + switch (periph) { + case 0: /* SDC1 */ + return clk_init_sdc(priv, 0, rate); + break; + case 1: /* SDC2 */ + return clk_init_sdc(priv, 1, rate); + break; + case 4: /* UART2 */ + return clk_init_uart(priv); + break; + default: + return 0; + } +} + +static int msm_clk_probe(struct udevice *dev) +{ + struct msm_clk_priv *priv = dev_get_priv(dev); + + priv->base = dev_get_addr(dev); + if (priv->base == FDT_ADDR_T_NONE) + return -EINVAL; + + return 0; +} + +static struct clk_ops msm_clk_ops = { + .set_periph_rate = msm_set_periph_rate, +}; + +static const struct udevice_id msm_clk_ids[] = { + { .compatible = "qcom,gcc-msm8916" }, + { .compatible = "qcom,gcc-apq8016" }, + { } +}; + +U_BOOT_DRIVER(clk_msm) = { + .name = "clk_msm", + .id = UCLASS_CLK, + .of_match = msm_clk_ids, + .ops = &msm_clk_ops, + .priv_auto_alloc_size = sizeof(struct msm_clk_priv), + .probe = msm_clk_probe, +}; diff --git a/arch/arm/mach-snapdragon/include/mach/gpio.h b/arch/arm/mach-snapdragon/include/mach/gpio.h new file mode 100644 index 0000000..ff949b2 --- /dev/null +++ b/arch/arm/mach-snapdragon/include/mach/gpio.h @@ -0,0 +1,9 @@ +/* + * Empty gpio.h + * + * This file must stay as arch/arm/include/asm/gpio.h requires it. + * + * (C) Copyright 2015 Mateusz Kulikowski mateusz.kulikowski@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ diff --git a/arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h b/arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h new file mode 100644 index 0000000..cdbfad0 --- /dev/null +++ b/arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h @@ -0,0 +1,14 @@ +/* + * Qualcomm APQ8916 sysmap + * + * (C) Copyright 2015 Mateusz Kulikowski mateusz.kulikowski@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef _MACH_SYSMAP_APQ8016_H +#define _MACH_SYSMAP_APQ8016_H + +#define GICD_BASE 0x0b000000 +#define GICC_BASE 0x0a20c000 + +#endif diff --git a/arch/arm/mach-snapdragon/reset.c b/arch/arm/mach-snapdragon/reset.c new file mode 100644 index 0000000..2627eec --- /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(msm_reset) = { + .name = "msm_reset", + .id = UCLASS_RESET, + .of_match = msm_reset_ids, + .ops = &msm_reset_ops, +};

On 24 January 2016 at 13:53, 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 Reviewed-by: Simon Glass sjg@chromium.org
Changes in v2:
- Rename DM_SPMI -> SPMI
- Make MND divider comments more compact :)
- p -> priv
- Add reviewed-by
- Reordered Kconfig to keep alphabetical order
- Renamed reset_sandbox -> msm_reset (typo in reset.c)
Changes in v1:
- Fix include order
- Cleanup defines (added spaces for readibility)
- Base address is integer to avoid casting
- Use setbits_* family where possible
- Drop unneded comments, added newlines where needed
- Check return value of dev_get_addr
- Add binding for apq8016
- Cleaned up divider calculation
- Drop most of gpio.h (only empty file is needed)
arch/arm/Kconfig | 12 + arch/arm/Makefile | 1 + arch/arm/mach-snapdragon/Kconfig | 6 + arch/arm/mach-snapdragon/Makefile | 8 + arch/arm/mach-snapdragon/clock-apq8016.c | 262 +++++++++++++++++++++ arch/arm/mach-snapdragon/include/mach/gpio.h | 9 + .../mach-snapdragon/include/mach/sysmap-apq8016.h | 14 ++ arch/arm/mach-snapdragon/reset.c | 40 ++++ 8 files changed, 352 insertions(+) create mode 100644 arch/arm/mach-snapdragon/Kconfig create mode 100644 arch/arm/mach-snapdragon/Makefile create mode 100644 arch/arm/mach-snapdragon/clock-apq8016.c create mode 100644 arch/arm/mach-snapdragon/include/mach/gpio.h create mode 100644 arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h create mode 100644 arch/arm/mach-snapdragon/reset.c
Tested on Dragonboard 410c Tested-by: Simon Glass sjg@chromium.org

This commit add support for 96Boards Dragonboard410C. It is board based on APQ8016 Qualcomm SoC, complying with 96boards specification. Features (present out of the box): - 4x Cortex A53 (ARMv8) - 2x USB Host port - 1x USB Device port - 4x LEDs - 1x HDMI connector - 1x uSD connector - 3x buttons (Power, Vol+, Vol-/Reset) - WIFI, Bluetooth with integrated antenna - 8GiB eMMC
U-Boot boots chained with fastboot in 64-bit mode. For detailed build instructions see readme.txt in board directory.
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com ---
Changes in v2: - Renamed CONFIG_DM_SPMI -> CONFIG_SPMI - Removed extra enter in dragonboard file - Added ULPI* to defconfig - Added MAINTAINERS to board - Cleaned up config file - use distro defaults/environment: - Dropped multiple CONFIG_CMD* and other CONFIG_* - Added distro env/config - Dropped old boot commands - Split dts - pm8916_gpio entries are taken directly from Linux Dragonboard dts; Add handles for u-boot in -uboot.dtsi; They will be removed once gpio drivers are converted to pinctrl. - Renamed some pmic nodes, fixed dragonboard.c to find them properly. - Added header and converted comments to c98-style in head.S - Print error if pmic gpio node is not found.
Changes in v1: - Add better help for dragonboard - Move static structures to board_prepare_usb - Add DM_SPMI to defconfig
arch/arm/dts/Makefile | 2 + arch/arm/dts/dragonboard410c-uboot.dtsi | 28 +++++ arch/arm/dts/dragonboard410c.dts | 148 ++++++++++++++++++++++ arch/arm/mach-snapdragon/Kconfig | 20 +++ board/qualcomm/dragonboard410c/Kconfig | 15 +++ board/qualcomm/dragonboard410c/MAINTAINERS | 6 + board/qualcomm/dragonboard410c/Makefile | 8 ++ board/qualcomm/dragonboard410c/dragonboard410c.c | 131 +++++++++++++++++++ board/qualcomm/dragonboard410c/head.S | 28 +++++ board/qualcomm/dragonboard410c/readme.txt | 40 ++++++ board/qualcomm/dragonboard410c/u-boot.lds | 90 +++++++++++++ configs/dragonboard410c_defconfig | 31 +++++ include/configs/dragonboard410c.h | 153 +++++++++++++++++++++++ 13 files changed, 700 insertions(+) create mode 100644 arch/arm/dts/dragonboard410c-uboot.dtsi create mode 100644 arch/arm/dts/dragonboard410c.dts create mode 100644 board/qualcomm/dragonboard410c/Kconfig create mode 100644 board/qualcomm/dragonboard410c/MAINTAINERS 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 641510c..2e48a11 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -100,6 +100,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-uboot.dtsi b/arch/arm/dts/dragonboard410c-uboot.dtsi new file mode 100644 index 0000000..cc2c175 --- /dev/null +++ b/arch/arm/dts/dragonboard410c-uboot.dtsi @@ -0,0 +1,28 @@ +/* + * U-Boot addition to handle Dragonboard 410c pins + * + * (C) Copyright 2015 Mateusz Kulikowski mateusz.kulikowski@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +&pm8916_gpios { + usb_hub_reset_pm { + gpios = <&pm8916_gpios 2 0>; + }; + + usb_sw_sel_pm { + gpios = <&pm8916_gpios 3 0>; + }; +}; + + +&pm8916_pon { + key_vol_down { + gpios = <&pm8916_pon 1 0>; + }; + + key_power { + gpios = <&pm8916_pon 0 0>; + }; +}; diff --git a/arch/arm/dts/dragonboard410c.dts b/arch/arm/dts/dragonboard410c.dts new file mode 100644 index 0000000..7746622 --- /dev/null +++ b/arch/arm/dts/dragonboard410c.dts @@ -0,0 +1,148 @@ +/* + * Qualcomm APQ8016 based Dragonboard 410C board device tree source + * + * (C) Copyright 2015 Mateusz Kulikowski mateusz.kulikowski@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/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@78b0000"; + }; + + + soc { + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges = <0x0 0x0 0x0 0xffffffff>; + compatible = "simple-bus"; + + clkc: qcom,gcc@1800000 { + compatible = "qcom,gcc-apq8016"; + reg = <0x1800000 0x80000>; + #address-cells = <0x1>; + #size-cells = <0x0>; + }; + + serial@78b0000 { + compatible = "qcom,msm-uartdm-v1.4"; + reg = <0x78b0000 0x200>; + u-boot,dm-pre-reloc; + clock = <&clkc 4>; + }; + + restart@4ab000 { + compatible = "qcom,pshold"; + reg = <0x4ab000 0x4>; + }; + + soc_gpios: pinctrl@1000000 { + compatible = "qcom,apq8016-pinctrl"; + reg = <0x1000000 0x300000>; + gpio-controller; + gpio-count = <122>; + gpio-bank-name="soc"; + #gpio-cells = <1>; + }; + + ehci@78d9000 { + compatible = "qcom,ehci-host"; + reg = <0x78d9000 0x400>; + }; + + sdhci@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@07864000 { + compatible = "qcom,sdhci-msm-v4"; + reg = <0x7864900 0x11c 0x7864000 0x800>; + index = <0x1>; + bus-width = <0x4>; + clock = <&clkc 1>; + clock-frequency = <200000000>; + }; + + spmi@200f000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x200f800 0x200 0x2400000 0x400000 0x2c00000 0x400000>; + #address-cells = <0x1>; + #size-cells = <0x1>; + pmic0: pm8916@0 { + compatible = "qcom,spmi-pmic"; + reg = <0x0 0x1>; + #address-cells = <0x1>; + #size-cells = <0x1>; + + pm8916_pon: pm8916_pon@800 { + compatible = "qcom,pm8916-pwrkey"; + reg = <0x800 0x96>; + #gpio-cells = <2>; + gpio-controller; + }; + + pm8916_gpios: pm8916_gpios@c000 { + compatible = "qcom,pm8916-gpio"; + reg = <0xc000 0x400>; + gpio-controller; + gpio-count = <4>; + #gpio-cells = <2>; + gpio-bank-name="pmic"; + }; + }; + + pmic1: pm8916@1 { + compatible = "qcom,spmi-pmic"; + reg = <0x1 0x1>; + }; + }; + }; + + leds { + compatible = "gpio-leds"; + user1 { + label = "green:user1"; + gpios = <&soc_gpios 21 0>; + }; + + user2 { + label = "green:user2"; + gpios = <&soc_gpios 120 0>; + }; + + user3 { + label = "green:user3"; + gpios = <&pm8916_gpios 0 0>; + }; + + user4 { + label = "green:user4"; + gpios = <&pm8916_gpios 1 0>; + }; + }; +}; + +#include "dragonboard410c-uboot.dtsi" diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig index 156e733..dc7ba21 100644 --- a/arch/arm/mach-snapdragon/Kconfig +++ b/arch/arm/mach-snapdragon/Kconfig @@ -3,4 +3,24 @@ if ARCH_SNAPDRAGON config SYS_SOC default "snapdragon"
+choice + prompt "Snapdragon board select" + +config TARGET_DRAGONBOARD410C + bool "96Boards Dragonboard 410C" + help + Support for 96Boards Dragonboard 410C. This board complies with + 96Board Open Platform Specifications. Features: + - Qualcomm Snapdragon 410C SoC - APQ8016 (4xCortex A53, Adreno 306) + - 1GiB RAM + - 8GiB eMMC, uSD slot + - WiFi, Bluetooth and GPS module + - 2x Host, 1x Device USB port + - HDMI + - 20-pin low speed and 40-pin high speed expanders, 4 LED, 3 buttons + +endchoice + +source "board/qualcomm/dragonboard410c/Kconfig" + endif diff --git a/board/qualcomm/dragonboard410c/Kconfig b/board/qualcomm/dragonboard410c/Kconfig new file mode 100644 index 0000000..03bd7ae --- /dev/null +++ b/board/qualcomm/dragonboard410c/Kconfig @@ -0,0 +1,15 @@ +if TARGET_DRAGONBOARD410C + +config SYS_BOARD + default "dragonboard410c" + +config SYS_VENDOR + default "qualcomm" + +config SYS_SOC + default "apq8016" + +config SYS_CONFIG_NAME + default "dragonboard410c" + +endif diff --git a/board/qualcomm/dragonboard410c/MAINTAINERS b/board/qualcomm/dragonboard410c/MAINTAINERS new file mode 100644 index 0000000..65cb47c --- /dev/null +++ b/board/qualcomm/dragonboard410c/MAINTAINERS @@ -0,0 +1,6 @@ +DRAGONBOARD410C BOARD +M: Mateusz Kulikowski mateusz.kulikowski@gmail.com +S: Maintained +F: board/qualcomm/dragonboard410c/ +F: include/configs/dragonboard410c.h +F: configs/dragonboard410c_defconfig 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..1fa5664 --- /dev/null +++ b/board/qualcomm/dragonboard410c/dragonboard410c.c @@ -0,0 +1,131 @@ +/* + * Board init file for Dragonboard 410C + * + * (C) Copyright 2015 Mateusz Kulikowski mateusz.kulikowski@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <usb.h> +#include <asm/gpio.h> + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init(void) +{ + gd->ram_size = PHYS_SDRAM_1_SIZE; + return 0; +} + +void dram_init_banksize(void) +{ + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; +} + + +int board_prepare_usb(enum usb_init_type type) +{ + static struct udevice *pmic_gpio; + static struct gpio_desc hub_reset, usb_sel; + int ret = 0, node; + + if (!pmic_gpio) { + ret = uclass_get_device_by_name(UCLASS_GPIO, + "pm8916_gpios@c000", + &pmic_gpio); + if (ret < 0) { + printf("Failed to find pm8916_gpios@c000 node.\n"); + return ret; + } + } + + /* 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, pmic_gpio->of_offset, + "usb_hub_reset_pm"); + if (node < 0) { + printf("Failed to find usb_hub_reset_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_pm gpio.\n"); + return ret; + } + } + + if (!dm_gpio_is_valid(&usb_sel)) { + node = fdt_subnode_offset(gd->fdt_blob, pmic_gpio->of_offset, + "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) +{ + struct udevice *pon; + struct gpio_desc resin; + int node, ret; + + ret = uclass_get_device_by_name(UCLASS_GPIO, "pm8916_pon@800", &pon); + if (ret < 0) { + printf("Failed to find PMIC pon node. Check device tree\n"); + return 0; + } + + node = fdt_subnode_offset(gd->fdt_blob, pon->of_offset, "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..9f1e0d9 --- /dev/null +++ b/board/qualcomm/dragonboard410c/head.S @@ -0,0 +1,28 @@ +/* + * Little-Kernel/Fastboot header for proper chain-loading + * + * (C) Copyright 2015 Mateusz Kulikowski mateusz.kulikowski@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#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..84fe597 --- /dev/null +++ b/configs/dragonboard410c_defconfig @@ -0,0 +1,31 @@ +CONFIG_ARM=y +CONFIG_ARM64=y +CONFIG_ARCH_SNAPDRAGON=y +CONFIG_TARGET_DRAGONBOARD410C=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=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_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y +CONFIG_USB_STORAGE=y diff --git a/include/configs/dragonboard410c.h b/include/configs/dragonboard410c.h new file mode 100644 index 0000000..1dfb171 --- /dev/null +++ b/include/configs/dragonboard410c.h @@ -0,0 +1,153 @@ +/* + * Board configuration file for Dragonboard 410C + * + * (C) Copyright 2015 Mateusz Kulikowski mateusz.kulikowski@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIGS_DRAGONBOARD410C_H +#define __CONFIGS_DRAGONBOARD410C_H + +#include <linux/sizes.h> +#include <asm/arch/sysmap-apq8016.h> + +#define CONFIG_IDENT_STRING "\nQualcomm-DragonBoard 410C" + +#define CONFIG_MISC_INIT_R /* To stop autoboot */ + +/* Flat Device Tree Definitions */ +#define CONFIG_OF_LIBFDT + +/* Physical Memory Map */ +#define CONFIG_NR_DRAM_BANKS 1 +#define PHYS_SDRAM_1 0x80000000 +/* 1008 MB (the last ~30Mb are secured for TrustZone by ATF*/ +#define PHYS_SDRAM_1_SIZE 0x3da00000 +#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 +#define CONFIG_SYS_TEXT_BASE 0x80080000 +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x7fff0) +#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE + 0x80000) +#define CONFIG_SYS_BOOTM_LEN 0x1000000 /* 16MB max kernel size */ + +/* UART */ +#define CONFIG_BAUDRATE 115200 + +/* Generic Timer Definitions */ +#define COUNTER_FREQUENCY 19000000 + +/* This are needed to have proper mmc support */ +#define CONFIG_MMC +#define CONFIG_GENERIC_MMC +#define CONFIG_SDHCI + +#define CONFIG_SYS_LDSCRIPT "board/qualcomm/dragonboard410c/u-boot.lds" + +/* Fixup - in init code we switch from device to host mode, + * it has to be done after each HCD reset */ +#define CONFIG_EHCI_HCD_INIT_AFTER_RESET + +#define CONFIG_USB_HOST_ETHER /* Enable USB Networking */ + +/* Support all possible USB ethernet dongles */ +#define CONFIG_USB_ETHER_DM9601 +#define CONFIG_USB_ETHER_ASIX +#define CONFIG_USB_ETHER_ASIX88179 +#define CONFIG_USB_ETHER_MCS7830 +#define CONFIG_USB_ETHER_SMSC95XX + +/* Libraries */ +#define CONFIG_MD5 + +/* Extra Commands */ +#define CONFIG_CMD_CACHE +#define CONFIG_CMD_ENV +#define CONFIG_CMD_GPIO +#define CONFIG_CMD_GPT +#define CONFIG_CMD_MD5SUM +#define CONFIG_CMD_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_REGINFO /* Register dump */ +#define CONFIG_CMD_TFTP +#define CONFIG_CMD_TIMER +#define CONFIG_CMD_UNZIP + +/* Partition table support */ +#define HAVE_BLOCK_DEVICE /* Needed for partition commands */ +#define CONFIG_PARTITION_UUIDS + +#include <config_distro_defaults.h> + +/* BOOTP options */ +#define CONFIG_BOOTP_BOOTFILESIZE + +/* Environment - Boot*/ +#define CONFIG_BOOTARGS "console=ttyMSM0,115200n8" + +#define BOOT_TARGET_DEVICES(func) \ + func(USB, usb, 0) \ + func(MMC, mmc, 0) \ + func(MMC, mmc, 1) \ + func(DHCP, dhcp, na) + +#include <config_distro_bootcmd.h> + +/* 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" + +/* Environment */ +#define CONFIG_EXTRA_ENV_SETTINGS \ + "reflash="CONFIG_ENV_REFLASH"\0"\ + "loadaddr=0x81000000\0" \ + "fdt_high=0xffffffffffffffff\0" \ + "initrd_high=0xffffffffffffffff\0" \ + "linux_image=Image\0" \ + "linux_addr=0x81000000\0"\ + "fdt_image=apq8016-sbc.dtb\0" \ + "fdt_addr=0x83000000\0"\ + "ramdisk_addr=0x84000000\0"\ + BOOTENV + +#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_MAXARGS 64 /* max command args */ + +#endif

On 24 January 2016 at 13:53, Mateusz Kulikowski mateusz.kulikowski@gmail.com wrote:
This commit add support for 96Boards Dragonboard410C. It is board based on APQ8016 Qualcomm SoC, complying with 96boards specification. Features (present out of the box):
- 4x Cortex A53 (ARMv8)
- 2x USB Host port
- 1x USB Device port
- 4x LEDs
- 1x HDMI connector
- 1x uSD connector
- 3x buttons (Power, Vol+, Vol-/Reset)
- WIFI, Bluetooth with integrated antenna
- 8GiB eMMC
U-Boot boots chained with fastboot in 64-bit mode. For detailed build instructions see readme.txt in board directory.
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com
Changes in v2:
- Renamed CONFIG_DM_SPMI -> CONFIG_SPMI
- Removed extra enter in dragonboard file
- Added ULPI* to defconfig
- Added MAINTAINERS to board
- Cleaned up config file - use distro defaults/environment:
- Dropped multiple CONFIG_CMD* and other CONFIG_*
- Added distro env/config
- Dropped old boot commands
- Split dts - pm8916_gpio entries are taken directly from Linux Dragonboard dts; Add handles for u-boot in -uboot.dtsi; They will be removed once gpio drivers are converted to pinctrl.
- Renamed some pmic nodes, fixed dragonboard.c to find them properly.
- Added header and converted comments to c98-style in head.S
- Print error if pmic gpio node is not found.
Changes in v1:
- Add better help for dragonboard
- Move static structures to board_prepare_usb
- Add DM_SPMI to defconfig
arch/arm/dts/Makefile | 2 + arch/arm/dts/dragonboard410c-uboot.dtsi | 28 +++++ arch/arm/dts/dragonboard410c.dts | 148 ++++++++++++++++++++++ arch/arm/mach-snapdragon/Kconfig | 20 +++ board/qualcomm/dragonboard410c/Kconfig | 15 +++ board/qualcomm/dragonboard410c/MAINTAINERS | 6 + board/qualcomm/dragonboard410c/Makefile | 8 ++ board/qualcomm/dragonboard410c/dragonboard410c.c | 131 +++++++++++++++++++ board/qualcomm/dragonboard410c/head.S | 28 +++++ board/qualcomm/dragonboard410c/readme.txt | 40 ++++++ board/qualcomm/dragonboard410c/u-boot.lds | 90 +++++++++++++ configs/dragonboard410c_defconfig | 31 +++++ include/configs/dragonboard410c.h | 153 +++++++++++++++++++++++ 13 files changed, 700 insertions(+) create mode 100644 arch/arm/dts/dragonboard410c-uboot.dtsi create mode 100644 arch/arm/dts/dragonboard410c.dts create mode 100644 board/qualcomm/dragonboard410c/Kconfig create mode 100644 board/qualcomm/dragonboard410c/MAINTAINERS 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
Tested on Dragonboard 410c Tested-by: Simon Glass sjg@chromium.org
For the readme, can you please do a patch to add a few more things?
- How to enter fastboot mode - How pressing power on reset works - it didn't do anything for me

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256
Hi,
On 31.01.2016 16:17, Simon Glass wrote:
On 24 January 2016 at 13:53, Mateusz Kulikowski mateusz.kulikowski@gmail.com wrote:
[...]
For the readme, can you please do a patch to add a few more things?
- How to enter fastboot mode
I've added it (sorry, it was kind-of obvious for me :) ).
- How pressing power on reset works - it didn't do anything for me
For now it's not very helpful as by pressing vol- you end up in fastboot first.
But, if you then use fastboot to load u-boot it will stop autoboot command (In case you don't have serial port).
========================= U-Boot 2016.03-rc1-00047-gffd9b24 (Feb 07 2016 - 22:03:00 +0100) Qualcomm-DragonBoard 410C
DRAM: 986 MiB MMC: sdhci@07824000: 0, sdhci@07864000: 1 Using default environment
In: serial@78b0000 Out: serial@78b0000 Err: serial@78b0000 Power button pressed - dropping to console. Net: Net Initialization Skipped No ethernet found. dragonboard410c => ========================
Once I enable UDC controller it will launch fastboot/dfu mode. This will be especially useful when U-Boot will replace little-kernel (that's my goal eventually).
Regards, Mateusz

On 25 January 2016 at 02:23, Mateusz Kulikowski mateusz.kulikowski@gmail.com wrote:
This commit add support for 96Boards Dragonboard410C. It is board based on APQ8016 Qualcomm SoC, complying with 96boards specification. Features (present out of the box):
- 4x Cortex A53 (ARMv8)
- 2x USB Host port
- 1x USB Device port
- 4x LEDs
- 1x HDMI connector
- 1x uSD connector
- 3x buttons (Power, Vol+, Vol-/Reset)
- WIFI, Bluetooth with integrated antenna
- 8GiB eMMC
U-Boot boots chained with fastboot in 64-bit mode. For detailed build instructions see readme.txt in board directory.
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com
Changes in v2:
- Renamed CONFIG_DM_SPMI -> CONFIG_SPMI
- Removed extra enter in dragonboard file
- Added ULPI* to defconfig
- Added MAINTAINERS to board
- Cleaned up config file - use distro defaults/environment:
- Dropped multiple CONFIG_CMD* and other CONFIG_*
- Added distro env/config
- Dropped old boot commands
- Split dts - pm8916_gpio entries are taken directly from Linux Dragonboard dts; Add handles for u-boot in -uboot.dtsi; They will be removed once gpio drivers are converted to pinctrl.
- Renamed some pmic nodes, fixed dragonboard.c to find them properly.
- Added header and converted comments to c98-style in head.S
- Print error if pmic gpio node is not found.
Changes in v1:
- Add better help for dragonboard
- Move static structures to board_prepare_usb
- Add DM_SPMI to defconfig
arch/arm/dts/Makefile | 2 + arch/arm/dts/dragonboard410c-uboot.dtsi | 28 +++++ arch/arm/dts/dragonboard410c.dts | 148 ++++++++++++++++++++++ arch/arm/mach-snapdragon/Kconfig | 20 +++ board/qualcomm/dragonboard410c/Kconfig | 15 +++ board/qualcomm/dragonboard410c/MAINTAINERS | 6 + board/qualcomm/dragonboard410c/Makefile | 8 ++ board/qualcomm/dragonboard410c/dragonboard410c.c | 131 +++++++++++++++++++ board/qualcomm/dragonboard410c/head.S | 28 +++++ board/qualcomm/dragonboard410c/readme.txt | 40 ++++++ board/qualcomm/dragonboard410c/u-boot.lds | 90 +++++++++++++ configs/dragonboard410c_defconfig | 31 +++++ include/configs/dragonboard410c.h | 153 +++++++++++++++++++++++ 13 files changed, 700 insertions(+) create mode 100644 arch/arm/dts/dragonboard410c-uboot.dtsi create mode 100644 arch/arm/dts/dragonboard410c.dts create mode 100644 board/qualcomm/dragonboard410c/Kconfig create mode 100644 board/qualcomm/dragonboard410c/MAINTAINERS 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 641510c..2e48a11 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -100,6 +100,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-uboot.dtsi b/arch/arm/dts/dragonboard410c-uboot.dtsi new file mode 100644 index 0000000..cc2c175 --- /dev/null +++ b/arch/arm/dts/dragonboard410c-uboot.dtsi
Why is this *-uboot.dtsi name?
I think it should be similar to apb8016*.dtsi
@@ -0,0 +1,28 @@ +/*
- U-Boot addition to handle Dragonboard 410c pins
- (C) Copyright 2015 Mateusz Kulikowski mateusz.kulikowski@gmail.com
- SPDX-License-Identifier: GPL-2.0+
- */
+&pm8916_gpios {
usb_hub_reset_pm {
gpios = <&pm8916_gpios 2 0>;
};
usb_sw_sel_pm {
gpios = <&pm8916_gpios 3 0>;
};
+};
+&pm8916_pon {
key_vol_down {
gpios = <&pm8916_pon 1 0>;
};
key_power {
gpios = <&pm8916_pon 0 0>;
};
+}; diff --git a/arch/arm/dts/dragonboard410c.dts b/arch/arm/dts/dragonboard410c.dts new file mode 100644 index 0000000..7746622 --- /dev/null +++ b/arch/arm/dts/dragonboard410c.dts
I this should be same as apq8016-sbc.dts Linux is it?
@@ -0,0 +1,148 @@ +/*
- Qualcomm APQ8016 based Dragonboard 410C board device tree source
- (C) Copyright 2015 Mateusz Kulikowski mateusz.kulikowski@gmail.com
- SPDX-License-Identifier: GPL-2.0+
- */
+/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@78b0000";
};
soc {
#address-cells = <0x1>;
#size-cells = <0x1>;
ranges = <0x0 0x0 0x0 0xffffffff>;
compatible = "simple-bus";
clkc: qcom,gcc@1800000 {
compatible = "qcom,gcc-apq8016";
reg = <0x1800000 0x80000>;
#address-cells = <0x1>;
#size-cells = <0x0>;
};
serial@78b0000 {
compatible = "qcom,msm-uartdm-v1.4";
reg = <0x78b0000 0x200>;
u-boot,dm-pre-reloc;
clock = <&clkc 4>;
};
restart@4ab000 {
compatible = "qcom,pshold";
reg = <0x4ab000 0x4>;
};
soc_gpios: pinctrl@1000000 {
compatible = "qcom,apq8016-pinctrl";
reg = <0x1000000 0x300000>;
gpio-controller;
gpio-count = <122>;
gpio-bank-name="soc";
#gpio-cells = <1>;
};
ehci@78d9000 {
compatible = "qcom,ehci-host";
reg = <0x78d9000 0x400>;
};
sdhci@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@07864000 {
compatible = "qcom,sdhci-msm-v4";
reg = <0x7864900 0x11c 0x7864000 0x800>;
index = <0x1>;
bus-width = <0x4>;
clock = <&clkc 1>;
clock-frequency = <200000000>;
};
spmi@200f000 {
compatible = "qcom,spmi-pmic-arb";
reg = <0x200f800 0x200 0x2400000 0x400000 0x2c00000 0x400000>;
#address-cells = <0x1>;
#size-cells = <0x1>;
pmic0: pm8916@0 {
compatible = "qcom,spmi-pmic";
reg = <0x0 0x1>;
#address-cells = <0x1>;
#size-cells = <0x1>;
pm8916_pon: pm8916_pon@800 {
compatible = "qcom,pm8916-pwrkey";
reg = <0x800 0x96>;
#gpio-cells = <2>;
gpio-controller;
};
pm8916_gpios: pm8916_gpios@c000 {
compatible = "qcom,pm8916-gpio";
reg = <0xc000 0x400>;
gpio-controller;
gpio-count = <4>;
#gpio-cells = <2>;
gpio-bank-name="pmic";
};
};
pmic1: pm8916@1 {
compatible = "qcom,spmi-pmic";
reg = <0x1 0x1>;
};
};
};
leds {
compatible = "gpio-leds";
user1 {
label = "green:user1";
gpios = <&soc_gpios 21 0>;
};
user2 {
label = "green:user2";
gpios = <&soc_gpios 120 0>;
};
user3 {
label = "green:user3";
gpios = <&pm8916_gpios 0 0>;
};
user4 {
label = "green:user4";
gpios = <&pm8916_gpios 1 0>;
};
};
+};
I will test this series and let you know.
+#include "dragonboard410c-uboot.dtsi" diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig index 156e733..dc7ba21 100644 --- a/arch/arm/mach-snapdragon/Kconfig +++ b/arch/arm/mach-snapdragon/Kconfig @@ -3,4 +3,24 @@ if ARCH_SNAPDRAGON config SYS_SOC default "snapdragon"
+choice
prompt "Snapdragon board select"
+config TARGET_DRAGONBOARD410C
bool "96Boards Dragonboard 410C"
help
Support for 96Boards Dragonboard 410C. This board complies with
96Board Open Platform Specifications. Features:
- Qualcomm Snapdragon 410C SoC - APQ8016 (4xCortex A53, Adreno 306)
- 1GiB RAM
- 8GiB eMMC, uSD slot
- WiFi, Bluetooth and GPS module
- 2x Host, 1x Device USB port
- HDMI
- 20-pin low speed and 40-pin high speed expanders, 4 LED, 3 buttons
+endchoice
+source "board/qualcomm/dragonboard410c/Kconfig"
endif diff --git a/board/qualcomm/dragonboard410c/Kconfig b/board/qualcomm/dragonboard410c/Kconfig new file mode 100644 index 0000000..03bd7ae --- /dev/null +++ b/board/qualcomm/dragonboard410c/Kconfig @@ -0,0 +1,15 @@ +if TARGET_DRAGONBOARD410C
+config SYS_BOARD
default "dragonboard410c"
+config SYS_VENDOR
default "qualcomm"
+config SYS_SOC
default "apq8016"
+config SYS_CONFIG_NAME
default "dragonboard410c"
+endif diff --git a/board/qualcomm/dragonboard410c/MAINTAINERS b/board/qualcomm/dragonboard410c/MAINTAINERS new file mode 100644 index 0000000..65cb47c --- /dev/null +++ b/board/qualcomm/dragonboard410c/MAINTAINERS @@ -0,0 +1,6 @@ +DRAGONBOARD410C BOARD +M: Mateusz Kulikowski mateusz.kulikowski@gmail.com +S: Maintained +F: board/qualcomm/dragonboard410c/ +F: include/configs/dragonboard410c.h +F: configs/dragonboard410c_defconfig 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..1fa5664 --- /dev/null +++ b/board/qualcomm/dragonboard410c/dragonboard410c.c @@ -0,0 +1,131 @@ +/*
- Board init file for Dragonboard 410C
- (C) Copyright 2015 Mateusz Kulikowski mateusz.kulikowski@gmail.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <dm.h> +#include <usb.h> +#include <asm/gpio.h>
+DECLARE_GLOBAL_DATA_PTR;
+int dram_init(void) +{
gd->ram_size = PHYS_SDRAM_1_SIZE;
return 0;
+}
+void dram_init_banksize(void) +{
gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
+}
+int board_prepare_usb(enum usb_init_type type) +{
static struct udevice *pmic_gpio;
static struct gpio_desc hub_reset, usb_sel;
int ret = 0, node;
if (!pmic_gpio) {
ret = uclass_get_device_by_name(UCLASS_GPIO,
"pm8916_gpios@c000",
&pmic_gpio);
if (ret < 0) {
printf("Failed to find pm8916_gpios@c000 node.\n");
return ret;
}
}
/* 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, pmic_gpio->of_offset,
"usb_hub_reset_pm");
if (node < 0) {
printf("Failed to find usb_hub_reset_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_pm gpio.\n");
return ret;
}
}
if (!dm_gpio_is_valid(&usb_sel)) {
node = fdt_subnode_offset(gd->fdt_blob, pmic_gpio->of_offset,
"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) +{
struct udevice *pon;
struct gpio_desc resin;
int node, ret;
ret = uclass_get_device_by_name(UCLASS_GPIO, "pm8916_pon@800", &pon);
if (ret < 0) {
printf("Failed to find PMIC pon node. Check device tree\n");
return 0;
}
node = fdt_subnode_offset(gd->fdt_blob, pon->of_offset, "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..9f1e0d9 --- /dev/null +++ b/board/qualcomm/dragonboard410c/head.S @@ -0,0 +1,28 @@ +/*
- Little-Kernel/Fastboot header for proper chain-loading
- (C) Copyright 2015 Mateusz Kulikowski mateusz.kulikowski@gmail.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#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..84fe597 --- /dev/null +++ b/configs/dragonboard410c_defconfig @@ -0,0 +1,31 @@ +CONFIG_ARM=y +CONFIG_ARM64=y +CONFIG_ARCH_SNAPDRAGON=y +CONFIG_TARGET_DRAGONBOARD410C=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=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_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y +CONFIG_USB_STORAGE=y diff --git a/include/configs/dragonboard410c.h b/include/configs/dragonboard410c.h new file mode 100644 index 0000000..1dfb171 --- /dev/null +++ b/include/configs/dragonboard410c.h @@ -0,0 +1,153 @@ +/*
- Board configuration file for Dragonboard 410C
- (C) Copyright 2015 Mateusz Kulikowski mateusz.kulikowski@gmail.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef __CONFIGS_DRAGONBOARD410C_H +#define __CONFIGS_DRAGONBOARD410C_H
+#include <linux/sizes.h> +#include <asm/arch/sysmap-apq8016.h>
+#define CONFIG_IDENT_STRING "\nQualcomm-DragonBoard 410C"
+#define CONFIG_MISC_INIT_R /* To stop autoboot */
+/* Flat Device Tree Definitions */ +#define CONFIG_OF_LIBFDT
+/* Physical Memory Map */ +#define CONFIG_NR_DRAM_BANKS 1 +#define PHYS_SDRAM_1 0x80000000 +/* 1008 MB (the last ~30Mb are secured for TrustZone by ATF*/ +#define PHYS_SDRAM_1_SIZE 0x3da00000 +#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 +#define CONFIG_SYS_TEXT_BASE 0x80080000 +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x7fff0) +#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE + 0x80000) +#define CONFIG_SYS_BOOTM_LEN 0x1000000 /* 16MB max kernel size */
+/* UART */ +#define CONFIG_BAUDRATE 115200
+/* Generic Timer Definitions */ +#define COUNTER_FREQUENCY 19000000
+/* This are needed to have proper mmc support */ +#define CONFIG_MMC +#define CONFIG_GENERIC_MMC +#define CONFIG_SDHCI
+#define CONFIG_SYS_LDSCRIPT "board/qualcomm/dragonboard410c/u-boot.lds"
+/* Fixup - in init code we switch from device to host mode,
- it has to be done after each HCD reset */
+#define CONFIG_EHCI_HCD_INIT_AFTER_RESET
+#define CONFIG_USB_HOST_ETHER /* Enable USB Networking */
+/* Support all possible USB ethernet dongles */ +#define CONFIG_USB_ETHER_DM9601 +#define CONFIG_USB_ETHER_ASIX +#define CONFIG_USB_ETHER_ASIX88179 +#define CONFIG_USB_ETHER_MCS7830 +#define CONFIG_USB_ETHER_SMSC95XX
+/* Libraries */ +#define CONFIG_MD5
+/* Extra Commands */ +#define CONFIG_CMD_CACHE +#define CONFIG_CMD_ENV +#define CONFIG_CMD_GPIO +#define CONFIG_CMD_GPT +#define CONFIG_CMD_MD5SUM +#define CONFIG_CMD_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_REGINFO /* Register dump */ +#define CONFIG_CMD_TFTP +#define CONFIG_CMD_TIMER +#define CONFIG_CMD_UNZIP
+/* Partition table support */ +#define HAVE_BLOCK_DEVICE /* Needed for partition commands */ +#define CONFIG_PARTITION_UUIDS
+#include <config_distro_defaults.h>
+/* BOOTP options */ +#define CONFIG_BOOTP_BOOTFILESIZE
+/* Environment - Boot*/ +#define CONFIG_BOOTARGS "console=ttyMSM0,115200n8"
+#define BOOT_TARGET_DEVICES(func) \
func(USB, usb, 0) \
func(MMC, mmc, 0) \
func(MMC, mmc, 1) \
func(DHCP, dhcp, na)
+#include <config_distro_bootcmd.h>
+/* 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"
+/* Environment */ +#define CONFIG_EXTRA_ENV_SETTINGS \
"reflash="CONFIG_ENV_REFLASH"\0"\
"loadaddr=0x81000000\0" \
"fdt_high=0xffffffffffffffff\0" \
"initrd_high=0xffffffffffffffff\0" \
"linux_image=Image\0" \
"linux_addr=0x81000000\0"\
"fdt_image=apq8016-sbc.dtb\0" \
"fdt_addr=0x83000000\0"\
"ramdisk_addr=0x84000000\0"\
BOOTENV
+#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_MAXARGS 64 /* max command args */
+#endif
2.5.0
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

- Update MAINTAINERS - Update git-mailrc
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com ---
Changes in v2: - New patch
Changes in v1: None
MAINTAINERS | 11 +++++++++++ doc/git-mailrc | 3 +++ 2 files changed, 14 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS index b387207..56a0eba 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -125,6 +125,11 @@ F: arch/arm/mach-s5pc1xx/ F: arch/arm/cpu/armv7/s5p-common/ F: arch/arm/include/asm/arch-s3c24x0/
+ARM SNAPDRAGON +M: Mateusz Kulikowski mateusz.kulikowski@gmail.com +S: Maintained +F: arch/arm/mach-snapdragon/ + ARM STM SPEAR M: Vipin Kumar vipin.kumar@st.com S: Maintained @@ -389,6 +394,12 @@ F: drivers/mtd/spi/ F: drivers/spi/ F: include/spi*
+SPMI +M: Mateusz Kulikowski mateusz.kulikowski@gmail.com +S: Maintained +F: drivers/spmi/ +F: include/spmi/ + TQ GROUP M: Martin Krause martin.krause@tq-systems.de S: Maintained diff --git a/doc/git-mailrc b/doc/git-mailrc index ced7085..1201d4a 100644 --- a/doc/git-mailrc +++ b/doc/git-mailrc @@ -33,6 +33,7 @@ alias lukma Lukasz Majewski l.majewski@samsung.com alias macpaul Macpaul Lin macpaul@andestech.com alias marex Marek Vasut marex@denx.de alias masahiro Masahiro Yamada yamada.masahiro@socionext.com +alias mateusz Mateusz Kulikowski mateusz.kulikowski@gmail.com alias monstr Michal Simek monstr@monstr.eu alias panto Pantelis Antoniou panto@antoniou-consulting.com alias prafulla Prafulla Wadaskar prafulla@marvell.com @@ -67,6 +68,7 @@ alias rmobile uboot, iwamatsu alias s3c samsung alias s5pc samsung alias samsung uboot, prom +alias snapdragon uboot, mateusz alias socfpga uboot, marex, Dinh Nguyen dinguyen@opensource.altera.com alias sunxi uboot, ijc, jwrdegoede alias tegra uboot, sjg, Tom Warren twarren@nvidia.com, Stephen Warren swarren@nvidia.com @@ -127,6 +129,7 @@ alias nand uboot, scottwood alias net uboot, jhersh alias phy uboot, jhersh alias spi uboot, jagan +alias spmi uboot, mateusz alias ubi uboot, hs alias usb uboot, marex alias video uboot, ag

On 24 January 2016 at 13:53, Mateusz Kulikowski mateusz.kulikowski@gmail.com wrote:
- Update MAINTAINERS
- Update git-mailrc
Signed-off-by: Mateusz Kulikowski mateusz.kulikowski@gmail.com
Changes in v2:
- New patch
Changes in v1: None
MAINTAINERS | 11 +++++++++++ doc/git-mailrc | 3 +++ 2 files changed, 14 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
participants (3)
-
Jagan Teki
-
Mateusz Kulikowski
-
Simon Glass