
On 8 February 2016 at 02:27, 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 Tested-by: Simon Glass sjg@chromium.org
Changes in v3: None 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 | 1 + drivers/gpio/msm_gpio.c | 135 +++++++++++++++++++++++++++++ 4 files changed, 172 insertions(+) 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";
Can't this driver goes into pinctrl (I mean gpio handling pincontrol), because Linux handle these gpio msm8916-pinctrl through pinctrl subsystem as per as I know, let me know in case if I miss anything here.
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 845dc72..a5e8182 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 845a6d4..6083c4a 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_PIC32_GPIO) += pic32_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),
+};
-- 2.5.0
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot