1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2013 Broadcom Corporation.
4  */
5 
6 #include <common.h>
7 #include <malloc.h>
8 #include <asm/io.h>
9 #include <asm/arch/sysmap.h>
10 
11 #define GPIO_BASE				(void *)GPIO2_BASE_ADDR
12 
13 #define GPIO_PASSWD				0x00a5a501
14 #define GPIO_PER_BANK				32
15 #define GPIO_MAX_BANK_NUM			8
16 
17 #define GPIO_BANK(gpio)				((gpio) >> 5)
18 #define GPIO_BITMASK(gpio)	\
19 	(1UL << ((gpio) & (GPIO_PER_BANK - 1)))
20 
21 #define GPIO_OUT_STATUS(bank)			(0x00000000 + ((bank) << 2))
22 #define GPIO_IN_STATUS(bank)			(0x00000020 + ((bank) << 2))
23 #define GPIO_OUT_SET(bank)			(0x00000040 + ((bank) << 2))
24 #define GPIO_OUT_CLEAR(bank)			(0x00000060 + ((bank) << 2))
25 #define GPIO_INT_STATUS(bank)			(0x00000080 + ((bank) << 2))
26 #define GPIO_INT_MASK(bank)			(0x000000a0 + ((bank) << 2))
27 #define GPIO_INT_MSKCLR(bank)			(0x000000c0 + ((bank) << 2))
28 #define GPIO_CONTROL(bank)			(0x00000100 + ((bank) << 2))
29 #define GPIO_PWD_STATUS(bank)			(0x00000500 + ((bank) << 2))
30 
31 #define GPIO_GPPWR_OFFSET			0x00000520
32 
33 #define GPIO_GPCTR0_DBR_SHIFT			5
34 #define GPIO_GPCTR0_DBR_MASK			0x000001e0
35 
36 #define GPIO_GPCTR0_ITR_SHIFT			3
37 #define GPIO_GPCTR0_ITR_MASK			0x00000018
38 #define GPIO_GPCTR0_ITR_CMD_RISING_EDGE		0x00000001
39 #define GPIO_GPCTR0_ITR_CMD_FALLING_EDGE	0x00000002
40 #define GPIO_GPCTR0_ITR_CMD_BOTH_EDGE		0x00000003
41 
42 #define GPIO_GPCTR0_IOTR_MASK			0x00000001
43 #define GPIO_GPCTR0_IOTR_CMD_0UTPUT		0x00000000
44 #define GPIO_GPCTR0_IOTR_CMD_INPUT		0x00000001
45 
gpio_request(unsigned gpio,const char * label)46 int gpio_request(unsigned gpio, const char *label)
47 {
48 	unsigned int value, off;
49 
50 	writel(GPIO_PASSWD, GPIO_BASE + GPIO_GPPWR_OFFSET);
51 	off = GPIO_PWD_STATUS(GPIO_BANK(gpio));
52 	value = readl(GPIO_BASE + off) & ~GPIO_BITMASK(gpio);
53 	writel(value, GPIO_BASE + off);
54 
55 	return 0;
56 }
57 
gpio_free(unsigned gpio)58 int gpio_free(unsigned gpio)
59 {
60 	unsigned int value, off;
61 
62 	writel(GPIO_PASSWD, GPIO_BASE + GPIO_GPPWR_OFFSET);
63 	off = GPIO_PWD_STATUS(GPIO_BANK(gpio));
64 	value = readl(GPIO_BASE + off) | GPIO_BITMASK(gpio);
65 	writel(value, GPIO_BASE + off);
66 
67 	return 0;
68 }
69 
gpio_direction_input(unsigned gpio)70 int gpio_direction_input(unsigned gpio)
71 {
72 	u32 val;
73 
74 	val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
75 	val &= ~GPIO_GPCTR0_IOTR_MASK;
76 	val |= GPIO_GPCTR0_IOTR_CMD_INPUT;
77 	writel(val, GPIO_BASE + GPIO_CONTROL(gpio));
78 
79 	return 0;
80 }
81 
gpio_direction_output(unsigned gpio,int value)82 int gpio_direction_output(unsigned gpio, int value)
83 {
84 	int bank_id = GPIO_BANK(gpio);
85 	int bitmask = GPIO_BITMASK(gpio);
86 	u32 val, off;
87 
88 	val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
89 	val &= ~GPIO_GPCTR0_IOTR_MASK;
90 	val |= GPIO_GPCTR0_IOTR_CMD_0UTPUT;
91 	writel(val, GPIO_BASE + GPIO_CONTROL(gpio));
92 	off = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
93 
94 	val = readl(GPIO_BASE + off);
95 	val |= bitmask;
96 	writel(val, GPIO_BASE + off);
97 
98 	return 0;
99 }
100 
gpio_get_value(unsigned gpio)101 int gpio_get_value(unsigned gpio)
102 {
103 	int bank_id = GPIO_BANK(gpio);
104 	int bitmask = GPIO_BITMASK(gpio);
105 	u32 val, off;
106 
107 	/* determine the GPIO pin direction */
108 	val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
109 	val &= GPIO_GPCTR0_IOTR_MASK;
110 
111 	/* read the GPIO bank status */
112 	off = (GPIO_GPCTR0_IOTR_CMD_INPUT == val) ?
113 	    GPIO_IN_STATUS(bank_id) : GPIO_OUT_STATUS(bank_id);
114 	val = readl(GPIO_BASE + off);
115 
116 	/* return the specified bit status */
117 	return !!(val & bitmask);
118 }
119 
gpio_set_value(unsigned gpio,int value)120 void gpio_set_value(unsigned gpio, int value)
121 {
122 	int bank_id = GPIO_BANK(gpio);
123 	int bitmask = GPIO_BITMASK(gpio);
124 	u32 val, off;
125 
126 	/* determine the GPIO pin direction */
127 	val = readl(GPIO_BASE + GPIO_CONTROL(gpio));
128 	val &= GPIO_GPCTR0_IOTR_MASK;
129 
130 	/* this function only applies to output pin */
131 	if (GPIO_GPCTR0_IOTR_CMD_INPUT == val) {
132 		printf("%s: Cannot set an input pin %d\n", __func__, gpio);
133 		return;
134 	}
135 
136 	off = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
137 
138 	val = readl(GPIO_BASE + off);
139 	val |= bitmask;
140 	writel(val, GPIO_BASE + off);
141 }
142