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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <device/pnp_ops.h>
#include <device/pnp.h>
#include <stdint.h>
#include "ite.h"
#include "ite_gpio.h"
/* Catch ITE SIOs that enable the driver but do not configure the number of sets */
#if CONFIG_SUPERIO_ITE_COMMON_NUM_GPIO_SETS == 0
#error "Maximum number of ITE SIO GPIO sets not provided"
#endif
#if CONFIG_SUPERIO_ITE_COMMON_NUM_GPIO_SETS > 10
#error "ITE SIO GPIO drivers only support up to 10 GPIO sets"
#endif
/* GPIO Polarity Select: 1: Inverting, 0: Non-inverting */
#define ITE_GPIO_REG_POLARITY(x) \
(((x) > 8) ? (0xd1 + ((x) - 9) * 5) \
: (0xb0 + ((x) - 1)) \
)
/* GPIO Internal Pull-up: 1: Enable, 0: Disable */
#define ITE_GPIO_REG_PULLUP(x) \
(((x) > 8) ? (0xd4 + ((x) - 9) * 5) \
: (0xb8 + ((x) - 1)) \
)
/* GPIO Function Select: 1: Simple I/O, 0: Alternate function */
#define ITE_GPIO_REG_FN_SELECT(x) \
(((x) > 8) ? (0xd3 + ((x) - 9) * 5) \
: (0xc0 + ((x) - 1)) \
)
/* GPIO Mode: 0: input mode, 1: output mode */
#define ITE_GPIO_REG_OUTPUT(x) \
(((x) > 8) ? (0xd2 + ((x) - 9) * 5) \
: (0xc8 + ((x) - 1)) \
)
/* GPIO LED pin mapping register */
#define ITE_GPIO_REG_LED_PINMAP(x) (0xf8 + ((x) & 1) * 2)
#define ITE_GPIO_LED_PIN_LOC(set, pin) ((((set) & 7) << 3) | ((pin) & 7))
#define ITE_GPIO_LED_PIN_LOC_MASK 0x3f
/* GPIO LED control register */
#define ITE_GPIO_REG_LED_CONTROL(x) (0xf9 + ((x) & 1) * 2)
#define ITE_GPIO_LED_OUTPUT_LOW (1 << 0)
#define ITE_GPIO_LED_PINMAP_CLEAR (1 << 4)
#define ITE_GPIO_LED_SHORT_LOW_PULSE \
(CONFIG(SUPERIO_ITE_COMMON_GPIO_LED_FREQ_5BIT) ? (1 << 5) \
: (1 << 3) \
)
#define ITE_GPIO_LED_FREQ_SEL(x) \
(CONFIG(SUPERIO_ITE_COMMON_GPIO_LED_FREQ_5BIT) \
? ((((x) & 0x18) << 3) | (((x) & 0x7) << 1)) \
: (((x) & 0x3) << 1) \
)
#define ITE_GPIO_LED_FREQ_SEL_MASK \
(CONFIG(SUPERIO_ITE_COMMON_GPIO_LED_FREQ_5BIT) ? 0xce : 0x06)
static bool ite_has_gpio_fn_select_reg(u8 set)
{
/* IT8718F has all registers for all sets. */
if (CONFIG(SUPERIO_ITE_IT8718F))
return true;
/* Typically ITE GPIO sets 6 to 8 don't have enable and polarity registers. */
if (set < 6 || set > 8)
return true;
return false;
}
static bool ite_has_gpio_polarity_reg(u8 set)
{
/* IT8718F has all registers for all sets. */
if (CONFIG(SUPERIO_ITE_IT8718F))
return true;
/* IT8720F/IT8721F has polarity register for all GPIO sets */
if (CONFIG(SUPERIO_ITE_IT8720F) || CONFIG(SUPERIO_ITE_IT8721F))
return true;
/* Typically ITE GPIO sets 6 to 8 don't have enable and polarity registers. */
if (set < 6 || set > 8)
return true;
return false;
}
static bool ite_has_gpio_pullup_reg(u8 set)
{
/* IT8718F/IT8720F does not have pull-up register for set 2 */
if ((CONFIG(SUPERIO_ITE_IT8718F) || CONFIG(SUPERIO_ITE_IT8720F)) && (set == 2))
return false;
/* IT8783E/F does not have pull-up register for set 6 */
if (CONFIG(SUPERIO_ITE_IT8783EF) && (set == 6))
return false;
/*
* ITE GPIO Sets 7 and 8 don't have a pullup register.
* See IT8786/IT8625 datasheet section 8.10.10.
* Also applies to IT8728F.
*/
if (set != 7 && set != 8)
return true;
return false;
}
/*
* Configures a single GPIO given its number as gpio_num, direction ("in_out"
* parameter) and properties, such as polarity and pull ("gpio_ctrl"
* parameter). The "enable" parameter can configure the GPIO in Simple I/O
* mode when set or Alternate function mode when clear. Some chips may also
* not support configuring all properties for a particular GPIO. It is left to
* the implementer to check if GPIO settings are valid for given gpio_num.
*/
void ite_gpio_setup(pnp_devfn_t gpiodev, u8 gpio_num, enum ite_gpio_direction in_out,
enum ite_gpio_mode enable, u8 gpio_ctrl)
{
u8 set = (gpio_num / 10);
u8 pin = (gpio_num % 10);
/* Number of configurable sets is chip dependent, 8 pins each */
if (gpio_num < 10 || set > CONFIG_SUPERIO_ITE_COMMON_NUM_GPIO_SETS || pin > 7)
return;
pnp_enter_conf_state(gpiodev);
pnp_set_logical_device(gpiodev);
if (ite_has_gpio_fn_select_reg(set))
pnp_unset_and_set_config(gpiodev, ITE_GPIO_REG_FN_SELECT(set),
1 << pin, (enable & 1) << pin);
if (ite_has_gpio_polarity_reg(set))
pnp_unset_and_set_config(gpiodev, ITE_GPIO_REG_POLARITY(set),
1 << pin,
(gpio_ctrl & ITE_GPIO_POL_INVERT) ? 1 << pin : 0);
pnp_unset_and_set_config(gpiodev, ITE_GPIO_REG_OUTPUT(set), 1 << pin, (in_out & 1) << pin);
if (ite_has_gpio_pullup_reg(set))
pnp_unset_and_set_config(gpiodev, ITE_GPIO_REG_PULLUP(set), 1 << pin,
(gpio_ctrl & ITE_GPIO_PULLUP_ENABLE) ? 1 << pin : 0);
pnp_exit_conf_state(gpiodev);
}
void ite_gpio_setup_led(pnp_devfn_t gpiodev, u8 gpio_num,
enum ite_gpio_led led_no,
enum ite_led_frequency freq,
u8 led_ctrl)
{
u8 set = (gpio_num / 10);
u8 pin = (gpio_num % 10);
u8 reg = 0;
/* Number of configurable sets is chip dependent, 8 pins each */
if (gpio_num < 10 || set > CONFIG_SUPERIO_ITE_COMMON_NUM_GPIO_SETS || pin > 7)
return;
/* LED is available only for GPIO sets 1-5 */
if (set > 5)
return;
pnp_enter_conf_state(gpiodev);
pnp_set_logical_device(gpiodev);
/* Pinmap clear bit is only available when frequency is controlled with 5 bits */
if (CONFIG(SUPERIO_ITE_COMMON_GPIO_LED_FREQ_5BIT) && (led_ctrl & ITE_LED_PINMAP_CLEAR))
reg |= ITE_GPIO_LED_PINMAP_CLEAR;
if (led_ctrl & ITE_LED_OUTPUT_LOW)
reg |= ITE_GPIO_LED_OUTPUT_LOW;
if (led_ctrl & ITE_LED_SHORT_LOW_PULSE)
reg |= ITE_GPIO_LED_SHORT_LOW_PULSE;
reg |= ITE_GPIO_LED_FREQ_SEL(freq);
pnp_write_config(gpiodev, ITE_GPIO_REG_LED_CONTROL(led_no), reg);
reg = ITE_GPIO_LED_PIN_LOC(set, pin);
pnp_write_config(gpiodev, ITE_GPIO_REG_LED_PINMAP(led_no), reg);
pnp_exit_conf_state(gpiodev);
}
|