1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2016 Nexell 4 * DeokJin, Lee <truevirtue@nexell.co.kr> 5 */ 6 7#include <common.h> 8#include <dm.h> 9#include <errno.h> 10#include <malloc.h> 11#include <asm/global_data.h> 12#include <asm/io.h> 13#include <asm/gpio.h> 14 15DECLARE_GLOBAL_DATA_PTR; 16 17struct nx_gpio_regs { 18 u32 data; /* Data register */ 19 u32 outputenb; /* Output Enable register */ 20 u32 detmode[2]; /* Detect Mode Register */ 21 u32 intenb; /* Interrupt Enable Register */ 22 u32 det; /* Event Detect Register */ 23 u32 pad; /* Pad Status Register */ 24}; 25 26struct nx_alive_gpio_regs { 27 u32 pwrgate; /* Power Gating Register */ 28 u32 reserved0[28]; /* Reserved0 */ 29 u32 outputenb_reset;/* Alive GPIO Output Enable Reset Register */ 30 u32 outputenb; /* Alive GPIO Output Enable Register */ 31 u32 outputenb_read; /* Alive GPIO Output Read Register */ 32 u32 reserved1[3]; /* Reserved1 */ 33 u32 pad_reset; /* Alive GPIO Output Reset Register */ 34 u32 data; /* Alive GPIO Output Register */ 35 u32 pad_read; /* Alive GPIO Pad Read Register */ 36 u32 reserved2[33]; /* Reserved2 */ 37 u32 pad; /* Alive GPIO Input Value Register */ 38}; 39 40struct nx_gpio_plat { 41 void *regs; 42 int gpio_count; 43 const char *bank_name; 44}; 45 46static int nx_alive_gpio_is_check(struct udevice *dev) 47{ 48 struct nx_gpio_plat *plat = dev_get_plat(dev); 49 const char *bank_name = plat->bank_name; 50 51 if (!strcmp(bank_name, "gpio_alv")) 52 return 1; 53 54 return 0; 55} 56 57static int nx_alive_gpio_direction_input(struct udevice *dev, unsigned int pin) 58{ 59 struct nx_gpio_plat *plat = dev_get_plat(dev); 60 struct nx_alive_gpio_regs *const regs = plat->regs; 61 62 setbits_le32(®s->outputenb_reset, 1 << pin); 63 64 return 0; 65} 66 67static int nx_alive_gpio_direction_output(struct udevice *dev, unsigned int pin, 68 int val) 69{ 70 struct nx_gpio_plat *plat = dev_get_plat(dev); 71 struct nx_alive_gpio_regs *const regs = plat->regs; 72 73 if (val) 74 setbits_le32(®s->data, 1 << pin); 75 else 76 setbits_le32(®s->pad_reset, 1 << pin); 77 78 setbits_le32(®s->outputenb, 1 << pin); 79 80 return 0; 81} 82 83static int nx_alive_gpio_get_value(struct udevice *dev, unsigned int pin) 84{ 85 struct nx_gpio_plat *plat = dev_get_plat(dev); 86 struct nx_alive_gpio_regs *const regs = plat->regs; 87 unsigned int mask = 1UL << pin; 88 unsigned int value; 89 90 value = (readl(®s->pad_read) & mask) >> pin; 91 92 return value; 93} 94 95static int nx_alive_gpio_set_value(struct udevice *dev, unsigned int pin, 96 int val) 97{ 98 struct nx_gpio_plat *plat = dev_get_plat(dev); 99 struct nx_alive_gpio_regs *const regs = plat->regs; 100 101 if (val) 102 setbits_le32(®s->data, 1 << pin); 103 else 104 clrbits_le32(®s->pad_reset, 1 << pin); 105 106 return 0; 107} 108 109static int nx_alive_gpio_get_function(struct udevice *dev, unsigned int pin) 110{ 111 struct nx_gpio_plat *plat = dev_get_plat(dev); 112 struct nx_alive_gpio_regs *const regs = plat->regs; 113 unsigned int mask = (1UL << pin); 114 unsigned int output; 115 116 output = readl(®s->outputenb_read) & mask; 117 118 if (output) 119 return GPIOF_OUTPUT; 120 else 121 return GPIOF_INPUT; 122} 123 124static int nx_gpio_direction_input(struct udevice *dev, unsigned int pin) 125{ 126 struct nx_gpio_plat *plat = dev_get_plat(dev); 127 struct nx_gpio_regs *const regs = plat->regs; 128 129 if (nx_alive_gpio_is_check(dev)) 130 return nx_alive_gpio_direction_input(dev, pin); 131 132 clrbits_le32(®s->outputenb, 1 << pin); 133 134 return 0; 135} 136 137static int nx_gpio_direction_output(struct udevice *dev, unsigned int pin, 138 int val) 139{ 140 struct nx_gpio_plat *plat = dev_get_plat(dev); 141 struct nx_gpio_regs *const regs = plat->regs; 142 143 if (nx_alive_gpio_is_check(dev)) 144 return nx_alive_gpio_direction_output(dev, pin, val); 145 146 if (val) 147 setbits_le32(®s->data, 1 << pin); 148 else 149 clrbits_le32(®s->data, 1 << pin); 150 151 setbits_le32(®s->outputenb, 1 << pin); 152 153 return 0; 154} 155 156static int nx_gpio_get_value(struct udevice *dev, unsigned int pin) 157{ 158 struct nx_gpio_plat *plat = dev_get_plat(dev); 159 struct nx_gpio_regs *const regs = plat->regs; 160 unsigned int mask = 1UL << pin; 161 unsigned int value; 162 163 if (nx_alive_gpio_is_check(dev)) 164 return nx_alive_gpio_get_value(dev, pin); 165 166 value = (readl(®s->pad) & mask) >> pin; 167 168 return value; 169} 170 171static int nx_gpio_set_value(struct udevice *dev, unsigned int pin, int val) 172{ 173 struct nx_gpio_plat *plat = dev_get_plat(dev); 174 struct nx_gpio_regs *const regs = plat->regs; 175 176 if (nx_alive_gpio_is_check(dev)) 177 return nx_alive_gpio_set_value(dev, pin, val); 178 179 if (val) 180 setbits_le32(®s->data, 1 << pin); 181 else 182 clrbits_le32(®s->data, 1 << pin); 183 184 return 0; 185} 186 187static int nx_gpio_get_function(struct udevice *dev, unsigned int pin) 188{ 189 struct nx_gpio_plat *plat = dev_get_plat(dev); 190 struct nx_gpio_regs *const regs = plat->regs; 191 unsigned int mask = (1UL << pin); 192 unsigned int output; 193 194 if (nx_alive_gpio_is_check(dev)) 195 return nx_alive_gpio_get_function(dev, pin); 196 197 output = readl(®s->outputenb) & mask; 198 199 if (output) 200 return GPIOF_OUTPUT; 201 else 202 return GPIOF_INPUT; 203} 204 205static int nx_gpio_probe(struct udevice *dev) 206{ 207 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 208 struct nx_gpio_plat *plat = dev_get_plat(dev); 209 210 uc_priv->gpio_count = plat->gpio_count; 211 uc_priv->bank_name = plat->bank_name; 212 213 return 0; 214} 215 216static int nx_gpio_of_to_plat(struct udevice *dev) 217{ 218 struct nx_gpio_plat *plat = dev_get_plat(dev); 219 220 plat->regs = map_physmem(devfdt_get_addr(dev), 221 sizeof(struct nx_gpio_regs), 222 MAP_NOCACHE); 223 plat->gpio_count = dev_read_s32_default(dev, "nexell,gpio-bank-width", 224 32); 225 plat->bank_name = dev_read_string(dev, "gpio-bank-name"); 226 227 return 0; 228} 229 230static const struct dm_gpio_ops nx_gpio_ops = { 231 .direction_input = nx_gpio_direction_input, 232 .direction_output = nx_gpio_direction_output, 233 .get_value = nx_gpio_get_value, 234 .set_value = nx_gpio_set_value, 235 .get_function = nx_gpio_get_function, 236}; 237 238static const struct udevice_id nx_gpio_ids[] = { 239 { .compatible = "nexell,nexell-gpio" }, 240 { } 241}; 242 243U_BOOT_DRIVER(nx_gpio) = { 244 .name = "nx_gpio", 245 .id = UCLASS_GPIO, 246 .of_match = nx_gpio_ids, 247 .ops = &nx_gpio_ops, 248 .of_to_plat = nx_gpio_of_to_plat, 249 .plat_auto = sizeof(struct nx_gpio_plat), 250 .probe = nx_gpio_probe, 251}; 252