1 /* $NetBSD: exynos_gpio.c,v 1.33 2022/02/11 23:48:50 riastradh Exp $ */ 2 3 /*- 4 * Copyright (c) 2014, 2020 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Reinoud Zandijk, and by Nick Hudson 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "opt_exynos.h" 33 #include "opt_arm_debug.h" 34 #include "gpio.h" 35 36 #include <sys/cdefs.h> 37 __KERNEL_RCSID(1, "$NetBSD: exynos_gpio.c,v 1.33 2022/02/11 23:48:50 riastradh Exp $"); 38 39 #include <sys/param.h> 40 #include <sys/bus.h> 41 #include <sys/device.h> 42 #include <sys/intr.h> 43 #include <sys/systm.h> 44 #include <sys/kmem.h> 45 #include <sys/gpio.h> 46 47 #include <dev/gpio/gpiovar.h> 48 49 #include <arm/samsung/exynos_reg.h> 50 #include <arm/samsung/exynos_var.h> 51 #include <arm/samsung/exynos_intr.h> 52 #include <arm/samsung/exynos_pinctrl.h> 53 54 #include <dev/fdt/fdtvar.h> 55 56 struct exynos_gpio_bank { 57 const char bank_name[6]; 58 device_t bank_dev; 59 struct gpio_chipset_tag bank_gc; 60 struct exynos_gpio_softc *bank_sc; 61 gpio_pin_t bank_pins[8]; 62 63 const bus_addr_t bank_core_offset; 64 const uint8_t bank_bits; 65 66 struct exynos_gpio_pin_cfg bank_cfg; 67 }; 68 69 struct exynos_gpio_pin { 70 struct exynos_gpio_softc *pin_sc; 71 int pin_no; 72 u_int pin_flags; 73 int pin_actlo; 74 const struct exynos_gpio_bank *pin_bank; 75 }; 76 77 78 //#define GPIO_REG(v,s,o) (EXYNOS##v##_GPIO_##s##_OFFSET + (o)) 79 #define GPIO_REG(v,s,o) ((o)) 80 #define GPIO_GRP(v, s, o, n, b) \ 81 { \ 82 .bank_name = #n, \ 83 .bank_core_offset = GPIO_REG(v,s,o), \ 84 .bank_bits = b, \ 85 } 86 87 #define GPIO_GRP_INTR(o, n, b, i) \ 88 { \ 89 .bank_name = #n, \ 90 .bank_core_offset = GPIO_REG(v,s,o), \ 91 .bank_bits = b, \ 92 } 93 94 #define GPIO_GRP_NONE(o, n, b) \ 95 { \ 96 .bank_name = #n, \ 97 .bank_core_offset = GPIO_REG(v,s,o), \ 98 .bank_bits = b, \ 99 } 100 101 #define GPIO_GRP_WAKEUP(o, n, b, i) \ 102 { \ 103 .bank_name = #n, \ 104 .bank_core_offset = GPIO_REG(v,s,o), \ 105 .bank_bits = b, \ 106 } 107 108 109 110 static struct exynos_gpio_bank exynos5420_banks[] = { 111 GPIO_GRP(5, MUXA, 0x0000, gpy7, 8), 112 GPIO_GRP(5, MUXA, 0x0C00, gpx0, 8), 113 GPIO_GRP(5, MUXA, 0x0C20, gpx1, 8), 114 GPIO_GRP(5, MUXA, 0x0C40, gpx2, 8), 115 GPIO_GRP(5, MUXA, 0x0C60, gpx3, 8), 116 117 GPIO_GRP(5, MUXB, 0x0000, gpc0, 8), 118 GPIO_GRP(5, MUXB, 0x0020, gpc1, 8), 119 GPIO_GRP(5, MUXB, 0x0040, gpc2, 7), 120 GPIO_GRP(5, MUXB, 0x0060, gpc3, 4), 121 GPIO_GRP(5, MUXB, 0x0080, gpc4, 2), 122 GPIO_GRP(5, MUXB, 0x00A0, gpd1, 8), 123 GPIO_GRP(5, MUXB, 0x00C0, gpy0, 6), 124 GPIO_GRP(5, MUXB, 0x00E0, gpy1, 4), 125 GPIO_GRP(5, MUXB, 0x0100, gpy2, 6), 126 GPIO_GRP(5, MUXB, 0x0120, gpy3, 8), 127 GPIO_GRP(5, MUXB, 0x0140, gpy4, 8), 128 GPIO_GRP(5, MUXB, 0x0160, gpy5, 8), 129 GPIO_GRP(5, MUXB, 0x0180, gpy6, 8), 130 131 GPIO_GRP(5, MUXC, 0x0000, gpe0, 8), 132 GPIO_GRP(5, MUXC, 0x0020, gpe1, 2), 133 GPIO_GRP(5, MUXC, 0x0040, gpf0, 6), 134 GPIO_GRP(5, MUXC, 0x0060, gpf1, 8), 135 GPIO_GRP(5, MUXC, 0x0080, gpg0, 8), 136 GPIO_GRP(5, MUXC, 0x00A0, gpg1, 8), 137 GPIO_GRP(5, MUXC, 0x00C0, gpg2, 2), 138 GPIO_GRP(5, MUXC, 0x00E0, gpj4, 4), 139 140 GPIO_GRP(5, MUXD, 0x0000, gpa0, 8), 141 GPIO_GRP(5, MUXD, 0x0020, gpa1, 6), 142 GPIO_GRP(5, MUXD, 0x0040, gpa2, 8), 143 GPIO_GRP(5, MUXD, 0x0060, gpb0, 5), 144 GPIO_GRP(5, MUXD, 0x0080, gpb1, 5), 145 GPIO_GRP(5, MUXD, 0x00A0, gpb2, 4), 146 GPIO_GRP(5, MUXD, 0x00C0, gpb3, 8), 147 GPIO_GRP(5, MUXD, 0x00E0, gpb4, 2), 148 GPIO_GRP(5, MUXD, 0x0100, gph0, 4), 149 150 GPIO_GRP(5, MUXE, 0x0000, gpz, 7), 151 }; 152 153 struct exynos_pinctrl_banks exynos5420_pinctrl_banks = { 154 .epb_banks = exynos5420_banks, 155 .epb_nbanks = __arraycount(exynos5420_banks) 156 }; 157 158 static struct exynos_gpio_bank exynos5410_banks[] = { 159 /* pin-controller 0 */ 160 GPIO_GRP_INTR(0x000, gpa0, 8, 0x00), 161 GPIO_GRP_INTR(0x020, gpa1, 6, 0x04), 162 GPIO_GRP_INTR(0x040, gpa2, 8, 0x08), 163 GPIO_GRP_INTR(0x060, gpb0, 5, 0x0c), 164 GPIO_GRP_INTR(0x080, gpb1, 5, 0x10), 165 GPIO_GRP_INTR(0x0A0, gpb2, 4, 0x14), 166 GPIO_GRP_INTR(0x0C0, gpb3, 4, 0x18), 167 GPIO_GRP_INTR(0x0E0, gpc0, 7, 0x1c), 168 GPIO_GRP_INTR(0x100, gpc3, 4, 0x20), 169 GPIO_GRP_INTR(0x120, gpc1, 7, 0x24), 170 GPIO_GRP_INTR(0x140, gpc2, 7, 0x28), 171 GPIO_GRP_INTR(0x180, gpd1, 8, 0x2c), 172 GPIO_GRP_INTR(0x1A0, gpe0, 8, 0x30), 173 GPIO_GRP_INTR(0x1C0, gpe1, 2, 0x34), 174 GPIO_GRP_INTR(0x1E0, gpf0, 6, 0x38), 175 GPIO_GRP_INTR(0x200, gpf1, 8, 0x3c), 176 GPIO_GRP_INTR(0x220, gpg0, 8, 0x40), 177 GPIO_GRP_INTR(0x240, gpg1, 8, 0x44), 178 GPIO_GRP_INTR(0x260, gpg2, 2, 0x48), 179 GPIO_GRP_INTR(0x280, gph0, 4, 0x4c), 180 GPIO_GRP_INTR(0x2A0, gph1, 8, 0x50), 181 GPIO_GRP_NONE(0x160, gpm5, 2), 182 GPIO_GRP_NONE(0x2C0, gpm7, 8), 183 GPIO_GRP_NONE(0x2E0, gpy0, 6), 184 GPIO_GRP_NONE(0x300, gpy1, 4), 185 GPIO_GRP_NONE(0x320, gpy2, 6), 186 GPIO_GRP_NONE(0x340, gpy3, 8), 187 GPIO_GRP_NONE(0x360, gpy4, 8), 188 GPIO_GRP_NONE(0x380, gpy5, 8), 189 GPIO_GRP_NONE(0x3A0, gpy6, 8), 190 GPIO_GRP_NONE(0x3C0, gpy7, 8), 191 GPIO_GRP_WAKEUP(0xC00, gpx0, 8, 0x00), 192 GPIO_GRP_WAKEUP(0xC20, gpx1, 8, 0x04), 193 GPIO_GRP_WAKEUP(0xC40, gpx2, 8, 0x08), 194 GPIO_GRP_WAKEUP(0xC60, gpx3, 8, 0x0c), 195 196 /* pin-controller 1 */ 197 GPIO_GRP_INTR(0x000, gpj0, 5, 0x00), 198 GPIO_GRP_INTR(0x020, gpj1, 8, 0x04), 199 GPIO_GRP_INTR(0x040, gpj2, 8, 0x08), 200 GPIO_GRP_INTR(0x060, gpj3, 8, 0x0c), 201 GPIO_GRP_INTR(0x080, gpj4, 2, 0x10), 202 GPIO_GRP_INTR(0x0A0, gpk0, 8, 0x14), 203 GPIO_GRP_INTR(0x0C0, gpk1, 8, 0x18), 204 GPIO_GRP_INTR(0x0E0, gpk2, 8, 0x1c), 205 GPIO_GRP_INTR(0x100, gpk3, 7, 0x20), 206 207 /* pin-controller 2 */ 208 GPIO_GRP_INTR(0x000, gpv0, 8, 0x00), 209 GPIO_GRP_INTR(0x020, gpv1, 8, 0x04), 210 GPIO_GRP_INTR(0x060, gpv2, 8, 0x08), 211 GPIO_GRP_INTR(0x080, gpv3, 8, 0x0c), 212 GPIO_GRP_INTR(0x0C0, gpv4, 2, 0x10), 213 214 /* pin-controller 2 */ 215 GPIO_GRP_INTR(0x000, gpz, 7, 0x00), 216 }; 217 218 struct exynos_pinctrl_banks exynos5410_pinctrl_banks = { 219 .epb_banks = exynos5410_banks, 220 .epb_nbanks = __arraycount(exynos5410_banks) 221 }; 222 223 224 static int exynos_gpio_pin_read(void *, int); 225 static void exynos_gpio_pin_write(void *, int, int); 226 static void exynos_gpio_pin_ctl(void *, int, int); 227 static void *exynos_gpio_fdt_acquire(device_t, const void *, 228 size_t, int); 229 static void exynos_gpio_fdt_release(device_t, void *); 230 231 static int exynos_gpio_fdt_read(device_t, void *, bool); 232 static void exynos_gpio_fdt_write(device_t, void *, int, bool); 233 static int exynos_gpio_cfprint(void *, const char *); 234 235 struct fdtbus_gpio_controller_func exynos_gpio_funcs = { 236 .acquire = exynos_gpio_fdt_acquire, 237 .release = exynos_gpio_fdt_release, 238 .read = exynos_gpio_fdt_read, 239 .write = exynos_gpio_fdt_write 240 }; 241 #define GPIO_WRITE(bank, reg, val) \ 242 bus_space_write_4((bank)->bank_sc->sc_bst, \ 243 (bank)->bank_sc->sc_bsh, \ 244 (bank)->bank_core_offset + (reg), (val)) 245 #define GPIO_READ(bank, reg) \ 246 bus_space_read_4((bank)->bank_sc->sc_bst, \ 247 (bank)->bank_sc->sc_bsh, \ 248 (bank)->bank_core_offset + (reg)) 249 250 static int 251 exynos_gpio_cfprint(void *priv, const char *pnp) 252 { 253 struct gpiobus_attach_args *gba = priv; 254 struct exynos_gpio_bank *bank = gba->gba_gc->gp_cookie; 255 const char *bankname = bank->bank_name; 256 257 if (pnp) 258 aprint_normal("gpiobus at %s", pnp); 259 260 aprint_normal(" (%s)", bankname); 261 262 return UNCONF; 263 } 264 265 static int 266 exynos_gpio_pin_read(void *cookie, int pin) 267 { 268 struct exynos_gpio_bank * const bank = cookie; 269 uint8_t val; 270 271 KASSERT(pin < bank->bank_bits); 272 val = bus_space_read_1(bank->bank_sc->sc_bst, bank->bank_sc->sc_bsh, 273 EXYNOS_GPIO_DAT); 274 275 return __SHIFTOUT(val, __BIT(pin)); 276 } 277 278 static void 279 exynos_gpio_pin_write(void *cookie, int pin, int value) 280 { 281 struct exynos_gpio_bank * const bank = cookie; 282 int val; 283 284 KASSERT(pin < bank->bank_bits); 285 val = bus_space_read_1(bank->bank_sc->sc_bst, bank->bank_sc->sc_bsh, 286 EXYNOS_GPIO_DAT); 287 val &= ~__BIT(pin); 288 if (value) 289 val |= __BIT(pin); 290 bus_space_write_1(bank->bank_sc->sc_bst, bank->bank_sc->sc_bsh, 291 EXYNOS_GPIO_DAT, val); 292 } 293 294 static void 295 exynos_gpio_pin_ctl(void *cookie, int pin, int flags) 296 { 297 struct exynos_gpio_bank * const bank = cookie; 298 struct exynos_gpio_pin_cfg ncfg = { 0 }; 299 300 /* honour pullup requests */ 301 if (flags & GPIO_PIN_PULLUP) { 302 ncfg.pud = EXYNOS_GPIO_PIN_PULL_UP; 303 ncfg.pud_valid = true; 304 } 305 if (flags & GPIO_PIN_PULLDOWN) { 306 ncfg.pud = EXYNOS_GPIO_PIN_PULL_DOWN; 307 ncfg.pud_valid = true; 308 } 309 310 /* honour i/o */ 311 if (flags & GPIO_PIN_INPUT) { 312 ncfg.cfg = EXYNOS_GPIO_FUNC_INPUT; 313 ncfg.cfg_valid = true; 314 } else if (flags & GPIO_PIN_OUTPUT) { 315 ncfg.cfg = EXYNOS_GPIO_FUNC_OUTPUT; 316 ncfg.cfg_valid = true; 317 } 318 319 /* update any config registers that changed */ 320 exynos_gpio_pin_ctl_write(bank, &ncfg, pin); 321 } 322 323 void exynos_gpio_pin_ctl_write(const struct exynos_gpio_bank *bank, 324 const struct exynos_gpio_pin_cfg *cfg, 325 int pin) 326 { 327 uint32_t val; 328 329 if (cfg->cfg_valid) { 330 val = GPIO_READ(bank, EXYNOS_GPIO_CON); 331 val &= ~(0xf << (pin * 4)); 332 val |= (cfg->cfg << (pin * 4)); 333 GPIO_WRITE(bank, EXYNOS_GPIO_CON, val); 334 } 335 336 if (cfg->pud_valid) { 337 val = GPIO_READ(bank, EXYNOS_GPIO_PUD); 338 val &= ~(0x3 << (pin * 2)); 339 val |= (cfg->pud << (pin * 2)); 340 GPIO_WRITE(bank, EXYNOS_GPIO_PUD, val); 341 } 342 343 if (cfg->drv_valid) { 344 val = GPIO_READ(bank, EXYNOS_GPIO_DRV); 345 val &= ~(0x3 << (pin * 2)); 346 val |= (cfg->drv << (pin * 2)); 347 GPIO_WRITE(bank, EXYNOS_GPIO_DRV, val); 348 } 349 350 if (cfg->conpwd_valid) { 351 val = GPIO_READ(bank, EXYNOS_GPIO_CONPWD); 352 val &= ~(0x3 << (pin * 2)); 353 val |= (cfg->conpwd << (pin * 2)); 354 GPIO_WRITE(bank, EXYNOS_GPIO_CONPWD, val); 355 } 356 357 if (cfg->pudpwd_valid) { 358 val = GPIO_READ(bank, EXYNOS_GPIO_PUDPWD); 359 val &= ~(0x3 << (pin * 2)); 360 val |= (cfg->pudpwd << (pin * 2)); 361 GPIO_WRITE(bank, EXYNOS_GPIO_PUDPWD, val); 362 } 363 } 364 365 struct exynos_gpio_softc * 366 exynos_gpio_bank_config(struct exynos_pinctrl_softc * parent, 367 const struct fdt_attach_args *faa, int node) 368 { 369 struct exynos_gpio_softc *sc = kmem_zalloc(sizeof(*sc), KM_SLEEP); 370 struct gpiobus_attach_args gba; 371 struct gpio_chipset_tag *gc_tag; 372 char result[64]; 373 374 OF_getprop(node, "name", result, sizeof(result)); 375 struct exynos_gpio_bank *bank = 376 exynos_gpio_bank_lookup(parent->sc_epb, result); 377 if (bank == NULL) { 378 aprint_error_dev(parent->sc_dev, "no bank found for %s\n", 379 result); 380 return NULL; 381 } 382 383 sc->sc_dev = parent->sc_dev; 384 sc->sc_bst = &armv7_generic_bs_tag; 385 sc->sc_bsh = parent->sc_bsh; 386 sc->sc_bank = bank; 387 388 gc_tag = &bank->bank_gc; 389 gc_tag->gp_cookie = bank; 390 gc_tag->gp_pin_read = exynos_gpio_pin_read; 391 gc_tag->gp_pin_write = exynos_gpio_pin_write; 392 gc_tag->gp_pin_ctl = exynos_gpio_pin_ctl; 393 memset(&gba, 0, sizeof(gba)); 394 gba.gba_gc = &bank->bank_gc; 395 gba.gba_pins = bank->bank_pins; 396 gba.gba_npins = bank->bank_bits; 397 398 bank->bank_sc = sc; 399 bank->bank_dev = 400 config_found(parent->sc_dev, &gba, exynos_gpio_cfprint, CFARGS_NONE); 401 402 /* read in our initial settings */ 403 bank->bank_cfg.cfg = GPIO_READ(bank, EXYNOS_GPIO_CON); 404 bank->bank_cfg.pud = GPIO_READ(bank, EXYNOS_GPIO_PUD); 405 bank->bank_cfg.drv = GPIO_READ(bank, EXYNOS_GPIO_DRV); 406 bank->bank_cfg.conpwd = GPIO_READ(bank, EXYNOS_GPIO_CONPWD); 407 bank->bank_cfg.pudpwd = GPIO_READ(bank, EXYNOS_GPIO_PUDPWD); 408 409 fdtbus_register_gpio_controller(bank->bank_dev, node, 410 &exynos_gpio_funcs); 411 return sc; 412 } 413 414 /* 415 * This function is a bit funky. Given a string that may look like 416 * 'gpAN' or 'gpAN-P' it is meant to find a match to the part before 417 * the '-', or the four character string if the dash is not present. 418 */ 419 struct exynos_gpio_bank * 420 exynos_gpio_bank_lookup(const struct exynos_pinctrl_banks *epb, 421 const char *name) 422 { 423 struct exynos_gpio_bank *bank; 424 425 for (u_int n = 0; n < epb->epb_nbanks; n++) { 426 bank = &epb->epb_banks[n]; 427 if (!strncmp(bank->bank_name, name, 428 strlen(bank->bank_name))) { 429 return bank; 430 } 431 } 432 433 return NULL; 434 } 435 436 #if notyet 437 static int 438 exynos_gpio_pin_lookup(const char *name) 439 { 440 char *p; 441 442 p = strchr(name, '-'); 443 if (p == NULL || p[1] < '0' || p[1] > '9') 444 return -1; 445 446 return p[1] - '0'; 447 } 448 #endif 449 450 static void * 451 exynos_gpio_fdt_acquire(device_t dev, const void *data, size_t len, int flags) 452 { 453 device_t parent = device_parent(dev); 454 struct exynos_pinctrl_softc *sc = device_private(parent); 455 const struct exynos_pinctrl_banks *epb = sc->sc_epb; 456 struct exynos_gpio_bank *bank = NULL; 457 struct exynos_gpio_pin *gpin; 458 u_int n; 459 460 KASSERT(device_is_a(parent, "exyopctl")); 461 462 if (len != 12) 463 return NULL; 464 465 const u_int *cells = data; 466 const int pin = be32toh(cells[1]) & 0x0f; 467 const int actlo = be32toh(cells[2]) & 0x01; 468 469 for (n = 0; n < epb->epb_nbanks; n++) { 470 if (epb->epb_banks[n].bank_dev == dev) { 471 bank = &epb->epb_banks[n]; 472 break; 473 } 474 } 475 KASSERTMSG(bank != NULL, "no such gpio bank child of %s @ %p: %s @ %p", 476 device_xname(parent), parent, device_xname(dev), dev); 477 478 gpin = kmem_alloc(sizeof(*gpin), KM_SLEEP); 479 gpin->pin_sc = bank->bank_sc; 480 gpin->pin_bank = bank; 481 gpin->pin_no = pin; 482 gpin->pin_flags = flags; 483 gpin->pin_actlo = actlo; 484 485 exynos_gpio_pin_ctl(bank, gpin->pin_no, gpin->pin_flags); 486 487 return gpin; 488 } 489 490 static void 491 exynos_gpio_fdt_release(device_t dev, void *priv) 492 { 493 struct exynos_gpio_pin *gpin = priv; 494 495 kmem_free(gpin, sizeof(*gpin)); 496 } 497 498 static int 499 exynos_gpio_fdt_read(device_t dev, void *priv, bool raw) 500 { 501 struct exynos_gpio_pin *gpin = priv; 502 int val; 503 504 val = (bus_space_read_1(gpin->pin_sc->sc_bst, 505 gpin->pin_sc->sc_bsh, 506 EXYNOS_GPIO_DAT) >> gpin->pin_no) & 1; 507 508 if (!raw && gpin->pin_actlo) 509 val = !val; 510 511 return val; 512 } 513 514 static void 515 exynos_gpio_fdt_write(device_t dev, void *priv, int val, bool raw) 516 { 517 struct exynos_gpio_pin *gpin = priv; 518 519 if (!raw && gpin->pin_actlo) 520 val = !val; 521 522 val = bus_space_read_1(gpin->pin_sc->sc_bst, 523 gpin->pin_sc->sc_bsh, 524 EXYNOS_GPIO_DAT); 525 val &= ~__BIT(gpin->pin_no); 526 if (val) 527 val |= __BIT(gpin->pin_no); 528 bus_space_write_1(gpin->pin_sc->sc_bst, 529 gpin->pin_sc->sc_bsh, 530 EXYNOS_GPIO_DAT, val); 531 532 } 533