Skip to content

Commit 04820c1

Browse files
Tim GoverJuerg Haefliger
authored andcommitted
pinctrl-bcm2835: Add support for BCM2838
GPIO configuration on BCM2838 is largely the same as BCM2835 except for the pull up/down configuration. The old mechanism has been replaced by new registers which don't require the fixed delay. Detect BCN2838 at run-time and use the new mechanism. Backwards compatibility for the device-tree configuration has been retained. (cherry picked from commit 928c90b0346026e91191dbe3de3e6f3725f8dbd4 https://github.com/raspberrypi/linux.git rpi-5.3.y) Signed-off-by: Hui Wang <hui.wang@canonical.com>
1 parent 41b6e73 commit 04820c1

File tree

1 file changed

+45
-15
lines changed

1 file changed

+45
-15
lines changed

drivers/pinctrl/bcm/pinctrl-bcm2835.c

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@
5959
#define GPPUDCLK0 0x98 /* Pin Pull-up/down Enable Clock */
6060
#define GP_GPIO_PUP_PDN_CNTRL_REG0 0xe4 /* 2711 Pin Pull-up/down select */
6161

62+
/* 2711 has a different mechanism for pin pull-up/down/enable */
63+
#define GPPUPPDN0 0xe4 /* Pin pull-up/down for pins 15:0 */
64+
#define GPPUPPDN1 0xe8 /* Pin pull-up/down for pins 31:16 */
65+
#define GPPUPPDN2 0xec /* Pin pull-up/down for pins 47:32 */
66+
#define GPPUPPDN3 0xf0 /* Pin pull-up/down for pins 57:48 */
67+
6268
#define FSEL_REG(p) (GPFSEL0 + (((p) / 10) * 4))
6369
#define FSEL_SHIFT(p) (((p) % 10) * 3)
6470
#define GPIO_REG_OFFSET(p) ((p) / 32)
@@ -915,21 +921,45 @@ static void bcm2835_pull_config_set(struct bcm2835_pinctrl *pc,
915921
unsigned int pin, unsigned int arg)
916922
{
917923
u32 off, bit;
918-
919-
off = GPIO_REG_OFFSET(pin);
920-
bit = GPIO_REG_SHIFT(pin);
921-
922-
bcm2835_gpio_wr(pc, GPPUD, arg & 3);
923-
/*
924-
* BCM2835 datasheet say to wait 150 cycles, but not of what.
925-
* But the VideoCore firmware delay for this operation
926-
* based nearly on the same amount of VPU cycles and this clock
927-
* runs at 250 MHz.
928-
*/
929-
udelay(1);
930-
bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit));
931-
udelay(1);
932-
bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0);
924+
/* BCM2835, BCM2836 & BCM2837 return 'gpio' for this unused register */
925+
int is_2835 = bcm2835_gpio_rd(pc, GPPUPPDN3) == 0x6770696f;
926+
927+
if (is_2835) {
928+
off = GPIO_REG_OFFSET(pin);
929+
bit = GPIO_REG_SHIFT(pin);
930+
/*
931+
* BCM2835 datasheet say to wait 150 cycles, but not of what.
932+
* But the VideoCore firmware delay for this operation
933+
* based nearly on the same amount of VPU cycles and this clock
934+
* runs at 250 MHz.
935+
*/
936+
bcm2835_gpio_wr(pc, GPPUD, arg & 3);
937+
udelay(1);
938+
bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit));
939+
udelay(1);
940+
bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0);
941+
} else {
942+
u32 reg;
943+
int lsb;
944+
945+
off = (pin >> 4);
946+
if (off > 3)
947+
return;
948+
lsb = (pin & 0xf) << 1;
949+
950+
/* The up/down semantics are reversed compared to BCM2835.
951+
* Instead of updating all the device tree files, translate the
952+
* values here.
953+
*/
954+
if (arg == 2)
955+
arg = 1;
956+
else if (arg == 1)
957+
arg = 2;
958+
reg = bcm2835_gpio_rd(pc, GPPUPPDN0 + (off *4));
959+
reg &= ~(0x3 << lsb);
960+
reg |= (arg & 3) << lsb;
961+
bcm2835_gpio_wr(pc, GPPUPPDN0 + (off * 4), reg);
962+
}
933963
}
934964

935965
static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev,

0 commit comments

Comments
 (0)