Skip to content

Commit 42bd007

Browse files
Chew, Kean HoLinus Walleij
authored andcommitted
pinctrl-baytrail: add function mux checking in gpio pin request
The requested gpio pin must has the func_pin_mux field set to GPIO function by BIOS/FW in advanced. Else, the gpio pin request would fail. This is to ensure that we do not expose any gpio pins which shall be used for alternate functions, for eg: wakeup pin, I/O interfaces for LPSS, etc. Signed-off-by: Chew, Kean Ho <[email protected]> Signed-off-by: Chew, Chiau Ee <[email protected]> Reviewed-by: Darren Hart <[email protected]> Signed-off-by: Linus Walleij <[email protected]>
1 parent a76cbd7 commit 42bd007

File tree

1 file changed

+39
-3
lines changed

1 file changed

+39
-3
lines changed

drivers/pinctrl/pinctrl-baytrail.c

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@
6060
#define BYT_NGPIO_NCORE 28
6161
#define BYT_NGPIO_SUS 44
6262

63+
#define BYT_SCORE_ACPI_UID "1"
64+
#define BYT_NCORE_ACPI_UID "2"
65+
#define BYT_SUS_ACPI_UID "3"
66+
6367
/*
6468
* Baytrail gpio controller consist of three separate sub-controllers called
6569
* SCORE, NCORE and SUS. The sub-controllers are identified by their acpi UID.
@@ -102,17 +106,17 @@ static unsigned const sus_pins[BYT_NGPIO_SUS] = {
102106

103107
static struct pinctrl_gpio_range byt_ranges[] = {
104108
{
105-
.name = "1", /* match with acpi _UID in probe */
109+
.name = BYT_SCORE_ACPI_UID, /* match with acpi _UID in probe */
106110
.npins = BYT_NGPIO_SCORE,
107111
.pins = score_pins,
108112
},
109113
{
110-
.name = "2",
114+
.name = BYT_NCORE_ACPI_UID,
111115
.npins = BYT_NGPIO_NCORE,
112116
.pins = ncore_pins,
113117
},
114118
{
115-
.name = "3",
119+
.name = BYT_SUS_ACPI_UID,
116120
.npins = BYT_NGPIO_SUS,
117121
.pins = sus_pins,
118122
},
@@ -145,9 +149,41 @@ static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset,
145149
return vg->reg_base + reg_offset + reg;
146150
}
147151

152+
static bool is_special_pin(struct byt_gpio *vg, unsigned offset)
153+
{
154+
/* SCORE pin 92-93 */
155+
if (!strcmp(vg->range->name, BYT_SCORE_ACPI_UID) &&
156+
offset >= 92 && offset <= 93)
157+
return true;
158+
159+
/* SUS pin 11-21 */
160+
if (!strcmp(vg->range->name, BYT_SUS_ACPI_UID) &&
161+
offset >= 11 && offset <= 21)
162+
return true;
163+
164+
return false;
165+
}
166+
148167
static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
149168
{
150169
struct byt_gpio *vg = to_byt_gpio(chip);
170+
void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG);
171+
u32 value;
172+
bool special;
173+
174+
/*
175+
* In most cases, func pin mux 000 means GPIO function.
176+
* But, some pins may have func pin mux 001 represents
177+
* GPIO function. Only allow user to export pin with
178+
* func pin mux preset as GPIO function by BIOS/FW.
179+
*/
180+
value = readl(reg) & BYT_PIN_MUX;
181+
special = is_special_pin(vg, offset);
182+
if ((special && value != 1) || (!special && value)) {
183+
dev_err(&vg->pdev->dev,
184+
"pin %u cannot be used as GPIO.\n", offset);
185+
return -EINVAL;
186+
}
151187

152188
pm_runtime_get(&vg->pdev->dev);
153189

0 commit comments

Comments
 (0)