175295Sdes// SPDX-License-Identifier: GPL-2.0+
275295Sdes/*
375295Sdes * Copyright (C) 2017 Marek Vasut <marek.vasut@gmail.com>
475295Sdes */
575295Sdes
675295Sdes#include <common.h>
775295Sdes#include <clk.h>
875295Sdes#include <dm.h>
975295Sdes#include <malloc.h>
1075295Sdes#include <asm/global_data.h>
1175295Sdes#include <dm/device_compat.h>
1275295Sdes#include <dm/pinctrl.h>
1375295Sdes#include <errno.h>
1475295Sdes#include <asm/gpio.h>
1575295Sdes#include <asm/io.h>
1675295Sdes#include <linux/bitops.h>
1775295Sdes#include "../pinctrl/renesas/sh_pfc.h"
1875295Sdes
1975295Sdes#define GPIO_IOINTSEL	0x00	/* General IO/Interrupt Switching Register */
2075295Sdes#define GPIO_INOUTSEL	0x04	/* General Input/Output Switching Register */
2175295Sdes#define GPIO_OUTDT	0x08	/* General Output Register */
2275295Sdes#define GPIO_INDT	0x0c	/* General Input Register */
2375295Sdes#define GPIO_INTDT	0x10	/* Interrupt Display Register */
2475295Sdes#define GPIO_INTCLR	0x14	/* Interrupt Clear Register */
2575295Sdes#define GPIO_INTMSK	0x18	/* Interrupt Mask Register */
2675295Sdes#define GPIO_MSKCLR	0x1c	/* Interrupt Mask Clear Register */
2775295Sdes#define GPIO_POSNEG	0x20	/* Positive/Negative Logic Select Register */
2875295Sdes#define GPIO_EDGLEVEL	0x24	/* Edge/level Select Register */
2975295Sdes#define GPIO_FILONOFF	0x28	/* Chattering Prevention On/Off Register */
3075295Sdes#define GPIO_BOTHEDGE	0x4c	/* One Edge/Both Edge Select Register */
3175295Sdes#define GPIO_INEN	0x50	/* General Input Enable Register */
3275295Sdes
3375295Sdes#define RCAR_MAX_GPIO_PER_BANK		32
3478073Sdes
3575295Sdes#define RCAR_GPIO_HAS_INEN		BIT(0)
3677965Sdes
3784246SdesDECLARE_GLOBAL_DATA_PTR;
3875295Sdes
3975295Sdesstruct rcar_gpio_priv {
4075295Sdes	void __iomem		*regs;
4175295Sdes	u32			quirks;
4275295Sdes	int			pfc_offset;
4375295Sdes};
4477998Sdes
4575295Sdesstatic int rcar_gpio_get_value(struct udevice *dev, unsigned offset)
4675295Sdes{
4789071Smsmith	struct rcar_gpio_priv *priv = dev_get_priv(dev);
4884246Sdes	const u32 bit = BIT(offset);
4975295Sdes
5075295Sdes	/*
5175295Sdes	 * Testing on r8a7790 shows that INDT does not show correct pin state
5275295Sdes	 * when configured as output, so use OUTDT in case of output pins.
5384246Sdes	 */
5484246Sdes	if (readl(priv->regs + GPIO_INOUTSEL) & bit)
5584246Sdes		return !!(readl(priv->regs + GPIO_OUTDT) & bit);
5684246Sdes	else
5784246Sdes		return !!(readl(priv->regs + GPIO_INDT) & bit);
5884246Sdes}
5984246Sdes
6084246Sdesstatic int rcar_gpio_set_value(struct udevice *dev, unsigned offset,
6184246Sdes			       int value)
6284246Sdes{
6375295Sdes	struct rcar_gpio_priv *priv = dev_get_priv(dev);
6484246Sdes
6584246Sdes	if (value)
6675295Sdes		setbits_le32(priv->regs + GPIO_OUTDT, BIT(offset));
6775295Sdes	else
6875295Sdes		clrbits_le32(priv->regs + GPIO_OUTDT, BIT(offset));
6984246Sdes
7084246Sdes	return 0;
7175295Sdes}
7275295Sdes
7375295Sdesstatic void rcar_gpio_set_direction(struct udevice *dev, unsigned offset,
7475295Sdes				    bool output)
7575295Sdes{
7675295Sdes	struct rcar_gpio_priv *priv = dev_get_priv(dev);
7775295Sdes	void __iomem *regs = priv->regs;
7875295Sdes
7975295Sdes	/*
8075295Sdes	 * follow steps in the GPIO documentation for
8193818Sjhb	 * "Setting General Output Mode" and
8293818Sjhb	 * "Setting General Input Mode"
8384246Sdes	 */
8484246Sdes
8575295Sdes	/* Configure postive logic in POSNEG */
8675295Sdes	clrbits_le32(regs + GPIO_POSNEG, BIT(offset));
8775295Sdes
8875295Sdes	/* Select "Input Enable/Disable" in INEN */
8975295Sdes	if (priv->quirks & RCAR_GPIO_HAS_INEN) {
9075295Sdes		if (output)
9175295Sdes			clrbits_le32(regs + GPIO_INEN, BIT(offset));
9275295Sdes		else
9384246Sdes			setbits_le32(regs + GPIO_INEN, BIT(offset));
9484386Sdes	}
9584386Sdes
9684386Sdes	/* Select "General Input/Output Mode" in IOINTSEL */
9775295Sdes	clrbits_le32(regs + GPIO_IOINTSEL, BIT(offset));
9875295Sdes
9975295Sdes	/* Select Input Mode or Output Mode in INOUTSEL */
10075295Sdes	if (output)
10175295Sdes		setbits_le32(regs + GPIO_INOUTSEL, BIT(offset));
10275295Sdes	else
10375295Sdes		clrbits_le32(regs + GPIO_INOUTSEL, BIT(offset));
10477998Sdes}
10577998Sdes
10675295Sdesstatic int rcar_gpio_direction_input(struct udevice *dev, unsigned offset)
10777998Sdes{
10875295Sdes	rcar_gpio_set_direction(dev, offset, false);
10988234Sdillon
11088234Sdillon	return 0;
11197940Sdes}
11288234Sdillon
11388234Sdillonstatic int rcar_gpio_direction_output(struct udevice *dev, unsigned offset,
11475295Sdes				      int value)
11584246Sdes{
11677998Sdes	/* write GPIO value to output before selecting output mode of pin */
11784246Sdes	rcar_gpio_set_value(dev, offset, value);
11875295Sdes	rcar_gpio_set_direction(dev, offset, true);
11984246Sdes
12075295Sdes	return 0;
12188234Sdillon}
12288234Sdillon
12399566Sjeffstatic int rcar_gpio_get_function(struct udevice *dev, unsigned offset)
12499566Sjeff{
12575295Sdes	struct rcar_gpio_priv *priv = dev_get_priv(dev);
12675295Sdes
12777998Sdes	if (readl(priv->regs + GPIO_INOUTSEL) & BIT(offset))
12877998Sdes		return GPIOF_OUTPUT;
12977998Sdes	else
13077998Sdes		return GPIOF_INPUT;
13177998Sdes}
13275295Sdes
13375295Sdesstatic const struct dm_gpio_ops rcar_gpio_ops = {
13475295Sdes	.request		= pinctrl_gpio_request,
13577998Sdes	.rfree			= pinctrl_gpio_free,
13684246Sdes	.direction_input	= rcar_gpio_direction_input,
13784246Sdes	.direction_output	= rcar_gpio_direction_output,
138103314Snjl	.get_value		= rcar_gpio_get_value,
139105165Sphk	.set_value		= rcar_gpio_set_value,
140105165Sphk	.get_function		= rcar_gpio_get_function,
14175295Sdes};
142105165Sphk
14377998Sdesstatic int rcar_gpio_probe(struct udevice *dev)
14477998Sdes{
14577998Sdes	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
14675295Sdes	struct rcar_gpio_priv *priv = dev_get_priv(dev);
14775295Sdes	struct fdtdec_phandle_args args;
148101308Sjeff	struct clk clk;
14975295Sdes	int node = dev_of_offset(dev);
15075295Sdes	int ret;
15175295Sdes
15284246Sdes	priv->regs = dev_read_addr_ptr(dev);
15375295Sdes	priv->quirks = dev_get_driver_data(dev);
15475295Sdes	uc_priv->bank_name = dev->name;
15575295Sdes
15677998Sdes	ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, node, "gpio-ranges",
15775295Sdes					     NULL, 3, 0, &args);
15875295Sdes	priv->pfc_offset = ret == 0 ? args.args[1] : -1;
15975295Sdes	uc_priv->gpio_count = ret == 0 ? args.args[2] : RCAR_MAX_GPIO_PER_BANK;
16075295Sdes
16175295Sdes	ret = clk_get_by_index(dev, 0, &clk);
16275295Sdes	if (ret < 0) {
16375295Sdes		dev_err(dev, "Failed to get GPIO bank clock\n");
16475295Sdes		return ret;
16577998Sdes	}
16677998Sdes
16775295Sdes	ret = clk_enable(&clk);
16875295Sdes	if (ret) {
16975295Sdes		dev_err(dev, "Failed to enable GPIO bank clock\n");
170103314Snjl		return ret;
171103314Snjl	}
172103314Snjl
173103314Snjl	return 0;
174103314Snjl}
175103314Snjl
17684246Sdesstatic const struct udevice_id rcar_gpio_ids[] = {
17777998Sdes	{ .compatible = "renesas,gpio-r8a7795" },
17884246Sdes	{ .compatible = "renesas,gpio-r8a7796" },
17984246Sdes	{ .compatible = "renesas,gpio-r8a77965" },
18084246Sdes	{ .compatible = "renesas,gpio-r8a77970" },
18184246Sdes	{ .compatible = "renesas,gpio-r8a77990" },
18284246Sdes	{ .compatible = "renesas,gpio-r8a77995" },
18375295Sdes	{ .compatible = "renesas,gpio-r8a779a0", .data = RCAR_GPIO_HAS_INEN },
184105077Smckusick	{ .compatible = "renesas,rcar-gen2-gpio" },
18599566Sjeff	{ .compatible = "renesas,rcar-gen3-gpio" },
18675295Sdes	{ .compatible = "renesas,rcar-gen4-gpio", .data = RCAR_GPIO_HAS_INEN },
18775295Sdes	{ /* sentinel */ }
18875295Sdes};
18975295Sdes
19075295SdesU_BOOT_DRIVER(rcar_gpio) = {
19175295Sdes	.name	= "rcar-gpio",
19275295Sdes	.id	= UCLASS_GPIO,
19375295Sdes	.of_match = rcar_gpio_ids,
19475295Sdes	.ops	= &rcar_gpio_ops,
19577998Sdes	.priv_auto	= sizeof(struct rcar_gpio_priv),
19688234Sdillon	.probe	= rcar_gpio_probe,
19788234Sdillon};
19897940Sdes