1 /* 2 * Atmel PIO4 device driver 3 * 4 * Copyright (C) 2015 Atmel Corporation 5 * Wenyou.Yang <wenyou.yang@atmel.com> 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 #include <common.h> 10 #include <dm.h> 11 #include <asm/arch/hardware.h> 12 #include <mach/gpio.h> 13 #include <mach/atmel_pio4.h> 14 15 #define ATMEL_PIO4_PINS_PER_BANK 32 16 17 /* 18 * Register Field Definitions 19 */ 20 #define ATMEL_PIO4_CFGR_FUNC (0x7 << 0) 21 #define ATMEL_PIO4_CFGR_FUNC_GPIO (0x0 << 0) 22 #define ATMEL_PIO4_CFGR_FUNC_PERIPH_A (0x1 << 0) 23 #define ATMEL_PIO4_CFGR_FUNC_PERIPH_B (0x2 << 0) 24 #define ATMEL_PIO4_CFGR_FUNC_PERIPH_C (0x3 << 0) 25 #define ATMEL_PIO4_CFGR_FUNC_PERIPH_D (0x4 << 0) 26 #define ATMEL_PIO4_CFGR_FUNC_PERIPH_E (0x5 << 0) 27 #define ATMEL_PIO4_CFGR_FUNC_PERIPH_F (0x6 << 0) 28 #define ATMEL_PIO4_CFGR_FUNC_PERIPH_G (0x7 << 0) 29 #define ATMEL_PIO4_CFGR_DIR (0x1 << 8) 30 #define ATMEL_PIO4_CFGR_PUEN (0x1 << 9) 31 #define ATMEL_PIO4_CFGR_PDEN (0x1 << 10) 32 #define ATMEL_PIO4_CFGR_IFEN (0x1 << 12) 33 #define ATMEL_PIO4_CFGR_IFSCEN (0x1 << 13) 34 #define ATMEL_PIO4_CFGR_OPD (0x1 << 14) 35 #define ATMEL_PIO4_CFGR_SCHMITT (0x1 << 15) 36 #define ATMEL_PIO4_CFGR_DRVSTR (0x3 << 16) 37 #define ATMEL_PIO4_CFGR_DRVSTR_LOW0 (0x0 << 16) 38 #define ATMEL_PIO4_CFGR_DRVSTR_LOW1 (0x1 << 16) 39 #define ATMEL_PIO4_CFGR_DRVSTR_MEDIUM (0x2 << 16) 40 #define ATMEL_PIO4_CFGR_DRVSTR_HIGH (0x3 << 16) 41 #define ATMEL_PIO4_CFGR_EVTSEL (0x7 << 24) 42 #define ATMEL_PIO4_CFGR_EVTSEL_FALLING (0x0 << 24) 43 #define ATMEL_PIO4_CFGR_EVTSEL_RISING (0x1 << 24) 44 #define ATMEL_PIO4_CFGR_EVTSEL_BOTH (0x2 << 24) 45 #define ATMEL_PIO4_CFGR_EVTSEL_LOW (0x3 << 24) 46 #define ATMEL_PIO4_CFGR_EVTSEL_HIGH (0x4 << 24) 47 #define ATMEL_PIO4_CFGR_PCFS (0x1 << 29) 48 #define ATMEL_PIO4_CFGR_ICFS (0x1 << 30) 49 50 static struct atmel_pio4_port *atmel_pio4_port_base(u32 port) 51 { 52 struct atmel_pio4_port *base = NULL; 53 54 switch (port) { 55 case AT91_PIO_PORTA: 56 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOA; 57 break; 58 case AT91_PIO_PORTB: 59 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOB; 60 break; 61 case AT91_PIO_PORTC: 62 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOC; 63 break; 64 case AT91_PIO_PORTD: 65 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOD; 66 break; 67 default: 68 printf("Error: Atmel PIO4: Failed to get PIO base of port#%d!\n", 69 port); 70 break; 71 } 72 73 return base; 74 } 75 76 static int atmel_pio4_config_io_func(u32 port, u32 pin, 77 u32 func, u32 use_pullup) 78 { 79 struct atmel_pio4_port *port_base; 80 u32 reg, mask; 81 82 if (pin >= ATMEL_PIO4_PINS_PER_BANK) 83 return -ENODEV; 84 85 port_base = atmel_pio4_port_base(port); 86 if (!port_base) 87 return -ENODEV; 88 89 mask = 1 << pin; 90 reg = func; 91 reg |= use_pullup ? ATMEL_PIO4_CFGR_PUEN : 0; 92 93 writel(mask, &port_base->mskr); 94 writel(reg, &port_base->cfgr); 95 96 return 0; 97 } 98 99 int atmel_pio4_set_gpio(u32 port, u32 pin, u32 use_pullup) 100 { 101 return atmel_pio4_config_io_func(port, pin, 102 ATMEL_PIO4_CFGR_FUNC_GPIO, 103 use_pullup); 104 } 105 106 int atmel_pio4_set_a_periph(u32 port, u32 pin, u32 use_pullup) 107 { 108 return atmel_pio4_config_io_func(port, pin, 109 ATMEL_PIO4_CFGR_FUNC_PERIPH_A, 110 use_pullup); 111 } 112 113 int atmel_pio4_set_b_periph(u32 port, u32 pin, u32 use_pullup) 114 { 115 return atmel_pio4_config_io_func(port, pin, 116 ATMEL_PIO4_CFGR_FUNC_PERIPH_B, 117 use_pullup); 118 } 119 120 int atmel_pio4_set_c_periph(u32 port, u32 pin, u32 use_pullup) 121 { 122 return atmel_pio4_config_io_func(port, pin, 123 ATMEL_PIO4_CFGR_FUNC_PERIPH_C, 124 use_pullup); 125 } 126 127 int atmel_pio4_set_d_periph(u32 port, u32 pin, u32 use_pullup) 128 { 129 return atmel_pio4_config_io_func(port, pin, 130 ATMEL_PIO4_CFGR_FUNC_PERIPH_D, 131 use_pullup); 132 } 133 134 int atmel_pio4_set_e_periph(u32 port, u32 pin, u32 use_pullup) 135 { 136 return atmel_pio4_config_io_func(port, pin, 137 ATMEL_PIO4_CFGR_FUNC_PERIPH_E, 138 use_pullup); 139 } 140 141 int atmel_pio4_set_f_periph(u32 port, u32 pin, u32 use_pullup) 142 { 143 return atmel_pio4_config_io_func(port, pin, 144 ATMEL_PIO4_CFGR_FUNC_PERIPH_F, 145 use_pullup); 146 } 147 148 int atmel_pio4_set_g_periph(u32 port, u32 pin, u32 use_pullup) 149 { 150 return atmel_pio4_config_io_func(port, pin, 151 ATMEL_PIO4_CFGR_FUNC_PERIPH_G, 152 use_pullup); 153 } 154 155 int atmel_pio4_set_pio_output(u32 port, u32 pin, u32 value) 156 { 157 struct atmel_pio4_port *port_base; 158 u32 reg, mask; 159 160 if (pin >= ATMEL_PIO4_PINS_PER_BANK) 161 return -ENODEV; 162 163 port_base = atmel_pio4_port_base(port); 164 if (!port_base) 165 return -ENODEV; 166 167 mask = 0x01 << pin; 168 reg = ATMEL_PIO4_CFGR_FUNC_GPIO | ATMEL_PIO4_CFGR_DIR; 169 170 writel(mask, &port_base->mskr); 171 writel(reg, &port_base->cfgr); 172 173 if (value) 174 writel(mask, &port_base->sodr); 175 else 176 writel(mask, &port_base->codr); 177 178 return 0; 179 } 180 181 int atmel_pio4_get_pio_input(u32 port, u32 pin) 182 { 183 struct atmel_pio4_port *port_base; 184 u32 reg, mask; 185 186 if (pin >= ATMEL_PIO4_PINS_PER_BANK) 187 return -ENODEV; 188 189 port_base = atmel_pio4_port_base(port); 190 if (!port_base) 191 return -ENODEV; 192 193 mask = 0x01 << pin; 194 reg = ATMEL_PIO4_CFGR_FUNC_GPIO; 195 196 writel(mask, &port_base->mskr); 197 writel(reg, &port_base->cfgr); 198 199 return (readl(&port_base->pdsr) & mask) ? 1 : 0; 200 } 201 202 #ifdef CONFIG_DM_GPIO 203 static int atmel_pio4_direction_input(struct udevice *dev, unsigned offset) 204 { 205 struct at91_port_platdata *plat = dev_get_platdata(dev); 206 struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr; 207 u32 mask = 0x01 << offset; 208 u32 reg = ATMEL_PIO4_CFGR_FUNC_GPIO; 209 210 writel(mask, &port_base->mskr); 211 writel(reg, &port_base->cfgr); 212 213 return 0; 214 } 215 216 static int atmel_pio4_direction_output(struct udevice *dev, 217 unsigned offset, int value) 218 { 219 struct at91_port_platdata *plat = dev_get_platdata(dev); 220 struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr; 221 u32 mask = 0x01 << offset; 222 u32 reg = ATMEL_PIO4_CFGR_FUNC_GPIO | ATMEL_PIO4_CFGR_DIR; 223 224 writel(mask, &port_base->mskr); 225 writel(reg, &port_base->cfgr); 226 227 if (value) 228 writel(mask, &port_base->sodr); 229 else 230 writel(mask, &port_base->codr); 231 232 return 0; 233 } 234 235 static int atmel_pio4_get_value(struct udevice *dev, unsigned offset) 236 { 237 struct at91_port_platdata *plat = dev_get_platdata(dev); 238 struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr; 239 u32 mask = 0x01 << offset; 240 241 return (readl(&port_base->pdsr) & mask) ? 1 : 0; 242 } 243 244 static int atmel_pio4_set_value(struct udevice *dev, 245 unsigned offset, int value) 246 { 247 struct at91_port_platdata *plat = dev_get_platdata(dev); 248 struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr; 249 u32 mask = 0x01 << offset; 250 251 if (value) 252 writel(mask, &port_base->sodr); 253 else 254 writel(mask, &port_base->codr); 255 256 return 0; 257 } 258 259 static int atmel_pio4_get_function(struct udevice *dev, unsigned offset) 260 { 261 struct at91_port_platdata *plat = dev_get_platdata(dev); 262 struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr; 263 u32 mask = 0x01 << offset; 264 265 writel(mask, &port_base->mskr); 266 267 return (readl(&port_base->cfgr) & 268 ATMEL_PIO4_CFGR_DIR) ? GPIOF_OUTPUT : GPIOF_INPUT; 269 } 270 271 static const struct dm_gpio_ops atmel_pio4_ops = { 272 .direction_input = atmel_pio4_direction_input, 273 .direction_output = atmel_pio4_direction_output, 274 .get_value = atmel_pio4_get_value, 275 .set_value = atmel_pio4_set_value, 276 .get_function = atmel_pio4_get_function, 277 }; 278 279 static int atmel_pio4_probe(struct udevice *dev) 280 { 281 struct at91_port_platdata *plat = dev_get_platdata(dev); 282 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 283 284 uc_priv->bank_name = plat->bank_name; 285 uc_priv->gpio_count = ATMEL_PIO4_PINS_PER_BANK; 286 287 return 0; 288 } 289 290 U_BOOT_DRIVER(gpio_atmel_pio4) = { 291 .name = "gpio_atmel_pio4", 292 .id = UCLASS_GPIO, 293 .ops = &atmel_pio4_ops, 294 .probe = atmel_pio4_probe, 295 }; 296 #endif 297