diff options
| -rw-r--r-- | drivers/gpio/gpio-tegra186.c | 472 |
1 files changed, 239 insertions, 233 deletions
diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index ca696635a..08c8734a4 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c | |||
| @@ -89,27 +89,6 @@ | |||
| 89 | #define GPIO_PORT(g) ((g) >> 3) | 89 | #define GPIO_PORT(g) ((g) >> 3) |
| 90 | #define GPIO_PIN(g) ((g) & 0x7) | 90 | #define GPIO_PIN(g) ((g) & 0x7) |
| 91 | 91 | ||
| 92 | struct tegra_gpio_controller { | ||
| 93 | int controller; | ||
| 94 | int irq; | ||
| 95 | u32 cnf[MAX_PORTS * MAX_PINS_PER_PORT]; | ||
| 96 | u32 dbc[MAX_PORTS * MAX_PINS_PER_PORT]; | ||
| 97 | u32 out_ctrl[MAX_PORTS * MAX_PINS_PER_PORT]; | ||
| 98 | u32 out_val[MAX_PORTS * MAX_PINS_PER_PORT]; | ||
| 99 | }; | ||
| 100 | |||
| 101 | struct tegra_gpio { | ||
| 102 | struct device *dev; | ||
| 103 | const struct tegra_pinctrl_soc_data *soc; | ||
| 104 | |||
| 105 | int nbanks; | ||
| 106 | void __iomem **regs; | ||
| 107 | int *regs_size; | ||
| 108 | unsigned int *reg_base; | ||
| 109 | }; | ||
| 110 | |||
| 111 | static struct tegra_gpio *tegra_gpio; | ||
| 112 | |||
| 113 | static int tegra186_gpio_wakes[] = { | 92 | static int tegra186_gpio_wakes[] = { |
| 114 | TEGRA_GPIO(A, 6), /* wake0 */ | 93 | TEGRA_GPIO(A, 6), /* wake0 */ |
| 115 | TEGRA_GPIO(A, 2), /* wake1 */ | 94 | TEGRA_GPIO(A, 2), /* wake1 */ |
| @@ -218,6 +197,27 @@ struct tegra_gpio_port_chip_info { | |||
| 218 | u32 reg_offset; | 197 | u32 reg_offset; |
| 219 | }; | 198 | }; |
| 220 | 199 | ||
| 200 | struct tegra_gpio_info; | ||
| 201 | |||
| 202 | struct tegra_gpio_controller { | ||
| 203 | int controller; | ||
| 204 | int irq; | ||
| 205 | struct tegra_gpio_info *tgi; | ||
| 206 | }; | ||
| 207 | |||
| 208 | struct tegra_gpio_info { | ||
| 209 | struct device *dev; | ||
| 210 | |||
| 211 | int nbanks; | ||
| 212 | void __iomem **regs; | ||
| 213 | struct irq_domain *irq_domain; | ||
| 214 | int tegra_gpio_bank_count; | ||
| 215 | struct tegra_gpio_controller tg_contrlr[MAX_GPIO_CONTROLLERS]; | ||
| 216 | struct gpio_chip gc; | ||
| 217 | struct irq_chip ic; | ||
| 218 | struct lock_class_key lock_class; | ||
| 219 | }; | ||
| 220 | |||
| 221 | #define TEGRA_GPIO_PORT_INFO(port, cid, cind, npins) \ | 221 | #define TEGRA_GPIO_PORT_INFO(port, cid, cind, npins) \ |
| 222 | [TEGRA_GPIO_BANK_ID_##port] = { \ | 222 | [TEGRA_GPIO_BANK_ID_##port] = { \ |
| 223 | .cont_id = cid, \ | 223 | .cont_id = cid, \ |
| @@ -273,12 +273,6 @@ static struct tegra_gpio_port_chip_info tegra_gpio_cinfo[] = { | |||
| 273 | TEGRA_AON_GPIO_PORT_INFO(FF, 6, 0, 5), | 273 | TEGRA_AON_GPIO_PORT_INFO(FF, 6, 0, 5), |
| 274 | }; | 274 | }; |
| 275 | 275 | ||
| 276 | static u32 tegra_gpio_bank_count; | ||
| 277 | static struct tegra_gpio_controller | ||
| 278 | tegra_gpio_controllers[MAX_GPIO_CONTROLLERS]; | ||
| 279 | |||
| 280 | static struct irq_domain *irq_domain; | ||
| 281 | |||
| 282 | static int tegra186_gpio_to_wake(int gpio) | 276 | static int tegra186_gpio_to_wake(int gpio) |
| 283 | { | 277 | { |
| 284 | int i; | 278 | int i; |
| @@ -293,7 +287,8 @@ static int tegra186_gpio_to_wake(int gpio) | |||
| 293 | return -EINVAL; | 287 | return -EINVAL; |
| 294 | } | 288 | } |
| 295 | 289 | ||
| 296 | static inline u32 tegra_gpio_readl(u32 gpio, u32 reg_offset) | 290 | static inline u32 tegra_gpio_readl(struct tegra_gpio_info *tgi, u32 gpio, |
| 291 | u32 reg_offset) | ||
| 297 | { | 292 | { |
| 298 | int port = GPIO_PORT(gpio); | 293 | int port = GPIO_PORT(gpio); |
| 299 | int pin = GPIO_PIN(gpio); | 294 | int pin = GPIO_PIN(gpio); |
| @@ -301,10 +296,11 @@ static inline u32 tegra_gpio_readl(u32 gpio, u32 reg_offset) | |||
| 301 | int rindex = tegra_gpio_cinfo[port].reg_index; | 296 | int rindex = tegra_gpio_cinfo[port].reg_index; |
| 302 | 297 | ||
| 303 | addr += (GPIO_REG_DIFF * pin) + reg_offset; | 298 | addr += (GPIO_REG_DIFF * pin) + reg_offset; |
| 304 | return __raw_readl(tegra_gpio->regs[rindex] + addr); | 299 | return __raw_readl(tgi->regs[rindex] + addr); |
| 305 | } | 300 | } |
| 306 | 301 | ||
| 307 | static inline void tegra_gpio_writel(u32 val, u32 gpio, u32 reg_offset) | 302 | static inline void tegra_gpio_writel(struct tegra_gpio_info *tgi, u32 val, |
| 303 | u32 gpio, u32 reg_offset) | ||
| 308 | { | 304 | { |
| 309 | int port = GPIO_PORT(gpio); | 305 | int port = GPIO_PORT(gpio); |
| 310 | int pin = GPIO_PIN(gpio); | 306 | int pin = GPIO_PIN(gpio); |
| @@ -312,11 +308,11 @@ static inline void tegra_gpio_writel(u32 val, u32 gpio, u32 reg_offset) | |||
| 312 | int rindex = tegra_gpio_cinfo[port].reg_index; | 308 | int rindex = tegra_gpio_cinfo[port].reg_index; |
| 313 | 309 | ||
| 314 | addr += (GPIO_REG_DIFF * pin) + reg_offset; | 310 | addr += (GPIO_REG_DIFF * pin) + reg_offset; |
| 315 | __raw_writel(val, tegra_gpio->regs[rindex] + addr); | 311 | __raw_writel(val, tgi->regs[rindex] + addr); |
| 316 | } | 312 | } |
| 317 | 313 | ||
| 318 | static inline void tegra_gpio_update(u32 gpio, u32 reg_offset, | 314 | static inline void tegra_gpio_update(struct tegra_gpio_info *tgi, u32 gpio, |
| 319 | u32 mask, u32 val) | 315 | u32 reg_offset, u32 mask, u32 val) |
| 320 | { | 316 | { |
| 321 | int port = GPIO_PORT(gpio); | 317 | int port = GPIO_PORT(gpio); |
| 322 | int pin = GPIO_PIN(gpio); | 318 | int pin = GPIO_PIN(gpio); |
| @@ -325,9 +321,9 @@ static inline void tegra_gpio_update(u32 gpio, u32 reg_offset, | |||
| 325 | u32 rval; | 321 | u32 rval; |
| 326 | 322 | ||
| 327 | addr += (GPIO_REG_DIFF * pin) + reg_offset; | 323 | addr += (GPIO_REG_DIFF * pin) + reg_offset; |
| 328 | rval = __raw_readl(tegra_gpio->regs[rindex] + addr); | 324 | rval = __raw_readl(tgi->regs[rindex] + addr); |
| 329 | rval = (rval & ~mask) | (val & mask); | 325 | rval = (rval & ~mask) | (val & mask); |
| 330 | __raw_writel(rval, tegra_gpio->regs[rindex] + addr); | 326 | __raw_writel(rval, tgi->regs[rindex] + addr); |
| 331 | } | 327 | } |
| 332 | 328 | ||
| 333 | int tegra_gpio_get_bank_int_nr(int gpio) | 329 | int tegra_gpio_get_bank_int_nr(int gpio) |
| @@ -339,7 +335,7 @@ EXPORT_SYMBOL(tegra_gpio_get_bank_int_nr); | |||
| 339 | /* | 335 | /* |
| 340 | * This function will return if the GPIO is accessible by CPU | 336 | * This function will return if the GPIO is accessible by CPU |
| 341 | */ | 337 | */ |
| 342 | static inline bool is_gpio_accessible(u32 offset) | 338 | static inline bool is_gpio_accessible(struct tegra_gpio_info *tgi, u32 offset) |
| 343 | { | 339 | { |
| 344 | int port = GPIO_PORT(offset); | 340 | int port = GPIO_PORT(offset); |
| 345 | int pin = GPIO_PIN(offset); | 341 | int pin = GPIO_PIN(offset); |
| @@ -357,8 +353,8 @@ static inline bool is_gpio_accessible(u32 offset) | |||
| 357 | 353 | ||
| 358 | rindex = tegra_gpio_cinfo[port].reg_index; | 354 | rindex = tegra_gpio_cinfo[port].reg_index; |
| 359 | 355 | ||
| 360 | val = __raw_readl(tegra_gpio->regs[rindex] + scr_offset + | 356 | val = __raw_readl(tgi->regs[rindex] + scr_offset + |
| 361 | (pin * GPIO_SCR_DIFF) + GPIO_SCR_REG); | 357 | (pin * GPIO_SCR_DIFF) + GPIO_SCR_REG); |
| 362 | 358 | ||
| 363 | if ((val & GPIO_FULL_ACCESS) == GPIO_FULL_ACCESS) | 359 | if ((val & GPIO_FULL_ACCESS) == GPIO_FULL_ACCESS) |
| 364 | return true; | 360 | return true; |
| @@ -368,31 +364,35 @@ static inline bool is_gpio_accessible(u32 offset) | |||
| 368 | 364 | ||
| 369 | int tegra_gpio_is_enabled(int gpio, int *is_gpio, int *is_input) | 365 | int tegra_gpio_is_enabled(int gpio, int *is_gpio, int *is_input) |
| 370 | { | 366 | { |
| 367 | #if 0 | ||
| 371 | u32 val; | 368 | u32 val; |
| 372 | if (is_gpio_accessible(gpio)) { | 369 | if (is_gpio_accessible(gpio)) { |
| 373 | val = tegra_gpio_readl(gpio, GPIO_ENB_CONFIG_REG); | 370 | val = tegra_gpio_readl(gpio, GPIO_ENB_CONFIG_REG); |
| 374 | *is_gpio = val & 0x1; | 371 | *is_gpio = val & 0x1; |
| 375 | *is_input = tegra_gpio_readl(gpio, GPIO_OUT_CTRL_REG); | 372 | *is_input = tegra_gpio_readl(gpio, GPIO_OUT_CTRL_REG); |
| 376 | } | 373 | } |
| 377 | return 0; | 374 | #else |
| 375 | return -1; | ||
| 376 | #endif | ||
| 378 | } | 377 | } |
| 379 | EXPORT_SYMBOL(tegra_gpio_is_enabled); | 378 | EXPORT_SYMBOL(tegra_gpio_is_enabled); |
| 380 | 379 | ||
| 381 | static void tegra_gpio_enable(int gpio) | 380 | static void tegra_gpio_enable(struct tegra_gpio_info *tgi, int gpio) |
| 382 | { | 381 | { |
| 383 | tegra_gpio_update(gpio, GPIO_ENB_CONFIG_REG, 0x1, 0x1); | 382 | tegra_gpio_update(tgi, gpio, GPIO_ENB_CONFIG_REG, 0x1, 0x1); |
| 384 | } | 383 | } |
| 385 | 384 | ||
| 386 | static void tegra_gpio_disable(int gpio) | 385 | static void tegra_gpio_disable(struct tegra_gpio_info *tgi, int gpio) |
| 387 | { | 386 | { |
| 388 | tegra_gpio_update(gpio, GPIO_ENB_CONFIG_REG, 0x1, 0x0); | 387 | tegra_gpio_update(tgi, gpio, GPIO_ENB_CONFIG_REG, 0x1, 0x0); |
| 389 | } | 388 | } |
| 390 | 389 | ||
| 391 | static int tegra_gpio_request(struct gpio_chip *chip, unsigned offset) | 390 | static int tegra_gpio_request(struct gpio_chip *chip, unsigned offset) |
| 392 | { | 391 | { |
| 392 | struct tegra_gpio_info *tgi = gpiochip_get_data(chip); | ||
| 393 | bool accessible; | 393 | bool accessible; |
| 394 | 394 | ||
| 395 | accessible = is_gpio_accessible(offset); | 395 | accessible = is_gpio_accessible(tgi, offset); |
| 396 | if (accessible) | 396 | if (accessible) |
| 397 | return pinctrl_request_gpio(chip->base + offset); | 397 | return pinctrl_request_gpio(chip->base + offset); |
| 398 | return -EBUSY; | 398 | return -EBUSY; |
| @@ -400,47 +400,54 @@ static int tegra_gpio_request(struct gpio_chip *chip, unsigned offset) | |||
| 400 | 400 | ||
| 401 | static void tegra_gpio_free(struct gpio_chip *chip, unsigned offset) | 401 | static void tegra_gpio_free(struct gpio_chip *chip, unsigned offset) |
| 402 | { | 402 | { |
| 403 | struct tegra_gpio_info *tgi = gpiochip_get_data(chip); | ||
| 404 | |||
| 403 | pinctrl_free_gpio(chip->base + offset); | 405 | pinctrl_free_gpio(chip->base + offset); |
| 404 | tegra_gpio_disable(offset); | 406 | tegra_gpio_disable(tgi, offset); |
| 405 | } | 407 | } |
| 406 | 408 | ||
| 407 | static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | 409 | static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value) |
| 408 | { | 410 | { |
| 411 | struct tegra_gpio_info *tgi = gpiochip_get_data(chip); | ||
| 409 | u32 val = (value) ? 0x1 : 0x0; | 412 | u32 val = (value) ? 0x1 : 0x0; |
| 410 | 413 | ||
| 411 | tegra_gpio_writel(val, offset, GPIO_OUT_VAL_REG); | 414 | tegra_gpio_writel(tgi, val, offset, GPIO_OUT_VAL_REG); |
| 412 | tegra_gpio_writel(0, offset, GPIO_OUT_CTRL_REG); | 415 | tegra_gpio_writel(tgi, 0, offset, GPIO_OUT_CTRL_REG); |
| 413 | } | 416 | } |
| 414 | 417 | ||
| 415 | static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset) | 418 | static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset) |
| 416 | { | 419 | { |
| 420 | struct tegra_gpio_info *tgi = gpiochip_get_data(chip); | ||
| 417 | u32 val; | 421 | u32 val; |
| 418 | 422 | ||
| 419 | val = tegra_gpio_readl(offset, GPIO_ENB_CONFIG_REG); | 423 | val = tegra_gpio_readl(tgi, offset, GPIO_ENB_CONFIG_REG); |
| 420 | if (val & GPIO_INOUT_BIT) | 424 | if (val & GPIO_INOUT_BIT) |
| 421 | return tegra_gpio_readl(offset, GPIO_OUT_VAL_REG) & 0x1; | 425 | return tegra_gpio_readl(tgi, offset, GPIO_OUT_VAL_REG) & 0x1; |
| 422 | 426 | ||
| 423 | return tegra_gpio_readl(offset, GPIO_INPUT_REG) & 0x1; | 427 | return tegra_gpio_readl(tgi, offset, GPIO_INPUT_REG) & 0x1; |
| 424 | } | 428 | } |
| 425 | 429 | ||
| 426 | static void set_gpio_direction_mode(unsigned offset, bool mode) | 430 | static void set_gpio_direction_mode(struct gpio_chip *chip, u32 offset, |
| 431 | bool mode) | ||
| 427 | { | 432 | { |
| 433 | struct tegra_gpio_info *tgi = gpiochip_get_data(chip); | ||
| 428 | u32 val; | 434 | u32 val; |
| 429 | 435 | ||
| 430 | val = tegra_gpio_readl(offset, GPIO_ENB_CONFIG_REG); | 436 | val = tegra_gpio_readl(tgi, offset, GPIO_ENB_CONFIG_REG); |
| 431 | if (mode) | 437 | if (mode) |
| 432 | val |= GPIO_INOUT_BIT; | 438 | val |= GPIO_INOUT_BIT; |
| 433 | else | 439 | else |
| 434 | val &= ~GPIO_INOUT_BIT; | 440 | val &= ~GPIO_INOUT_BIT; |
| 435 | tegra_gpio_writel(val, offset, GPIO_ENB_CONFIG_REG); | 441 | tegra_gpio_writel(tgi, val, offset, GPIO_ENB_CONFIG_REG); |
| 436 | } | 442 | } |
| 437 | 443 | ||
| 438 | static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | 444 | static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset) |
| 439 | { | 445 | { |
| 446 | struct tegra_gpio_info *tgi = gpiochip_get_data(chip); | ||
| 440 | int ret; | 447 | int ret; |
| 441 | 448 | ||
| 442 | set_gpio_direction_mode(offset, 0); | 449 | set_gpio_direction_mode(chip, offset, 0); |
| 443 | tegra_gpio_enable(offset); | 450 | tegra_gpio_enable(tgi, offset); |
| 444 | ret = pinctrl_gpio_direction_input(chip->base + offset); | 451 | ret = pinctrl_gpio_direction_input(chip->base + offset); |
| 445 | if (ret < 0) | 452 | if (ret < 0) |
| 446 | dev_err(chip->parent, | 453 | dev_err(chip->parent, |
| @@ -451,11 +458,12 @@ static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | |||
| 451 | static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset, | 458 | static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset, |
| 452 | int value) | 459 | int value) |
| 453 | { | 460 | { |
| 461 | struct tegra_gpio_info *tgi = gpiochip_get_data(chip); | ||
| 454 | int ret; | 462 | int ret; |
| 455 | 463 | ||
| 456 | tegra_gpio_set(chip, offset, value); | 464 | tegra_gpio_set(chip, offset, value); |
| 457 | set_gpio_direction_mode(offset, 1); | 465 | set_gpio_direction_mode(chip, offset, 1); |
| 458 | tegra_gpio_enable(offset); | 466 | tegra_gpio_enable(tgi, offset); |
| 459 | ret = pinctrl_gpio_direction_output(chip->base + offset); | 467 | ret = pinctrl_gpio_direction_output(chip->base + offset); |
| 460 | if (ret < 0) | 468 | if (ret < 0) |
| 461 | dev_err(chip->parent, | 469 | dev_err(chip->parent, |
| @@ -466,44 +474,52 @@ static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset, | |||
| 466 | static int tegra_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, | 474 | static int tegra_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, |
| 467 | unsigned debounce) | 475 | unsigned debounce) |
| 468 | { | 476 | { |
| 477 | struct tegra_gpio_info *tgi = gpiochip_get_data(chip); | ||
| 469 | unsigned dbc_ms = DIV_ROUND_UP(debounce, 1000); | 478 | unsigned dbc_ms = DIV_ROUND_UP(debounce, 1000); |
| 470 | 479 | ||
| 471 | tegra_gpio_update(offset, GPIO_ENB_CONFIG_REG, 0x1, 0x1); | 480 | tegra_gpio_update(tgi, offset, GPIO_ENB_CONFIG_REG, 0x1, 0x1); |
| 472 | tegra_gpio_update(offset, GPIO_DEB_FUNC_BIT, 0x5, 0x1); | 481 | tegra_gpio_update(tgi, offset, GPIO_DEB_FUNC_BIT, 0x5, 0x1); |
| 473 | /* Update debounce threshold */ | 482 | /* Update debounce threshold */ |
| 474 | tegra_gpio_writel(dbc_ms, offset, GPIO_DBC_THRES_REG); | 483 | tegra_gpio_writel(tgi, dbc_ms, offset, GPIO_DBC_THRES_REG); |
| 475 | return 0; | 484 | return 0; |
| 476 | } | 485 | } |
| 477 | 486 | ||
| 478 | static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | 487 | static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset) |
| 479 | { | 488 | { |
| 480 | return irq_find_mapping(irq_domain, offset); | 489 | struct tegra_gpio_info *tgi = gpiochip_get_data(chip); |
| 490 | |||
| 491 | return irq_find_mapping(tgi->irq_domain, offset); | ||
| 481 | } | 492 | } |
| 482 | 493 | ||
| 483 | static void tegra_gpio_irq_ack(struct irq_data *d) | 494 | static void tegra_gpio_irq_ack(struct irq_data *d) |
| 484 | { | 495 | { |
| 496 | struct tegra_gpio_controller *ctrlr = irq_data_get_irq_chip_data(d); | ||
| 485 | int gpio = d->hwirq; | 497 | int gpio = d->hwirq; |
| 486 | 498 | ||
| 487 | tegra_gpio_writel(1, gpio, GPIO_INT_CLEAR_REG); | 499 | tegra_gpio_writel(ctrlr->tgi, 1, gpio, GPIO_INT_CLEAR_REG); |
| 488 | } | 500 | } |
| 489 | 501 | ||
| 490 | static void tegra_gpio_irq_mask(struct irq_data *d) | 502 | static void tegra_gpio_irq_mask(struct irq_data *d) |
| 491 | { | 503 | { |
| 504 | struct tegra_gpio_controller *c = irq_data_get_irq_chip_data(d); | ||
| 492 | int gpio = d->hwirq; | 505 | int gpio = d->hwirq; |
| 493 | 506 | ||
| 494 | tegra_gpio_update(gpio, GPIO_ENB_CONFIG_REG, GPIO_INT_FUNC_BIT, 0); | 507 | tegra_gpio_update(c->tgi, gpio, GPIO_ENB_CONFIG_REG, GPIO_INT_FUNC_BIT, |
| 508 | 0); | ||
| 495 | } | 509 | } |
| 496 | 510 | ||
| 497 | static void tegra_gpio_irq_unmask(struct irq_data *d) | 511 | static void tegra_gpio_irq_unmask(struct irq_data *d) |
| 498 | { | 512 | { |
| 513 | struct tegra_gpio_controller *c = irq_data_get_irq_chip_data(d); | ||
| 499 | int gpio = d->hwirq; | 514 | int gpio = d->hwirq; |
| 500 | 515 | ||
| 501 | tegra_gpio_update(gpio, GPIO_ENB_CONFIG_REG, GPIO_INT_FUNC_BIT, | 516 | tegra_gpio_update(c->tgi, gpio, GPIO_ENB_CONFIG_REG, GPIO_INT_FUNC_BIT, |
| 502 | GPIO_INT_FUNC_BIT); | 517 | GPIO_INT_FUNC_BIT); |
| 503 | } | 518 | } |
| 504 | 519 | ||
| 505 | static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) | 520 | static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) |
| 506 | { | 521 | { |
| 522 | struct tegra_gpio_controller *ctrlr = irq_data_get_irq_chip_data(d); | ||
| 507 | int gpio = d->hwirq; | 523 | int gpio = d->hwirq; |
| 508 | u32 lvl_type = 0; | 524 | u32 lvl_type = 0; |
| 509 | u32 trg_type = 0; | 525 | u32 trg_type = 0; |
| @@ -543,12 +559,12 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) | |||
| 543 | lvl_type = lvl_type << 0x2; | 559 | lvl_type = lvl_type << 0x2; |
| 544 | 560 | ||
| 545 | /* Clear and Program the values */ | 561 | /* Clear and Program the values */ |
| 546 | val = tegra_gpio_readl(gpio, GPIO_ENB_CONFIG_REG); | 562 | val = tegra_gpio_readl(ctrlr->tgi, gpio, GPIO_ENB_CONFIG_REG); |
| 547 | val &= ~((0x3 << GPIO_TRG_TYPE_BIT_OFFSET) | (GPIO_TRG_LVL_BIT)); | 563 | val &= ~((0x3 << GPIO_TRG_TYPE_BIT_OFFSET) | (GPIO_TRG_LVL_BIT)); |
| 548 | val |= trg_type | lvl_type; | 564 | val |= trg_type | lvl_type; |
| 549 | tegra_gpio_writel(val, gpio, GPIO_ENB_CONFIG_REG); | 565 | tegra_gpio_writel(ctrlr->tgi, val, gpio, GPIO_ENB_CONFIG_REG); |
| 550 | 566 | ||
| 551 | tegra_gpio_enable(gpio); | 567 | tegra_gpio_enable(ctrlr->tgi, gpio); |
| 552 | 568 | ||
| 553 | if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) | 569 | if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) |
| 554 | irq_set_handler_locked(d, handle_level_irq); | 570 | irq_set_handler_locked(d, handle_level_irq); |
| @@ -576,31 +592,6 @@ static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable) | |||
| 576 | return ret; | 592 | return ret; |
| 577 | } | 593 | } |
| 578 | 594 | ||
| 579 | static struct gpio_chip tegra_gpio_chip = { | ||
| 580 | .label = "tegra-gpio", | ||
| 581 | .request = tegra_gpio_request, | ||
| 582 | .free = tegra_gpio_free, | ||
| 583 | .direction_input = tegra_gpio_direction_input, | ||
| 584 | .get = tegra_gpio_get, | ||
| 585 | .direction_output = tegra_gpio_direction_output, | ||
| 586 | .set = tegra_gpio_set, | ||
| 587 | .set_debounce = tegra_gpio_set_debounce, | ||
| 588 | .to_irq = tegra_gpio_to_irq, | ||
| 589 | .base = 0, | ||
| 590 | }; | ||
| 591 | |||
| 592 | static struct irq_chip tegra_gpio_irq_chip = { | ||
| 593 | .name = "GPIO", | ||
| 594 | .irq_ack = tegra_gpio_irq_ack, | ||
| 595 | .irq_mask = tegra_gpio_irq_mask, | ||
| 596 | .irq_unmask = tegra_gpio_irq_unmask, | ||
| 597 | .irq_set_type = tegra_gpio_irq_set_type, | ||
| 598 | .irq_set_wake = tegra_gpio_irq_set_wake, | ||
| 599 | .flags = IRQCHIP_MASK_ON_SUSPEND, | ||
| 600 | .irq_shutdown = tegra_gpio_irq_mask, | ||
| 601 | .irq_disable = tegra_gpio_irq_mask, | ||
| 602 | }; | ||
| 603 | |||
| 604 | static void tegra_gpio_irq_handler_desc(struct irq_desc *desc) | 595 | static void tegra_gpio_irq_handler_desc(struct irq_desc *desc) |
| 605 | { | 596 | { |
| 606 | struct irq_chip *chip = irq_desc_get_chip(desc); | 597 | struct irq_chip *chip = irq_desc_get_chip(desc); |
| @@ -614,7 +605,7 @@ static void tegra_gpio_irq_handler_desc(struct irq_desc *desc) | |||
| 614 | int rindex; | 605 | int rindex; |
| 615 | int port_map[MAX_GPIO_PORTS]; | 606 | int port_map[MAX_GPIO_PORTS]; |
| 616 | 607 | ||
| 617 | for (i =0; i < MAX_GPIO_PORTS; ++i) | 608 | for (i = 0; i < MAX_GPIO_PORTS; ++i) |
| 618 | port_map[i] = -1; | 609 | port_map[i] = -1; |
| 619 | 610 | ||
| 620 | for (i = 0; i < ARRAY_SIZE(tegra_gpio_cinfo); ++i) { | 611 | for (i = 0; i < ARRAY_SIZE(tegra_gpio_cinfo); ++i) { |
| @@ -630,8 +621,8 @@ static void tegra_gpio_irq_handler_desc(struct irq_desc *desc) | |||
| 630 | 621 | ||
| 631 | rindex = tegra_gpio_cinfo[port].reg_index; | 622 | rindex = tegra_gpio_cinfo[port].reg_index; |
| 632 | addr = tegra_gpio_cinfo[port].reg_offset; | 623 | addr = tegra_gpio_cinfo[port].reg_offset; |
| 633 | val = __raw_readl(tegra_gpio->regs[rindex] + | 624 | val = __raw_readl(tg_cont->tgi->regs[rindex] + addr + |
| 634 | addr + GPIO_INT_STATUS_OFFSET + GPIO_STATUS_G1); | 625 | GPIO_INT_STATUS_OFFSET + GPIO_STATUS_G1); |
| 635 | gpio = port * 8; | 626 | gpio = port * 8; |
| 636 | for_each_set_bit(pin, &val, 8) | 627 | for_each_set_bit(pin, &val, 8) |
| 637 | generic_handle_irq(gpio_to_irq(gpio + pin)); | 628 | generic_handle_irq(gpio_to_irq(gpio + pin)); |
| @@ -652,6 +643,82 @@ static void tegra_gpio_irq_handler(struct irq_desc *desc) | |||
| 652 | } | 643 | } |
| 653 | #endif | 644 | #endif |
| 654 | 645 | ||
| 646 | #ifdef CONFIG_DEBUG_FS | ||
| 647 | |||
| 648 | #define TOTAL_GPIOS 253 | ||
| 649 | |||
| 650 | #include <linux/debugfs.h> | ||
| 651 | #include <linux/seq_file.h> | ||
| 652 | |||
| 653 | static int dbg_gpio_show(struct seq_file *s, void *unused) | ||
| 654 | { | ||
| 655 | struct tegra_gpio_info *tgi = s->private; | ||
| 656 | int i; | ||
| 657 | bool accessible; | ||
| 658 | char x, y; | ||
| 659 | int count = 0; | ||
| 660 | |||
| 661 | x = ' '; | ||
| 662 | y = 'A'; | ||
| 663 | |||
| 664 | seq_puts(s, "Port:Pin:ENB DBC IN OUT_CTRL OUT_VAL INT_CLR\n"); | ||
| 665 | |||
| 666 | for (i = 0; i < TOTAL_GPIOS; i++) { | ||
| 667 | accessible = is_gpio_accessible(tgi, i); | ||
| 668 | if (count == 8) | ||
| 669 | count = 0; | ||
| 670 | |||
| 671 | if ((count == 0) && (i/8)) { | ||
| 672 | if (x != ' ') | ||
| 673 | x++; | ||
| 674 | if (y == 'Z') { | ||
| 675 | y = 'A'; | ||
| 676 | x = 'A'; | ||
| 677 | } else { | ||
| 678 | y++; | ||
| 679 | } | ||
| 680 | } | ||
| 681 | count++; | ||
| 682 | if (accessible) { | ||
| 683 | seq_printf(s, "%c%c:%d 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", | ||
| 684 | x, y, i%8, | ||
| 685 | tegra_gpio_readl(tgi, i, GPIO_ENB_CONFIG_REG), | ||
| 686 | tegra_gpio_readl(tgi, i, GPIO_DBC_THRES_REG), | ||
| 687 | tegra_gpio_readl(tgi, i, GPIO_INPUT_REG), | ||
| 688 | tegra_gpio_readl(tgi, i, GPIO_OUT_CTRL_REG), | ||
| 689 | tegra_gpio_readl(tgi, i, GPIO_OUT_VAL_REG), | ||
| 690 | tegra_gpio_readl(tgi, i, GPIO_INT_CLEAR_REG)); | ||
| 691 | } | ||
| 692 | } | ||
| 693 | |||
| 694 | return 0; | ||
| 695 | } | ||
| 696 | |||
| 697 | static int dbg_gpio_open(struct inode *inode, struct file *file) | ||
| 698 | { | ||
| 699 | return single_open(file, dbg_gpio_show, inode->i_private); | ||
| 700 | } | ||
| 701 | |||
| 702 | static const struct file_operations debug_fops = { | ||
| 703 | .open = dbg_gpio_open, | ||
| 704 | .read = seq_read, | ||
| 705 | .llseek = seq_lseek, | ||
| 706 | .release = single_release, | ||
| 707 | }; | ||
| 708 | |||
| 709 | static int __init tegra_gpio_debuginit(struct tegra_gpio_info *tgi) | ||
| 710 | { | ||
| 711 | (void) debugfs_create_file("tegra_gpio", S_IRUGO, | ||
| 712 | NULL, tgi, &debug_fops); | ||
| 713 | |||
| 714 | return 0; | ||
| 715 | } | ||
| 716 | #else | ||
| 717 | static inline void tegra_gpio_debuginit(struct tegra_gpio_info *tgi) | ||
| 718 | { | ||
| 719 | } | ||
| 720 | #endif | ||
| 721 | |||
| 655 | static struct of_device_id tegra_gpio_of_match[] = { | 722 | static struct of_device_id tegra_gpio_of_match[] = { |
| 656 | { .compatible = "nvidia,tegra186-gpio", NULL }, | 723 | { .compatible = "nvidia,tegra186-gpio", NULL }, |
| 657 | { }, | 724 | { }, |
| @@ -661,52 +728,84 @@ static int tegra_gpio_probe(struct platform_device *pdev) | |||
| 661 | { | 728 | { |
| 662 | struct resource *res; | 729 | struct resource *res; |
| 663 | struct tegra_gpio_controller *tg_cont; | 730 | struct tegra_gpio_controller *tg_cont; |
| 731 | struct tegra_gpio_info *tgi; | ||
| 664 | void __iomem *base; | 732 | void __iomem *base; |
| 665 | u32 i; | 733 | u32 i; |
| 666 | int gpio; | 734 | int gpio; |
| 667 | int ret; | 735 | int ret; |
| 668 | 736 | ||
| 669 | for (tegra_gpio_bank_count = 0;; tegra_gpio_bank_count++) { | 737 | tgi = devm_kzalloc(&pdev->dev, sizeof(*tgi), GFP_KERNEL); |
| 738 | if (!tgi) | ||
| 739 | return -ENOMEM; | ||
| 740 | tgi->dev = &pdev->dev; | ||
| 741 | |||
| 742 | for (tgi->tegra_gpio_bank_count = 0;; tgi->tegra_gpio_bank_count++) { | ||
| 670 | res = platform_get_resource(pdev, IORESOURCE_IRQ, | 743 | res = platform_get_resource(pdev, IORESOURCE_IRQ, |
| 671 | tegra_gpio_bank_count); | 744 | tgi->tegra_gpio_bank_count); |
| 672 | if (!res) | 745 | if (!res) |
| 673 | break; | 746 | break; |
| 674 | } | 747 | } |
| 675 | 748 | if (!tgi->tegra_gpio_bank_count) { | |
| 676 | if (!tegra_gpio_bank_count) { | ||
| 677 | dev_err(&pdev->dev, "No GPIO Controller found\n"); | 749 | dev_err(&pdev->dev, "No GPIO Controller found\n"); |
| 678 | return -ENODEV; | 750 | return -ENODEV; |
| 679 | } | 751 | } |
| 680 | 752 | ||
| 681 | tegra_gpio = devm_kzalloc(&pdev->dev, sizeof(*tegra_gpio), GFP_KERNEL); | 753 | tgi->gc.label = "tegra-gpio"; |
| 682 | if (!tegra_gpio) { | 754 | tgi->gc.request = tegra_gpio_request; |
| 683 | dev_err(&pdev->dev, "Can't alloc tegra_gpio\n"); | 755 | tgi->gc.free = tegra_gpio_free; |
| 684 | return -ENOMEM; | 756 | tgi->gc.direction_input = tegra_gpio_direction_input; |
| 757 | tgi->gc.get = tegra_gpio_get; | ||
| 758 | tgi->gc.direction_output = tegra_gpio_direction_output; | ||
| 759 | tgi->gc.set = tegra_gpio_set; | ||
| 760 | tgi->gc.to_irq = tegra_gpio_to_irq; | ||
| 761 | tgi->gc.set_debounce = tegra_gpio_set_debounce; | ||
| 762 | tgi->gc.base = 0; | ||
| 763 | tgi->gc.ngpio = MAX_PORTS * MAX_PINS_PER_PORT; | ||
| 764 | tgi->gc.parent = &pdev->dev; | ||
| 765 | tgi->gc.of_node = pdev->dev.of_node; | ||
| 766 | |||
| 767 | tgi->ic.name = "GPIO"; | ||
| 768 | tgi->ic.irq_ack = tegra_gpio_irq_ack; | ||
| 769 | tgi->ic.irq_mask = tegra_gpio_irq_mask; | ||
| 770 | tgi->ic.irq_unmask = tegra_gpio_irq_unmask; | ||
| 771 | tgi->ic.irq_set_type = tegra_gpio_irq_set_type; | ||
| 772 | tgi->ic.irq_shutdown = tegra_gpio_irq_mask; | ||
| 773 | tgi->ic.irq_set_wake = tegra_gpio_irq_set_wake; | ||
| 774 | tgi->ic.irq_disable = tegra_gpio_irq_mask; | ||
| 775 | |||
| 776 | platform_set_drvdata(pdev, tgi); | ||
| 777 | |||
| 778 | for (i = 0; i < tgi->tegra_gpio_bank_count; i++) { | ||
| 779 | res = platform_get_resource(pdev, IORESOURCE_IRQ, i); | ||
| 780 | if (!res) { | ||
| 781 | dev_err(&pdev->dev, "Missing IRQ resource\n"); | ||
| 782 | return -ENODEV; | ||
| 783 | } | ||
| 784 | tg_cont = &tgi->tg_contrlr[i]; | ||
| 785 | tg_cont->controller = i; | ||
| 786 | tg_cont->irq = res->start; | ||
| 787 | tg_cont->tgi = tgi; | ||
| 685 | } | 788 | } |
| 686 | tegra_gpio->dev = &pdev->dev; | 789 | |
| 790 | tgi->irq_domain = irq_domain_add_linear(pdev->dev.of_node, | ||
| 791 | tgi->gc.ngpio, | ||
| 792 | &irq_domain_simple_ops, NULL); | ||
| 793 | if (!tgi->irq_domain) | ||
| 794 | return -ENODEV; | ||
| 687 | 795 | ||
| 688 | for (i = 0;; i++) { | 796 | for (i = 0;; i++) { |
| 689 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); | 797 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); |
| 690 | if (!res) | 798 | if (!res) |
| 691 | break; | 799 | break; |
| 692 | } | 800 | } |
| 693 | tegra_gpio->nbanks = i; | 801 | tgi->nbanks = i; |
| 694 | 802 | ||
| 695 | tegra_gpio->regs = devm_kzalloc(&pdev->dev, tegra_gpio->nbanks * | 803 | tgi->regs = devm_kzalloc(&pdev->dev, tgi->nbanks * sizeof(*tgi->regs), |
| 696 | sizeof(*tegra_gpio->regs), GFP_KERNEL); | 804 | GFP_KERNEL); |
| 697 | if (!tegra_gpio->regs) { | 805 | if (!tgi->regs) |
| 698 | dev_err(&pdev->dev, "Can't alloc regs pointer\n"); | ||
| 699 | return -ENODEV; | ||
| 700 | } | ||
| 701 | |||
| 702 | tegra_gpio->reg_base = devm_kzalloc(&pdev->dev, tegra_gpio->nbanks * | ||
| 703 | sizeof(*tegra_gpio->reg_base), GFP_KERNEL); | ||
| 704 | if (!tegra_gpio->reg_base) { | ||
| 705 | dev_err(&pdev->dev, "Can't alloc reg_base pointer\n"); | ||
| 706 | return -ENOMEM; | 806 | return -ENOMEM; |
| 707 | } | ||
| 708 | 807 | ||
| 709 | for (i = 0; i < tegra_gpio->nbanks; i++) { | 808 | for (i = 0; i < tgi->nbanks; i++) { |
| 710 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); | 809 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); |
| 711 | if (!res) { | 810 | if (!res) { |
| 712 | dev_err(&pdev->dev, "Missing MEM resource\n"); | 811 | dev_err(&pdev->dev, "Missing MEM resource\n"); |
| @@ -721,66 +820,43 @@ static int tegra_gpio_probe(struct platform_device *pdev) | |||
| 721 | ret); | 820 | ret); |
| 722 | return ret; | 821 | return ret; |
| 723 | } | 822 | } |
| 724 | tegra_gpio->reg_base[i] = res->start; | 823 | tgi->regs[i] = base; |
| 725 | tegra_gpio->regs[i] = base; | ||
| 726 | } | 824 | } |
| 727 | 825 | ||
| 728 | for (i = 0; i < tegra_gpio_bank_count; i++) { | 826 | ret = gpiochip_add_data(&tgi->gc, tgi); |
| 729 | res = platform_get_resource(pdev, IORESOURCE_IRQ, i); | 827 | if (ret < 0) { |
| 730 | if (!res) { | 828 | dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); |
| 731 | dev_err(&pdev->dev, "Missing IRQ resource\n"); | 829 | return ret; |
| 732 | return -ENODEV; | ||
| 733 | } | ||
| 734 | tg_cont = &tegra_gpio_controllers[i]; | ||
| 735 | tg_cont->controller = i; | ||
| 736 | tg_cont->irq = res->start; | ||
| 737 | } | 830 | } |
| 738 | 831 | ||
| 739 | tegra_gpio_chip.parent = &pdev->dev; | 832 | for (gpio = 0; gpio < tgi->gc.ngpio; gpio++) { |
| 740 | tegra_gpio_chip.of_node = pdev->dev.of_node; | 833 | int irq = irq_create_mapping(tgi->irq_domain, gpio); |
| 741 | tegra_gpio_chip.ngpio = MAX_PORTS * MAX_PINS_PER_PORT; | ||
| 742 | |||
| 743 | irq_domain = irq_domain_add_linear(pdev->dev.of_node, | ||
| 744 | tegra_gpio_chip.ngpio, &irq_domain_simple_ops, NULL); | ||
| 745 | if (!irq_domain) | ||
| 746 | return -ENODEV; | ||
| 747 | |||
| 748 | for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) { | ||
| 749 | int irq = irq_create_mapping(irq_domain, gpio); | ||
| 750 | int cont_id = tegra_gpio_cinfo[GPIO_PORT(gpio)].cont_id; | 834 | int cont_id = tegra_gpio_cinfo[GPIO_PORT(gpio)].cont_id; |
| 751 | 835 | ||
| 752 | if (is_gpio_accessible(gpio)) | 836 | if (is_gpio_accessible(tgi, gpio)) |
| 753 | /* mask interrupts for this GPIO */ | 837 | /* mask interrupts for this GPIO */ |
| 754 | tegra_gpio_update(gpio, GPIO_ENB_CONFIG_REG, GPIO_INT_FUNC_BIT, 0); | 838 | tegra_gpio_update(tgi, gpio, GPIO_ENB_CONFIG_REG, |
| 755 | 839 | GPIO_INT_FUNC_BIT, 0); | |
| 756 | tg_cont = &tegra_gpio_controllers[cont_id]; | ||
| 757 | 840 | ||
| 841 | tg_cont = &tgi->tg_contrlr[cont_id]; | ||
| 842 | irq_set_lockdep_class(irq, &tgi->lock_class); | ||
| 758 | irq_set_chip_data(irq, tg_cont); | 843 | irq_set_chip_data(irq, tg_cont); |
| 759 | irq_set_chip_and_handler(irq, &tegra_gpio_irq_chip, | 844 | irq_set_chip_and_handler(irq, &tgi->ic, handle_simple_irq); |
| 760 | handle_simple_irq); | ||
| 761 | } | ||
| 762 | |||
| 763 | ret = gpiochip_add(&tegra_gpio_chip); | ||
| 764 | if (ret < 0) { | ||
| 765 | dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); | ||
| 766 | for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) { | ||
| 767 | int irq = irq_find_mapping(irq_domain, gpio); | ||
| 768 | if (irq) | ||
| 769 | irq_dispose_mapping(irq); | ||
| 770 | } | ||
| 771 | irq_domain_remove(irq_domain); | ||
| 772 | return ret; | ||
| 773 | } | 845 | } |
| 774 | 846 | ||
| 775 | for (i = 0; i < tegra_gpio_bank_count; i++) { | 847 | for (i = 0; i < tgi->tegra_gpio_bank_count; i++) { |
| 776 | tg_cont = &tegra_gpio_controllers[i]; | 848 | tg_cont = &tgi->tg_contrlr[i]; |
| 777 | irq_set_chained_handler_and_data(tg_cont->irq, | 849 | irq_set_chained_handler_and_data(tg_cont->irq, |
| 778 | tegra_gpio_irq_handler, tg_cont); | 850 | tegra_gpio_irq_handler, |
| 851 | tg_cont); | ||
| 779 | } | 852 | } |
| 780 | 853 | ||
| 781 | tegra_pm_update_gpio_wakeup_table(tegra_gpio_chip.base, | 854 | tegra_pm_update_gpio_wakeup_table(tgi->gc.base, |
| 782 | tegra186_gpio_wakes, | 855 | tegra186_gpio_wakes, |
| 783 | ARRAY_SIZE(tegra186_gpio_wakes)); | 856 | ARRAY_SIZE(tegra186_gpio_wakes)); |
| 857 | |||
| 858 | tegra_gpio_debuginit(tgi); | ||
| 859 | |||
| 784 | return 0; | 860 | return 0; |
| 785 | } | 861 | } |
| 786 | 862 | ||
| @@ -799,76 +875,6 @@ static int __init tegra_gpio_init(void) | |||
| 799 | } | 875 | } |
| 800 | postcore_initcall(tegra_gpio_init); | 876 | postcore_initcall(tegra_gpio_init); |
| 801 | 877 | ||
| 802 | #ifdef CONFIG_DEBUG_FS | ||
| 803 | |||
| 804 | #define TOTAL_GPIOS 253 | ||
| 805 | |||
| 806 | #include <linux/debugfs.h> | ||
| 807 | #include <linux/seq_file.h> | ||
| 808 | |||
| 809 | static int dbg_gpio_show(struct seq_file *s, void *unused) | ||
| 810 | { | ||
| 811 | int i; | ||
| 812 | bool accessible; | ||
| 813 | char x, y; | ||
| 814 | int count = 0; | ||
| 815 | |||
| 816 | x = ' '; | ||
| 817 | y = 'A'; | ||
| 818 | |||
| 819 | seq_puts(s, "Port:Pin:ENB DBC IN OUT_CTRL OUT_VAL INT_CLR\n"); | ||
| 820 | |||
| 821 | for (i = 0; i < TOTAL_GPIOS; i++) { | ||
| 822 | accessible = is_gpio_accessible(i); | ||
| 823 | if (count == 8) | ||
| 824 | count = 0; | ||
| 825 | |||
| 826 | if ((count == 0) && (i/8)) { | ||
| 827 | if (x != ' ') | ||
| 828 | x++; | ||
| 829 | if (y == 'Z') { | ||
| 830 | y = 'A'; | ||
| 831 | x = 'A'; | ||
| 832 | } else { | ||
| 833 | y++; | ||
| 834 | } | ||
| 835 | } | ||
| 836 | count++; | ||
| 837 | if (accessible) { | ||
| 838 | seq_printf(s, "%c%c:%d 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", | ||
| 839 | x, y, i%8, | ||
| 840 | tegra_gpio_readl(i, GPIO_ENB_CONFIG_REG), | ||
| 841 | tegra_gpio_readl(i, GPIO_DBC_THRES_REG), | ||
| 842 | tegra_gpio_readl(i, GPIO_INPUT_REG), | ||
| 843 | tegra_gpio_readl(i, GPIO_OUT_CTRL_REG), | ||
| 844 | tegra_gpio_readl(i, GPIO_OUT_VAL_REG), | ||
| 845 | tegra_gpio_readl(i, GPIO_INT_CLEAR_REG)); | ||
| 846 | } | ||
| 847 | } | ||
| 848 | return 0; | ||
| 849 | } | ||
| 850 | |||
| 851 | static int dbg_gpio_open(struct inode *inode, struct file *file) | ||
| 852 | { | ||
| 853 | return single_open(file, dbg_gpio_show, &inode->i_private); | ||
| 854 | } | ||
| 855 | |||
| 856 | static const struct file_operations debug_fops = { | ||
| 857 | .open = dbg_gpio_open, | ||
| 858 | .read = seq_read, | ||
| 859 | .llseek = seq_lseek, | ||
| 860 | .release = single_release, | ||
| 861 | }; | ||
| 862 | |||
| 863 | static int __init tegra_gpio_debuginit(void) | ||
| 864 | { | ||
| 865 | (void) debugfs_create_file("tegra_gpio", S_IRUGO, | ||
| 866 | NULL, NULL, &debug_fops); | ||
| 867 | return 0; | ||
| 868 | } | ||
| 869 | late_initcall(tegra_gpio_debuginit); | ||
| 870 | #endif | ||
| 871 | |||
| 872 | MODULE_AUTHOR("Suresh Mangipudi <smangipudi@nvidia.com>"); | 878 | MODULE_AUTHOR("Suresh Mangipudi <smangipudi@nvidia.com>"); |
| 873 | MODULE_DESCRIPTION("NVIDIA Tegra186 GPIO driver"); | 879 | MODULE_DESCRIPTION("NVIDIA Tegra186 GPIO driver"); |
| 874 | MODULE_LICENSE("GPL v2"); | 880 | MODULE_LICENSE("GPL v2"); |
