1 /* 2 * Copyright (C) 2012 Vikram Narayananan 3 * <vikram186@gmail.com> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <dm.h> 10 #include <dm/pinctrl.h> 11 #include <errno.h> 12 #include <asm/gpio.h> 13 #include <asm/io.h> 14 #include <fdtdec.h> 15 16 struct bcm2835_gpios { 17 struct bcm2835_gpio_regs *reg; 18 struct udevice *pinctrl; 19 }; 20 21 static int bcm2835_gpio_direction_input(struct udevice *dev, unsigned gpio) 22 { 23 struct bcm2835_gpios *gpios = dev_get_priv(dev); 24 unsigned val; 25 26 val = readl(&gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]); 27 val &= ~(BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio)); 28 val |= (BCM2835_GPIO_INPUT << BCM2835_GPIO_FSEL_SHIFT(gpio)); 29 writel(val, &gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]); 30 31 return 0; 32 } 33 34 static int bcm2835_gpio_direction_output(struct udevice *dev, unsigned int gpio, 35 int value) 36 { 37 struct bcm2835_gpios *gpios = dev_get_priv(dev); 38 unsigned val; 39 40 gpio_set_value(gpio, value); 41 42 val = readl(&gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]); 43 val &= ~(BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio)); 44 val |= (BCM2835_GPIO_OUTPUT << BCM2835_GPIO_FSEL_SHIFT(gpio)); 45 writel(val, &gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]); 46 47 return 0; 48 } 49 50 static int bcm2835_get_value(const struct bcm2835_gpios *gpios, unsigned gpio) 51 { 52 unsigned val; 53 54 val = readl(&gpios->reg->gplev[BCM2835_GPIO_COMMON_BANK(gpio)]); 55 56 return (val >> BCM2835_GPIO_COMMON_SHIFT(gpio)) & 0x1; 57 } 58 59 static int bcm2835_gpio_get_value(struct udevice *dev, unsigned gpio) 60 { 61 const struct bcm2835_gpios *gpios = dev_get_priv(dev); 62 63 return bcm2835_get_value(gpios, gpio); 64 } 65 66 static int bcm2835_gpio_set_value(struct udevice *dev, unsigned gpio, 67 int value) 68 { 69 struct bcm2835_gpios *gpios = dev_get_priv(dev); 70 u32 *output_reg = value ? gpios->reg->gpset : gpios->reg->gpclr; 71 72 writel(1 << BCM2835_GPIO_COMMON_SHIFT(gpio), 73 &output_reg[BCM2835_GPIO_COMMON_BANK(gpio)]); 74 75 return 0; 76 } 77 78 static int bcm2835_gpio_get_function(struct udevice *dev, unsigned offset) 79 { 80 struct bcm2835_gpios *priv = dev_get_priv(dev); 81 int funcid; 82 83 funcid = pinctrl_get_gpio_mux(priv->pinctrl, 0, offset); 84 85 switch (funcid) { 86 case BCM2835_GPIO_OUTPUT: 87 return GPIOF_OUTPUT; 88 case BCM2835_GPIO_INPUT: 89 return GPIOF_INPUT; 90 default: 91 return GPIOF_FUNC; 92 } 93 } 94 95 static const struct dm_gpio_ops gpio_bcm2835_ops = { 96 .direction_input = bcm2835_gpio_direction_input, 97 .direction_output = bcm2835_gpio_direction_output, 98 .get_value = bcm2835_gpio_get_value, 99 .set_value = bcm2835_gpio_set_value, 100 .get_function = bcm2835_gpio_get_function, 101 }; 102 103 static int bcm2835_gpio_probe(struct udevice *dev) 104 { 105 struct bcm2835_gpios *gpios = dev_get_priv(dev); 106 struct bcm2835_gpio_platdata *plat = dev_get_platdata(dev); 107 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 108 109 uc_priv->bank_name = "GPIO"; 110 uc_priv->gpio_count = BCM2835_GPIO_COUNT; 111 gpios->reg = (struct bcm2835_gpio_regs *)plat->base; 112 113 /* We know we're spawned by the pinctrl driver */ 114 gpios->pinctrl = dev->parent; 115 116 return 0; 117 } 118 119 #if CONFIG_IS_ENABLED(OF_CONTROL) 120 static int bcm2835_gpio_ofdata_to_platdata(struct udevice *dev) 121 { 122 struct bcm2835_gpio_platdata *plat = dev_get_platdata(dev); 123 fdt_addr_t addr; 124 125 addr = devfdt_get_addr(dev); 126 if (addr == FDT_ADDR_T_NONE) 127 return -EINVAL; 128 129 plat->base = addr; 130 return 0; 131 } 132 #endif 133 134 U_BOOT_DRIVER(gpio_bcm2835) = { 135 .name = "gpio_bcm2835", 136 .id = UCLASS_GPIO, 137 .ofdata_to_platdata = of_match_ptr(bcm2835_gpio_ofdata_to_platdata), 138 .platdata_auto_alloc_size = sizeof(struct bcm2835_gpio_platdata), 139 .ops = &gpio_bcm2835_ops, 140 .probe = bcm2835_gpio_probe, 141 .flags = DM_FLAG_PRE_RELOC, 142 .priv_auto_alloc_size = sizeof(struct bcm2835_gpios), 143 }; 144