| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * linux/arch/arm/mach-sa1100/assabet.c |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Author: Nicolas Pitre |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * This file contains all Assabet-specific tweaks. |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 10 | | - * published by the Free Software Foundation. |
|---|
| 11 | 8 | */ |
|---|
| 12 | 9 | #include <linux/init.h> |
|---|
| 13 | 10 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 15 | 12 | #include <linux/errno.h> |
|---|
| 16 | 13 | #include <linux/gpio/gpio-reg.h> |
|---|
| 17 | 14 | #include <linux/gpio/machine.h> |
|---|
| 15 | +#include <linux/gpio_keys.h> |
|---|
| 18 | 16 | #include <linux/ioport.h> |
|---|
| 19 | 17 | #include <linux/platform_data/sa11x0-serial.h> |
|---|
| 20 | 18 | #include <linux/regulator/fixed.h> |
|---|
| .. | .. |
|---|
| 36 | 34 | #include <asm/setup.h> |
|---|
| 37 | 35 | #include <asm/page.h> |
|---|
| 38 | 36 | #include <asm/pgtable-hwdef.h> |
|---|
| 39 | | -#include <asm/pgtable.h> |
|---|
| 40 | 37 | #include <asm/tlbflush.h> |
|---|
| 41 | 38 | |
|---|
| 42 | 39 | #include <asm/mach/arch.h> |
|---|
| .. | .. |
|---|
| 468 | 465 | static struct fixed_voltage_config assabet_cf_vcc_pdata __initdata = { |
|---|
| 469 | 466 | .supply_name = "cf-power", |
|---|
| 470 | 467 | .microvolts = 3300000, |
|---|
| 471 | | - .enable_high = 1, |
|---|
| 468 | +}; |
|---|
| 469 | + |
|---|
| 470 | +static struct gpiod_lookup_table assabet_cf_vcc_gpio_table = { |
|---|
| 471 | + .dev_id = "reg-fixed-voltage.0", |
|---|
| 472 | + .table = { |
|---|
| 473 | + GPIO_LOOKUP("assabet", 0, NULL, GPIO_ACTIVE_HIGH), |
|---|
| 474 | + { }, |
|---|
| 475 | + }, |
|---|
| 476 | +}; |
|---|
| 477 | + |
|---|
| 478 | +static struct gpio_led assabet_leds[] __initdata = { |
|---|
| 479 | + { |
|---|
| 480 | + .name = "assabet:red", |
|---|
| 481 | + .default_trigger = "cpu0", |
|---|
| 482 | + .active_low = 1, |
|---|
| 483 | + .default_state = LEDS_GPIO_DEFSTATE_KEEP, |
|---|
| 484 | + }, { |
|---|
| 485 | + .name = "assabet:green", |
|---|
| 486 | + .default_trigger = "heartbeat", |
|---|
| 487 | + .active_low = 1, |
|---|
| 488 | + .default_state = LEDS_GPIO_DEFSTATE_KEEP, |
|---|
| 489 | + }, |
|---|
| 490 | +}; |
|---|
| 491 | + |
|---|
| 492 | +static const struct gpio_led_platform_data assabet_leds_pdata __initconst = { |
|---|
| 493 | + .num_leds = ARRAY_SIZE(assabet_leds), |
|---|
| 494 | + .leds = assabet_leds, |
|---|
| 495 | +}; |
|---|
| 496 | + |
|---|
| 497 | +static struct gpio_keys_button assabet_keys_buttons[] = { |
|---|
| 498 | + { |
|---|
| 499 | + .gpio = 0, |
|---|
| 500 | + .irq = IRQ_GPIO0, |
|---|
| 501 | + .desc = "gpio0", |
|---|
| 502 | + .wakeup = 1, |
|---|
| 503 | + .can_disable = 1, |
|---|
| 504 | + .debounce_interval = 5, |
|---|
| 505 | + }, { |
|---|
| 506 | + .gpio = 1, |
|---|
| 507 | + .irq = IRQ_GPIO1, |
|---|
| 508 | + .desc = "gpio1", |
|---|
| 509 | + .wakeup = 1, |
|---|
| 510 | + .can_disable = 1, |
|---|
| 511 | + .debounce_interval = 5, |
|---|
| 512 | + }, |
|---|
| 513 | +}; |
|---|
| 514 | + |
|---|
| 515 | +static const struct gpio_keys_platform_data assabet_keys_pdata = { |
|---|
| 516 | + .buttons = assabet_keys_buttons, |
|---|
| 517 | + .nbuttons = ARRAY_SIZE(assabet_keys_buttons), |
|---|
| 518 | + .rep = 0, |
|---|
| 519 | +}; |
|---|
| 520 | + |
|---|
| 521 | +static struct gpiod_lookup_table assabet_uart1_gpio_table = { |
|---|
| 522 | + .dev_id = "sa11x0-uart.1", |
|---|
| 523 | + .table = { |
|---|
| 524 | + GPIO_LOOKUP("assabet", 16, "dtr", GPIO_ACTIVE_LOW), |
|---|
| 525 | + GPIO_LOOKUP("assabet", 17, "rts", GPIO_ACTIVE_LOW), |
|---|
| 526 | + GPIO_LOOKUP("assabet", 25, "dcd", GPIO_ACTIVE_LOW), |
|---|
| 527 | + GPIO_LOOKUP("assabet", 26, "cts", GPIO_ACTIVE_LOW), |
|---|
| 528 | + GPIO_LOOKUP("assabet", 27, "dsr", GPIO_ACTIVE_LOW), |
|---|
| 529 | + { }, |
|---|
| 530 | + }, |
|---|
| 531 | +}; |
|---|
| 532 | + |
|---|
| 533 | +static struct gpiod_lookup_table assabet_uart3_gpio_table = { |
|---|
| 534 | + .dev_id = "sa11x0-uart.3", |
|---|
| 535 | + .table = { |
|---|
| 536 | + GPIO_LOOKUP("assabet", 28, "cts", GPIO_ACTIVE_LOW), |
|---|
| 537 | + GPIO_LOOKUP("assabet", 29, "dsr", GPIO_ACTIVE_LOW), |
|---|
| 538 | + GPIO_LOOKUP("assabet", 30, "dcd", GPIO_ACTIVE_LOW), |
|---|
| 539 | + GPIO_LOOKUP("assabet", 31, "rng", GPIO_ACTIVE_LOW), |
|---|
| 540 | + { }, |
|---|
| 541 | + }, |
|---|
| 472 | 542 | }; |
|---|
| 473 | 543 | |
|---|
| 474 | 544 | static void __init assabet_init(void) |
|---|
| .. | .. |
|---|
| 517 | 587 | neponset_resources, ARRAY_SIZE(neponset_resources)); |
|---|
| 518 | 588 | #endif |
|---|
| 519 | 589 | } else { |
|---|
| 590 | + gpiod_add_lookup_table(&assabet_uart1_gpio_table); |
|---|
| 591 | + gpiod_add_lookup_table(&assabet_uart3_gpio_table); |
|---|
| 592 | + gpiod_add_lookup_table(&assabet_cf_vcc_gpio_table); |
|---|
| 593 | + |
|---|
| 520 | 594 | sa11x0_register_fixed_regulator(0, &assabet_cf_vcc_pdata, |
|---|
| 521 | | - assabet_cf_vcc_consumers, |
|---|
| 522 | | - ARRAY_SIZE(assabet_cf_vcc_consumers)); |
|---|
| 595 | + assabet_cf_vcc_consumers, |
|---|
| 596 | + ARRAY_SIZE(assabet_cf_vcc_consumers), |
|---|
| 597 | + true); |
|---|
| 523 | 598 | |
|---|
| 524 | 599 | } |
|---|
| 600 | + |
|---|
| 601 | + platform_device_register_resndata(NULL, "gpio-keys", 0, |
|---|
| 602 | + NULL, 0, |
|---|
| 603 | + &assabet_keys_pdata, |
|---|
| 604 | + sizeof(assabet_keys_pdata)); |
|---|
| 605 | + |
|---|
| 606 | + gpio_led_register_device(-1, &assabet_leds_pdata); |
|---|
| 525 | 607 | |
|---|
| 526 | 608 | #ifndef ASSABET_PAL_VIDEO |
|---|
| 527 | 609 | sa11x0_register_lcd(&lq039q2ds54_info); |
|---|
| .. | .. |
|---|
| 550 | 632 | int prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO); |
|---|
| 551 | 633 | pmd_t *pmd; |
|---|
| 552 | 634 | |
|---|
| 553 | | - pmd = pmd_offset(pud_offset(pgd_offset_k(virt), virt), virt); |
|---|
| 635 | + pmd = pmd_off_k(virt); |
|---|
| 554 | 636 | *pmd = __pmd(phys | prot); |
|---|
| 555 | 637 | flush_pmd_entry(pmd); |
|---|
| 556 | 638 | } |
|---|
| .. | .. |
|---|
| 570 | 652 | */ |
|---|
| 571 | 653 | static void __init get_assabet_scr(void) |
|---|
| 572 | 654 | { |
|---|
| 573 | | - unsigned long uninitialized_var(scr), i; |
|---|
| 655 | + unsigned long scr, i; |
|---|
| 574 | 656 | |
|---|
| 575 | 657 | GPDR |= 0x3fc; /* Configure GPIO 9:2 as outputs */ |
|---|
| 576 | 658 | GPSR = 0x3fc; /* Write 0xFF to GPIO 9:2 */ |
|---|
| .. | .. |
|---|
| 598 | 680 | { |
|---|
| 599 | 681 | if (port->mapbase == _Ser1UTCR0) { |
|---|
| 600 | 682 | if (state) |
|---|
| 601 | | - ASSABET_BCR_clear(ASSABET_BCR_RS232EN | |
|---|
| 602 | | - ASSABET_BCR_COM_RTS | |
|---|
| 603 | | - ASSABET_BCR_COM_DTR); |
|---|
| 683 | + ASSABET_BCR_clear(ASSABET_BCR_RS232EN); |
|---|
| 604 | 684 | else |
|---|
| 605 | | - ASSABET_BCR_set(ASSABET_BCR_RS232EN | |
|---|
| 606 | | - ASSABET_BCR_COM_RTS | |
|---|
| 607 | | - ASSABET_BCR_COM_DTR); |
|---|
| 685 | + ASSABET_BCR_set(ASSABET_BCR_RS232EN); |
|---|
| 608 | 686 | } |
|---|
| 609 | | -} |
|---|
| 610 | | - |
|---|
| 611 | | -/* |
|---|
| 612 | | - * Assabet uses COM_RTS and COM_DTR for both UART1 (com port) |
|---|
| 613 | | - * and UART3 (radio module). We only handle them for UART1 here. |
|---|
| 614 | | - */ |
|---|
| 615 | | -static void assabet_set_mctrl(struct uart_port *port, u_int mctrl) |
|---|
| 616 | | -{ |
|---|
| 617 | | - if (port->mapbase == _Ser1UTCR0) { |
|---|
| 618 | | - u_int set = 0, clear = 0; |
|---|
| 619 | | - |
|---|
| 620 | | - if (mctrl & TIOCM_RTS) |
|---|
| 621 | | - clear |= ASSABET_BCR_COM_RTS; |
|---|
| 622 | | - else |
|---|
| 623 | | - set |= ASSABET_BCR_COM_RTS; |
|---|
| 624 | | - |
|---|
| 625 | | - if (mctrl & TIOCM_DTR) |
|---|
| 626 | | - clear |= ASSABET_BCR_COM_DTR; |
|---|
| 627 | | - else |
|---|
| 628 | | - set |= ASSABET_BCR_COM_DTR; |
|---|
| 629 | | - |
|---|
| 630 | | - ASSABET_BCR_clear(clear); |
|---|
| 631 | | - ASSABET_BCR_set(set); |
|---|
| 632 | | - } |
|---|
| 633 | | -} |
|---|
| 634 | | - |
|---|
| 635 | | -static u_int assabet_get_mctrl(struct uart_port *port) |
|---|
| 636 | | -{ |
|---|
| 637 | | - u_int ret = 0; |
|---|
| 638 | | - u_int bsr = ASSABET_BSR; |
|---|
| 639 | | - |
|---|
| 640 | | - /* need 2 reads to read current value */ |
|---|
| 641 | | - bsr = ASSABET_BSR; |
|---|
| 642 | | - |
|---|
| 643 | | - if (port->mapbase == _Ser1UTCR0) { |
|---|
| 644 | | - if (bsr & ASSABET_BSR_COM_DCD) |
|---|
| 645 | | - ret |= TIOCM_CD; |
|---|
| 646 | | - if (bsr & ASSABET_BSR_COM_CTS) |
|---|
| 647 | | - ret |= TIOCM_CTS; |
|---|
| 648 | | - if (bsr & ASSABET_BSR_COM_DSR) |
|---|
| 649 | | - ret |= TIOCM_DSR; |
|---|
| 650 | | - } else if (port->mapbase == _Ser3UTCR0) { |
|---|
| 651 | | - if (bsr & ASSABET_BSR_RAD_DCD) |
|---|
| 652 | | - ret |= TIOCM_CD; |
|---|
| 653 | | - if (bsr & ASSABET_BSR_RAD_CTS) |
|---|
| 654 | | - ret |= TIOCM_CTS; |
|---|
| 655 | | - if (bsr & ASSABET_BSR_RAD_DSR) |
|---|
| 656 | | - ret |= TIOCM_DSR; |
|---|
| 657 | | - if (bsr & ASSABET_BSR_RAD_RI) |
|---|
| 658 | | - ret |= TIOCM_RI; |
|---|
| 659 | | - } else { |
|---|
| 660 | | - ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR; |
|---|
| 661 | | - } |
|---|
| 662 | | - |
|---|
| 663 | | - return ret; |
|---|
| 664 | 687 | } |
|---|
| 665 | 688 | |
|---|
| 666 | 689 | static struct sa1100_port_fns assabet_port_fns __initdata = { |
|---|
| 667 | | - .set_mctrl = assabet_set_mctrl, |
|---|
| 668 | | - .get_mctrl = assabet_get_mctrl, |
|---|
| 669 | 690 | .pm = assabet_uart_pm, |
|---|
| 670 | 691 | }; |
|---|
| 671 | 692 | |
|---|
| .. | .. |
|---|
| 716 | 737 | sa1100_register_uart(2, 3); |
|---|
| 717 | 738 | } |
|---|
| 718 | 739 | |
|---|
| 719 | | -/* LEDs */ |
|---|
| 720 | | -#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS) |
|---|
| 721 | | -struct assabet_led { |
|---|
| 722 | | - struct led_classdev cdev; |
|---|
| 723 | | - u32 mask; |
|---|
| 724 | | -}; |
|---|
| 725 | | - |
|---|
| 726 | | -/* |
|---|
| 727 | | - * The triggers lines up below will only be used if the |
|---|
| 728 | | - * LED triggers are compiled in. |
|---|
| 729 | | - */ |
|---|
| 730 | | -static const struct { |
|---|
| 731 | | - const char *name; |
|---|
| 732 | | - const char *trigger; |
|---|
| 733 | | -} assabet_leds[] = { |
|---|
| 734 | | - { "assabet:red", "cpu0",}, |
|---|
| 735 | | - { "assabet:green", "heartbeat", }, |
|---|
| 736 | | -}; |
|---|
| 737 | | - |
|---|
| 738 | | -/* |
|---|
| 739 | | - * The LED control in Assabet is reversed: |
|---|
| 740 | | - * - setting bit means turn off LED |
|---|
| 741 | | - * - clearing bit means turn on LED |
|---|
| 742 | | - */ |
|---|
| 743 | | -static void assabet_led_set(struct led_classdev *cdev, |
|---|
| 744 | | - enum led_brightness b) |
|---|
| 745 | | -{ |
|---|
| 746 | | - struct assabet_led *led = container_of(cdev, |
|---|
| 747 | | - struct assabet_led, cdev); |
|---|
| 748 | | - |
|---|
| 749 | | - if (b != LED_OFF) |
|---|
| 750 | | - ASSABET_BCR_clear(led->mask); |
|---|
| 751 | | - else |
|---|
| 752 | | - ASSABET_BCR_set(led->mask); |
|---|
| 753 | | -} |
|---|
| 754 | | - |
|---|
| 755 | | -static enum led_brightness assabet_led_get(struct led_classdev *cdev) |
|---|
| 756 | | -{ |
|---|
| 757 | | - struct assabet_led *led = container_of(cdev, |
|---|
| 758 | | - struct assabet_led, cdev); |
|---|
| 759 | | - |
|---|
| 760 | | - return (ASSABET_BCR & led->mask) ? LED_OFF : LED_FULL; |
|---|
| 761 | | -} |
|---|
| 762 | | - |
|---|
| 763 | | -static int __init assabet_leds_init(void) |
|---|
| 764 | | -{ |
|---|
| 765 | | - int i; |
|---|
| 766 | | - |
|---|
| 767 | | - if (!machine_is_assabet()) |
|---|
| 768 | | - return -ENODEV; |
|---|
| 769 | | - |
|---|
| 770 | | - for (i = 0; i < ARRAY_SIZE(assabet_leds); i++) { |
|---|
| 771 | | - struct assabet_led *led; |
|---|
| 772 | | - |
|---|
| 773 | | - led = kzalloc(sizeof(*led), GFP_KERNEL); |
|---|
| 774 | | - if (!led) |
|---|
| 775 | | - break; |
|---|
| 776 | | - |
|---|
| 777 | | - led->cdev.name = assabet_leds[i].name; |
|---|
| 778 | | - led->cdev.brightness_set = assabet_led_set; |
|---|
| 779 | | - led->cdev.brightness_get = assabet_led_get; |
|---|
| 780 | | - led->cdev.default_trigger = assabet_leds[i].trigger; |
|---|
| 781 | | - |
|---|
| 782 | | - if (!i) |
|---|
| 783 | | - led->mask = ASSABET_BCR_LED_RED; |
|---|
| 784 | | - else |
|---|
| 785 | | - led->mask = ASSABET_BCR_LED_GREEN; |
|---|
| 786 | | - |
|---|
| 787 | | - if (led_classdev_register(NULL, &led->cdev) < 0) { |
|---|
| 788 | | - kfree(led); |
|---|
| 789 | | - break; |
|---|
| 790 | | - } |
|---|
| 791 | | - } |
|---|
| 792 | | - |
|---|
| 793 | | - return 0; |
|---|
| 794 | | -} |
|---|
| 795 | | - |
|---|
| 796 | | -/* |
|---|
| 797 | | - * Since we may have triggers on any subsystem, defer registration |
|---|
| 798 | | - * until after subsystem_init. |
|---|
| 799 | | - */ |
|---|
| 800 | | -fs_initcall(assabet_leds_init); |
|---|
| 801 | | -#endif |
|---|
| 802 | | - |
|---|
| 803 | 740 | void __init assabet_init_irq(void) |
|---|
| 804 | 741 | { |
|---|
| 805 | 742 | unsigned int assabet_gpio_base; |
|---|
| .. | .. |
|---|
| 819 | 756 | */ |
|---|
| 820 | 757 | assabet_gpio_base = assabet_init_gpio((void *)&ASSABET_BCR, def_val); |
|---|
| 821 | 758 | |
|---|
| 822 | | - assabet_cf_vcc_pdata.gpio = assabet_gpio_base + 0; |
|---|
| 759 | + assabet_leds[0].gpio = assabet_gpio_base + 13; |
|---|
| 760 | + assabet_leds[1].gpio = assabet_gpio_base + 14; |
|---|
| 823 | 761 | } |
|---|
| 824 | 762 | |
|---|
| 825 | 763 | MACHINE_START(ASSABET, "Intel-Assabet") |
|---|