summaryrefslogtreecommitdiff
path: root/drivers/gpio/twl4030-gpio.c
blob: 57c12fcfb95a85186749e3a91dba0fb50039fd57 (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
#include <common.h>
#include <twl4030.h>

#define BIT(x) (1 << (x))

/* GPIO_CTRL Fields */
#define MASK_GPIO_CTRL_GPIO_ON		BIT(2)

/* store usage of each GPIO. - each bit represents one GPIO */
static unsigned int gpio_usage_count;

static inline int gpio_twl4030_write(u8 address, u8 data)
{
	return twl4030_i2c_write_u8(TWL4030_CHIP_GPIO, data, address);
}

static inline int gpio_twl4030_read(u8 address)
{
	u8 data;
	int ret = 0;

	ret = twl4030_i2c_read_u8(TWL4030_CHIP_GPIO, &data, address);
	return (ret < 0) ? ret : data;
}

int twl4030_set_gpio_direction(unsigned int gpio, unsigned int is_input)
{
	u8 d_bnk = gpio >> 3;
	u8 d_msk = BIT(gpio & 0x7);
	u8 reg = 0;
	u8 base = REG_GPIODATADIR1 + d_bnk;
	int ret = 0;

	ret = gpio_twl4030_read(base);
	if (ret >= 0) {
		if (is_input)
			reg = ret & ~d_msk;
		else
			reg = ret | d_msk;

		ret = gpio_twl4030_write(base, reg);
	}

	return ret;
}

int twl4030_set_gpio_dataout(unsigned int gpio, unsigned int enable)
{
	u8 d_bnk = gpio >> 3;
	u8 d_msk = BIT(gpio & 0x7);
	u8 base = 0;

	if (enable)
		base = REG_SETGPIODATAOUT1 + d_bnk;
	else
		base = REG_CLEARGPIODATAOUT1 + d_bnk;

	return gpio_twl4030_write(base, d_msk);
}

int twl4030_get_gpio_datain(unsigned int gpio)
{
	u8 d_bnk = gpio >> 3;
	u8 d_off = gpio & 0x7;
	u8 base = 0;
	int ret = 0;

	if (unlikely((gpio >= TWL4030_GPIO_MAX)
		|| !(gpio_usage_count & BIT(gpio))))
		return -1;

	base = REG_GPIODATAIN1 + d_bnk;
	ret = gpio_twl4030_read(base);
	if (ret > 0)
		ret = (ret >> d_off) & 0x1;

	return ret;
}

int twl4030_request_gpio(unsigned int gpio)
{
	int status = 0;

	/* on first use, turn GPIO module "on" */
	if (!gpio_usage_count) {
		// struct twl4030_gpio_platform_data *pdata;
		u8 value = MASK_GPIO_CTRL_GPIO_ON;

		status = gpio_twl4030_write(REG_GPIO_CTRL, value);
	}

	if (!status)
		gpio_usage_count |= (0x1 << gpio);

	return status;
}

void twl4030_free_gpio(unsigned int gpio)
{
	gpio_usage_count &= ~BIT(gpio);

	/* on last use, switch off GPIO module */
	if (!gpio_usage_count)
		gpio_twl4030_write(REG_GPIO_CTRL, 0x0);
}