summaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/ath79/pinctrl_ar933x.c
blob: e3f64b63553cd6aaba741edd062b0f6ff8a668b8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
 *
 * SPDX-License-Identifier: GPL-2.0+
 */

#include <common.h>
#include <dm.h>
#include <errno.h>
#include <asm/io.h>
#include <dm/pinctrl.h>
#include <mach/ar71xx_regs.h>

DECLARE_GLOBAL_DATA_PTR;

enum periph_id {
	PERIPH_ID_UART0,
	PERIPH_ID_SPI0,
	PERIPH_ID_NONE = -1,
};

struct ar933x_pinctrl_priv {
	void __iomem *regs;
};

static void pinctrl_ar933x_spi_config(struct ar933x_pinctrl_priv *priv, int cs)
{
	switch (cs) {
	case 0:
		clrsetbits_be32(priv->regs + AR71XX_GPIO_REG_OE,
				AR933X_GPIO(4), AR933X_GPIO(3) |
				AR933X_GPIO(5) | AR933X_GPIO(2));
		setbits_be32(priv->regs + AR71XX_GPIO_REG_FUNC,
			     AR933X_GPIO_FUNC_SPI_EN |
			     AR933X_GPIO_FUNC_RES_TRUE);
		break;
	}
}

static void pinctrl_ar933x_uart_config(struct ar933x_pinctrl_priv *priv, int uart_id)
{
	switch (uart_id) {
	case PERIPH_ID_UART0:
		clrsetbits_be32(priv->regs + AR71XX_GPIO_REG_OE,
				AR933X_GPIO(9), AR933X_GPIO(10));
		setbits_be32(priv->regs + AR71XX_GPIO_REG_FUNC,
			     AR933X_GPIO_FUNC_UART_EN |
			     AR933X_GPIO_FUNC_RES_TRUE);
		break;
	}
}

static int ar933x_pinctrl_request(struct udevice *dev, int func, int flags)
{
	struct ar933x_pinctrl_priv *priv = dev_get_priv(dev);

	debug("%s: func=%x, flags=%x\n", __func__, func, flags);
	switch (func) {
	case PERIPH_ID_SPI0:
		pinctrl_ar933x_spi_config(priv, flags);
		break;
	case PERIPH_ID_UART0:
		pinctrl_ar933x_uart_config(priv, func);
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static int ar933x_pinctrl_get_periph_id(struct udevice *dev,
					struct udevice *periph)
{
	u32 cell[2];
	int ret;

	ret = fdtdec_get_int_array(gd->fdt_blob, periph->of_offset,
				   "interrupts", cell, ARRAY_SIZE(cell));
	if (ret < 0)
		return -EINVAL;

	switch (cell[0]) {
	case 128:
		return PERIPH_ID_UART0;
	case 129:
		return PERIPH_ID_SPI0;
	}
	return -ENOENT;
}

static int ar933x_pinctrl_set_state_simple(struct udevice *dev,
					   struct udevice *periph)
{
	int func;

	func = ar933x_pinctrl_get_periph_id(dev, periph);
	if (func < 0)
		return func;
	return ar933x_pinctrl_request(dev, func, 0);
}

static struct pinctrl_ops ar933x_pinctrl_ops = {
	.set_state_simple	= ar933x_pinctrl_set_state_simple,
	.request	= ar933x_pinctrl_request,
	.get_periph_id	= ar933x_pinctrl_get_periph_id,
};

static int ar933x_pinctrl_probe(struct udevice *dev)
{
	struct ar933x_pinctrl_priv *priv = dev_get_priv(dev);
	fdt_addr_t addr;

	addr = dev_get_addr(dev);
	if (addr == FDT_ADDR_T_NONE)
		return -EINVAL;

	priv->regs = map_physmem(addr,
				 AR71XX_GPIO_SIZE,
				 MAP_NOCACHE);
	return 0;
}

static const struct udevice_id ar933x_pinctrl_ids[] = {
	{ .compatible = "qca,ar933x-pinctrl" },
	{ }
};

U_BOOT_DRIVER(pinctrl_ar933x) = {
	.name		= "pinctrl_ar933x",
	.id		= UCLASS_PINCTRL,
	.of_match	= ar933x_pinctrl_ids,
	.priv_auto_alloc_size = sizeof(struct ar933x_pinctrl_priv),
	.ops		= &ar933x_pinctrl_ops,
	.probe		= ar933x_pinctrl_probe,
};
OpenPOWER on IntegriCloud