Pull tty/serial driver updates from Greg KH: "Here is the big set of tty/serial driver changes for 5.12-rc1. Nothing huge, just lots of good cleanups and additions: - n_tty line discipline cleanups - vt core cleanups and reworks to make the code more "modern" - stm32 driver additions - tty led support added to the tty core and led layer - minor serial driver fixups and additions All of these have been in linux-next for a while with no reported issues" * tag 'tty-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (54 commits) serial: core: Remove BUG_ON(in_interrupt()) check vt_ioctl: Remove in_interrupt() check dt-bindings: serial: imx: Switch to my personal address vt: keyboard, use new API for keyboard_tasklet serial: stm32: improve platform_get_irq condition handling in init_port serial: ifx6x60: Remove driver for deprecated platform tty: fix up iterate_tty_read() EOVERFLOW handling tty: fix up hung_up_tty_read() conversion tty: fix up hung_up_tty_write() conversion tty: teach the n_tty ICANON case about the new "cookie continuations" too tty: teach n_tty line discipline about the new "cookie continuations" tty: clean up legacy leftovers from n_tty line discipline tty: implement read_iter tty: convert tty_ldisc_ops 'read()' function to take a kernel pointer serial: remove sirf prima/atlas driver serial: mxs-auart: Remove <asm/cacheflush.h> serial: mxs-auart: Remove serial_mxs_probe_dt() serial: fsl_lpuart: Use of_device_get_match_data() dt-bindings: serial: renesas,hscif: Add r8a779a0 support tty: serial: Drop unused efm32 serial driver ...
Unified · Split
| @@ -0,0 +1,6 @@ | |||
| 1 | What: /sys/class/leds/<led>/ttyname | ||
| 2 | Date: Dec 2020 | ||
| 3 | KernelVersion: 5.10 | ||
| 4 | Contact: linux-leds@vger.kernel.org | ||
| 5 | Description: | ||
| 6 | Specifies the tty device name of the triggering tty | ||
| @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 6 unmodified lines | |||
| 7 | title: Freescale i.MX Universal Asynchronous Receiver/Transmitter (UART) | 7 | title: Freescale i.MX Universal Asynchronous Receiver/Transmitter (UART) |
| 8 | 8 | ||
| 9 | maintainers: | 9 | maintainers: |
| 10 | - Fabio Estevam <fabio.estevam@nxp.com> | 10 | - Fabio Estevam <festevam@gmail.com> |
| 11 | 11 | ||
| 12 | allOf: | 12 | allOf: |
| 13 | - $ref: "serial.yaml" | 13 | - $ref: "serial.yaml" |
| @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 6 unmodified lines | |||
| 7 | title: Freescale MXS Application UART (AUART) | 7 | title: Freescale MXS Application UART (AUART) |
| 8 | 8 | ||
| 9 | maintainers: | 9 | maintainers: |
| 10 | - Fabio Estevam <fabio.estevam@nxp.com> | 10 | - Fabio Estevam <festevam@gmail.com> |
| 11 | 11 | ||
| 12 | allOf: | 12 | allOf: |
| 13 | - $ref: "serial.yaml" | 13 | - $ref: "serial.yaml" |
| @@ -51,6 +51,7 @@ properties: · 50 unmodified lines | |||
| 51 | - renesas,hscif-r8a77980 # R-Car V3H | 51 | - renesas,hscif-r8a77980 # R-Car V3H |
| 52 | - renesas,hscif-r8a77990 # R-Car E3 | 52 | - renesas,hscif-r8a77990 # R-Car E3 |
| 53 | - renesas,hscif-r8a77995 # R-Car D3 | 53 | - renesas,hscif-r8a77995 # R-Car D3 |
| 54 | - renesas,hscif-r8a779a0 # R-Car V3U | ||
| 54 | - const: renesas,rcar-gen3-hscif # R-Car Gen3 and RZ/G2 | 55 | - const: renesas,rcar-gen3-hscif # R-Car Gen3 and RZ/G2 |
| 55 | - const: renesas,hscif # generic HSCIF compatible UART | 56 | - const: renesas,hscif # generic HSCIF compatible UART |
| 56 | 57 | ||
| @@ -1,34 +0,0 @@ | |||
| 1 | * CSR SiRFprimaII/atlasVI Universal Synchronous Asynchronous Receiver/Transmitter * | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible : Should be "sirf,prima2-uart", "sirf, prima2-usp-uart", | ||
| 5 | "sirf,atlas7-uart" or "sirf,atlas7-usp-uart". | ||
| 6 | - reg : Offset and length of the register set for the device | ||
| 7 | - interrupts : Should contain uart interrupt | ||
| 8 | - fifosize : Should define hardware rx/tx fifo size | ||
| 9 | - clocks : Should contain uart clock number | ||
| 10 | |||
| 11 | Optional properties: | ||
| 12 | - uart-has-rtscts: we have hardware flow controller pins in hardware | ||
| 13 | - rts-gpios: RTS pin for USP-based UART if uart-has-rtscts is true | ||
| 14 | - cts-gpios: CTS pin for USP-based UART if uart-has-rtscts is true | ||
| 15 | |||
| 16 | Example: | ||
| 17 | |||
| 18 | uart0: uart@b0050000 { | ||
| 19 | cell-index = <0>; | ||
| 20 | compatible = "sirf,prima2-uart"; | ||
| 21 | reg = <0xb0050000 0x1000>; | ||
| 22 | interrupts = <17>; | ||
| 23 | fifosize = <128>; | ||
| 24 | clocks = <&clks 13>; | ||
| 25 | }; | ||
| 26 | |||
| 27 | On the board-specific dts, we can put rts-gpios and cts-gpios like | ||
| 28 | |||
| 29 | usp@b0090000 { | ||
| 30 | compatible = "sirf,prima2-usp-uart"; | ||
| 31 | uart-has-rtscts; | ||
| 32 | rts-gpios = <&gpio 15 0>; | ||
| 33 | cts-gpios = <&gpio 46 0>; | ||
| 34 | }; | ||
| @@ -50,11 +50,14 @@ properties: · 49 unmodified lines | |||
| 50 | minItems: 1 | 50 | minItems: 1 |
| 51 | maxItems: 2 | 51 | maxItems: 2 |
| 52 | 52 | ||
| 53 | cts-gpios: | 53 | # cts-gpios and rts-gpios properties can be used instead of 'uart-has-rtscts' |
| 54 | maxItems: 1 | 54 | # or 'st,hw-flow-ctrl' (deprecated) for making use of any gpio pins for flow |
| 55 | 55 | # control instead of dedicated pins. | |
| 56 | rts-gpios: | 56 | # |
| 57 | maxItems: 1 | 57 | # It should be noted that both cts-gpios/rts-gpios and 'uart-has-rtscts' or |
| 58 | # 'st,hw-flow-ctrl' (deprecated) properties cannot co-exist in a design. | ||
| 59 | cts-gpios: true | ||
| 60 | rts-gpios: true | ||
| 58 | 61 | ||
| 59 | wakeup-source: true | 62 | wakeup-source: true |
| 60 | 63 | ||
| @@ -68,7 +68,6 @@ There are debugfs parameters provided for serial communication. · 67 unmodified lines | |||
| 68 | * tty_status: Prints the bit-mask tty status information | 68 | * tty_status: Prints the bit-mask tty status information |
| 69 | 69 | ||
| 70 | - 0x01 - tty->warned is on. | 70 | - 0x01 - tty->warned is on. |
| 71 | - 0x02 - tty->low_latency is on. | ||
| 72 | - 0x04 - tty->packed is on. | 71 | - 0x04 - tty->packed is on. |
| 73 | - 0x08 - tty->flow_stopped is on. | 72 | - 0x08 - tty->flow_stopped is on. |
| 74 | - 0x10 - tty->hw_stopped is on. | 73 | - 0x10 - tty->hw_stopped is on. |
| @@ -152,7 +152,7 @@ static int spk_ttyio_initialise_ldisc(struct spk_synth *synth) · 151 unmodified lines | |||
| 152 | if (ret) | 152 | if (ret) |
| 153 | return ret; | 153 | return ret; |
| 154 | 154 | ||
| 155 | tty = tty_kopen(dev); | 155 | tty = tty_kopen_exclusive(dev); |
| 156 | if (IS_ERR(tty)) | 156 | if (IS_ERR(tty)) |
| 157 | return PTR_ERR(tty); | 157 | return PTR_ERR(tty); |
| 158 | 158 | ||
| @@ -801,7 +801,8 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file *file, · 800 unmodified lines | |||
| 801 | * We don't provide read/write/poll interface for user space. | 801 | * We don't provide read/write/poll interface for user space. |
| 802 | */ | 802 | */ |
| 803 | static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file, | 803 | static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file, |
| 804 | unsigned char __user *buf, size_t nr) | 804 | unsigned char *buf, size_t nr, |
| 805 | void **cookie, unsigned long offset) | ||
| 805 | { | 806 | { |
| 806 | return 0; | 807 | return 0; |
| 807 | } | 808 | } |
| @@ -818,29 +819,28 @@ static __poll_t hci_uart_tty_poll(struct tty_struct *tty, · 10 unmodified lines | |||
| 818 | return 0; | 819 | return 0; |
| 819 | } | 820 | } |
| 820 | 821 | ||
| 822 | static struct tty_ldisc_ops hci_uart_ldisc = { | ||
| 823 | .owner = THIS_MODULE, | ||
| 824 | .magic = TTY_LDISC_MAGIC, | ||
| 825 | .name = "n_hci", | ||
| 826 | .open = hci_uart_tty_open, | ||
| 827 | .close = hci_uart_tty_close, | ||
| 828 | .read = hci_uart_tty_read, | ||
| 829 | .write = hci_uart_tty_write, | ||
| 830 | .ioctl = hci_uart_tty_ioctl, | ||
| 831 | .compat_ioctl = hci_uart_tty_ioctl, | ||
| 832 | .poll = hci_uart_tty_poll, | ||
| 833 | .receive_buf = hci_uart_tty_receive, | ||
| 834 | .write_wakeup = hci_uart_tty_wakeup, | ||
| 835 | }; | ||
| 836 | |||
| 821 | static int __init hci_uart_init(void) | 837 | static int __init hci_uart_init(void) |
| 822 | { | 838 | { |
| 823 | static struct tty_ldisc_ops hci_uart_ldisc; | ||
| 824 | int err; | 839 | int err; |
| 825 | 840 | ||
| 826 | BT_INFO("HCI UART driver ver %s", VERSION); | 841 | BT_INFO("HCI UART driver ver %s", VERSION); |
| 827 | 842 | ||
| 828 | /* Register the tty discipline */ | 843 | /* Register the tty discipline */ |
| 829 | |||
| 830 | memset(&hci_uart_ldisc, 0, sizeof(hci_uart_ldisc)); | ||
| 831 | hci_uart_ldisc.magic = TTY_LDISC_MAGIC; | ||
| 832 | hci_uart_ldisc.name = "n_hci"; | ||
| 833 | hci_uart_ldisc.open = hci_uart_tty_open; | ||
| 834 | hci_uart_ldisc.close = hci_uart_tty_close; | ||
| 835 | hci_uart_ldisc.read = hci_uart_tty_read; | ||
| 836 | hci_uart_ldisc.write = hci_uart_tty_write; | ||
| 837 | hci_uart_ldisc.ioctl = hci_uart_tty_ioctl; | ||
| 838 | hci_uart_ldisc.compat_ioctl = hci_uart_tty_ioctl; | ||
| 839 | hci_uart_ldisc.poll = hci_uart_tty_poll; | ||
| 840 | hci_uart_ldisc.receive_buf = hci_uart_tty_receive; | ||
| 841 | hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup; | ||
| 842 | hci_uart_ldisc.owner = THIS_MODULE; | ||
| 843 | |||
| 844 | err = tty_register_ldisc(N_HCI, &hci_uart_ldisc); | 844 | err = tty_register_ldisc(N_HCI, &hci_uart_ldisc); |
| 845 | if (err) { | 845 | if (err) { |
| 846 | BT_ERR("HCI line discipline registration failed. (%d)", err); | 846 | BT_ERR("HCI line discipline registration failed. (%d)", err); |
| @@ -2494,8 +2494,6 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) · 2493 unmodified lines | |||
| 2494 | printk("%s(%d):mgslpc_open(%s), old ref count = %d\n", | 2494 | printk("%s(%d):mgslpc_open(%s), old ref count = %d\n", |
| 2495 | __FILE__, __LINE__, tty->driver->name, port->count); | 2495 | __FILE__, __LINE__, tty->driver->name, port->count); |
| 2496 | 2496 | ||
| 2497 | port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | ||
| 2498 | |||
| 2499 | spin_lock_irqsave(&info->netlock, flags); | 2497 | spin_lock_irqsave(&info->netlock, flags); |
| 2500 | if (info->netcount) { | 2498 | if (info->netcount) { |
| 2501 | retval = -EBUSY; | 2499 | retval = -EBUSY; |
| @@ -156,7 +156,9 @@ out: · 155 unmodified lines | |||
| 156 | * returning 0 characters. | 156 | * returning 0 characters. |
| 157 | */ | 157 | */ |
| 158 | 158 | ||
| 159 | static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, unsigned char __user * buf, size_t nr) | 159 | static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, |
| 160 | unsigned char *kbuf, size_t nr, | ||
| 161 | void **cookie, unsigned long offset) | ||
| 160 | { | 162 | { |
| 161 | struct serport *serport = (struct serport*) tty->disc_data; | 163 | struct serport *serport = (struct serport*) tty->disc_data; |
| 162 | struct serio *serio; | 164 | struct serio *serio; |
| @@ -144,4 +144,13 @@ config LEDS_TRIGGER_AUDIO · 143 unmodified lines | |||
| 144 | the audio mute and mic-mute changes. | 144 | the audio mute and mic-mute changes. |
| 145 | If unsure, say N | 145 | If unsure, say N |
| 146 | 146 | ||
| 147 | config LEDS_TRIGGER_TTY | ||
| 148 | tristate "LED Trigger for TTY devices" | ||
| 149 | depends on TTY | ||
| 150 | help | ||
| 151 | This allows LEDs to be controlled by activity on ttys which includes | ||
| 152 | serial devices like /dev/ttyS0. | ||
| 153 | |||
| 154 | When build as a module this driver will be called ledtrig-tty. | ||
| 155 | |||
| 147 | endif # LEDS_TRIGGERS | 156 | endif # LEDS_TRIGGERS |
| @@ -15,3 +15,4 @@ obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o · 14 unmodified lines | |||
| 15 | obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o | 15 | obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o |
| 16 | obj-$(CONFIG_LEDS_TRIGGER_PATTERN) += ledtrig-pattern.o | 16 | obj-$(CONFIG_LEDS_TRIGGER_PATTERN) += ledtrig-pattern.o |
| 17 | obj-$(CONFIG_LEDS_TRIGGER_AUDIO) += ledtrig-audio.o | 17 | obj-$(CONFIG_LEDS_TRIGGER_AUDIO) += ledtrig-audio.o |
| 18 | obj-$(CONFIG_LEDS_TRIGGER_TTY) += ledtrig-tty.o | ||
| @@ -0,0 +1,183 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | #include <linux/delay.h> | ||
| 4 | #include <linux/leds.h> | ||
| 5 | #include <linux/module.h> | ||
| 6 | #include <linux/slab.h> | ||
| 7 | #include <linux/tty.h> | ||
| 8 | #include <uapi/linux/serial.h> | ||
| 9 | |||
| 10 | struct ledtrig_tty_data { | ||
| 11 | struct led_classdev *led_cdev; | ||
| 12 | struct delayed_work dwork; | ||
| 13 | struct mutex mutex; | ||
| 14 | const char *ttyname; | ||
| 15 | struct tty_struct *tty; | ||
| 16 | int rx, tx; | ||
| 17 | }; | ||
| 18 | |||
| 19 | static void ledtrig_tty_restart(struct ledtrig_tty_data *trigger_data) | ||
| 20 | { | ||
| 21 | schedule_delayed_work(&trigger_data->dwork, 0); | ||
| 22 | } | ||
| 23 | |||
| 24 | static ssize_t ttyname_show(struct device *dev, | ||
| 25 | struct device_attribute *attr, char *buf) | ||
| 26 | { | ||
| 27 | struct ledtrig_tty_data *trigger_data = led_trigger_get_drvdata(dev); | ||
| 28 | ssize_t len = 0; | ||
| 29 | |||
| 30 | mutex_lock(&trigger_data->mutex); | ||
| 31 | |||
| 32 | if (trigger_data->ttyname) | ||
| 33 | len = sprintf(buf, "%s\n", trigger_data->ttyname); | ||
| 34 | |||
| 35 | mutex_unlock(&trigger_data->mutex); | ||
| 36 | |||
| 37 | return len; | ||
| 38 | } | ||
| 39 | |||
| 40 | static ssize_t ttyname_store(struct device *dev, | ||
| 41 | struct device_attribute *attr, const char *buf, | ||
| 42 | size_t size) | ||
| 43 | { | ||
| 44 | struct ledtrig_tty_data *trigger_data = led_trigger_get_drvdata(dev); | ||
| 45 | char *ttyname; | ||
| 46 | ssize_t ret = size; | ||
| 47 | bool running; | ||
| 48 | |||
| 49 | if (size > 0 && buf[size - 1] == '\n') | ||
| 50 | size -= 1; | ||
| 51 | |||
| 52 | if (size) { | ||
| 53 | ttyname = kmemdup_nul(buf, size, GFP_KERNEL); | ||
| 54 | if (!ttyname) { | ||
| 55 | ret = -ENOMEM; | ||
| 56 | goto out_unlock; | ||
| 57 | } | ||
| 58 | } else { | ||
| 59 | ttyname = NULL; | ||
| 60 | } | ||
| 61 | |||
| 62 | mutex_lock(&trigger_data->mutex); | ||
| 63 | |||
| 64 | running = trigger_data->ttyname != NULL; | ||
| 65 | |||
| 66 | kfree(trigger_data->ttyname); | ||
| 67 | tty_kref_put(trigger_data->tty); | ||
| 68 | trigger_data->tty = NULL; | ||
| 69 | |||
| 70 | trigger_data->ttyname = ttyname; | ||
| 71 | |||
| 72 | out_unlock: | ||
| 73 | mutex_unlock(&trigger_data->mutex); | ||
| 74 | |||
| 75 | if (ttyname && !running) | ||
| 76 | ledtrig_tty_restart(trigger_data); | ||
| 77 | |||
| 78 | return ret; | ||
| 79 | } | ||
| 80 | static DEVICE_ATTR_RW(ttyname); | ||
| 81 | |||
| 82 | static void ledtrig_tty_work(struct work_struct *work) | ||
| 83 | { | ||
| 84 | struct ledtrig_tty_data *trigger_data = | ||
| 85 | container_of(work, struct ledtrig_tty_data, dwork.work); | ||
| 86 | struct serial_icounter_struct icount; | ||
| 87 | int ret; | ||
| 88 | |||
| 89 | mutex_lock(&trigger_data->mutex); | ||
| 90 | |||
| 91 | if (!trigger_data->ttyname) { | ||
| 92 | /* exit without rescheduling */ | ||
| 93 | mutex_unlock(&trigger_data->mutex); | ||
| 94 | return; | ||
| 95 | } | ||
| 96 | |||
| 97 | /* try to get the tty corresponding to $ttyname */ | ||
| 98 | if (!trigger_data->tty) { | ||
| 99 | dev_t devno; | ||
| 100 | struct tty_struct *tty; | ||
| 101 | int ret; | ||
| 102 | |||
| 103 | ret = tty_dev_name_to_number(trigger_data->ttyname, &devno); | ||
| 104 | if (ret < 0) | ||
| 105 | /* | ||
| 106 | * A device with this name might appear later, so keep | ||
| 107 | * retrying. | ||
| 108 | */ | ||
| 109 | goto out; | ||
| 110 | |||
| 111 | tty = tty_kopen_shared(devno); | ||
| 112 | if (IS_ERR(tty) || !tty) | ||
| 113 | /* What to do? retry or abort */ | ||
| 114 | goto out; | ||
| 115 | |||
| 116 | trigger_data->tty = tty; | ||
| 117 | } | ||
| 118 | |||
| 119 | ret = tty_get_icount(trigger_data->tty, &icount); | ||
| 120 | if (ret) { | ||
| 121 | dev_info(trigger_data->tty->dev, "Failed to get icount, stopped polling\n"); | ||
| 122 | mutex_unlock(&trigger_data->mutex); | ||
| 123 | return; | ||
| 124 | } | ||
| 125 | |||
| 126 | if (icount.rx != trigger_data->rx || | ||
| 127 | icount.tx != trigger_data->tx) { | ||
| 128 | led_set_brightness(trigger_data->led_cdev, LED_ON); | ||
| 129 | |||
| 130 | trigger_data->rx = icount.rx; | ||
| 131 | trigger_data->tx = icount.tx; | ||
| 132 | } else { | ||
| 133 | led_set_brightness(trigger_data->led_cdev, LED_OFF); | ||
| 134 | } | ||
| 135 | |||
| 136 | out: | ||
| 137 | mutex_unlock(&trigger_data->mutex); | ||
| 138 | schedule_delayed_work(&trigger_data->dwork, msecs_to_jiffies(100)); | ||
| 139 | } | ||
| 140 | |||
| 141 | static struct attribute *ledtrig_tty_attrs[] = { | ||
| 142 | &dev_attr_ttyname.attr, | ||
| 143 | NULL | ||
| 144 | }; | ||
| 145 | ATTRIBUTE_GROUPS(ledtrig_tty); | ||
| 146 | |||
| 147 | static int ledtrig_tty_activate(struct led_classdev *led_cdev) | ||
| 148 | { | ||
| 149 | struct ledtrig_tty_data *trigger_data; | ||
| 150 | |||
| 151 | trigger_data = kzalloc(sizeof(*trigger_data), GFP_KERNEL); | ||
| 152 | if (!trigger_data) | ||
| 153 | return -ENOMEM; | ||
| 154 | |||
| 155 | led_set_trigger_data(led_cdev, trigger_data); | ||
| 156 | |||
| 157 | INIT_DELAYED_WORK(&trigger_data->dwork, ledtrig_tty_work); | ||
| 158 | trigger_data->led_cdev = led_cdev; | ||
| 159 | mutex_init(&trigger_data->mutex); | ||
| 160 | |||
| 161 | return 0; | ||
| 162 | } | ||
| 163 | |||
| 164 | static void ledtrig_tty_deactivate(struct led_classdev *led_cdev) | ||
| 165 | { | ||
| 166 | struct ledtrig_tty_data *trigger_data = led_get_trigger_data(led_cdev); | ||
| 167 | |||
| 168 | cancel_delayed_work_sync(&trigger_data->dwork); | ||
| 169 | |||
| 170 | kfree(trigger_data); | ||
| 171 | } | ||
| 172 | |||
| 173 | static struct led_trigger ledtrig_tty = { | ||
| 174 | .name = "tty", | ||
| 175 | .activate = ledtrig_tty_activate, | ||
| 176 | .deactivate = ledtrig_tty_deactivate, | ||
| 177 | .groups = ledtrig_tty_groups, | ||
| 178 | }; | ||
| 179 | module_led_trigger(ledtrig_tty); | ||
| 180 | |||
| 181 | MODULE_AUTHOR("Uwe Kleine-König <u.kleine-koenig@pengutronix.de>"); | ||
| 182 | MODULE_DESCRIPTION("UART LED trigger"); | ||
| 183 | MODULE_LICENSE("GPL v2"); | ||
| @@ -89,8 +89,7 @@ static inline void update_tty_status(struct ser_device *ser) · 88 unmodified lines | |||
| 89 | ser->tty_status = | 89 | ser->tty_status = |
| 90 | ser->tty->stopped << 5 | | 90 | ser->tty->stopped << 5 | |
| 91 | ser->tty->flow_stopped << 3 | | 91 | ser->tty->flow_stopped << 3 | |
| 92 | ser->tty->packet << 2 | | 92 | ser->tty->packet << 2; |
| 93 | ser->tty->port->low_latency << 1; | ||
| 94 | } | 93 | } |
| 95 | static inline void debugfs_init(struct ser_device *ser, struct tty_struct *tty) | 94 | static inline void debugfs_init(struct ser_device *ser, struct tty_struct *tty) |
| 96 | { | 95 | { |
| @@ -259,7 +259,8 @@ static int ppp_asynctty_hangup(struct tty_struct *tty) · 258 unmodified lines | |||
| 259 | */ | 259 | */ |
| 260 | static ssize_t | 260 | static ssize_t |
| 261 | ppp_asynctty_read(struct tty_struct *tty, struct file *file, | 261 | ppp_asynctty_read(struct tty_struct *tty, struct file *file, |
| 262 | unsigned char __user *buf, size_t count) | 262 | unsigned char *buf, size_t count, |
| 263 | void **cookie, unsigned long offset) | ||
| 263 | { | 264 | { |
| 264 | return -EAGAIN; | 265 | return -EAGAIN; |
| 265 | } | 266 | } |
| @@ -257,7 +257,8 @@ static int ppp_sync_hangup(struct tty_struct *tty) · 256 unmodified lines | |||
| 257 | */ | 257 | */ |
| 258 | static ssize_t | 258 | static ssize_t |
| 259 | ppp_sync_read(struct tty_struct *tty, struct file *file, | 259 | ppp_sync_read(struct tty_struct *tty, struct file *file, |
| 260 | unsigned char __user *buf, size_t count) | 260 | unsigned char *buf, size_t count, |
| 261 | void **cookie, unsigned long offset) | ||
| 261 | { | 262 | { |
| 262 | return -EAGAIN; | 263 | return -EAGAIN; |
| 263 | } | 264 | } |
| @@ -914,7 +914,6 @@ static int tty3215_open(struct tty_struct *tty, struct file * filp) · 913 unmodified lines | |||
| 914 | 914 | ||
| 915 | tty_port_tty_set(&raw->port, tty); | 915 | tty_port_tty_set(&raw->port, tty); |
| 916 | 916 | ||
| 917 | raw->port.low_latency = 0; /* don't use bottom half for pushing chars */ | ||
| 918 | /* | 917 | /* |
| 919 | * Start up 3215 device | 918 | * Start up 3215 device |
| 920 | */ | 919 | */ |
| @@ -65,7 +65,6 @@ sclp_tty_open(struct tty_struct *tty, struct file *filp) · 64 unmodified lines | |||
| 65 | { | 65 | { |
| 66 | tty_port_tty_set(&sclp_port, tty); | 66 | tty_port_tty_set(&sclp_port, tty); |
| 67 | tty->driver_data = NULL; | 67 | tty->driver_data = NULL; |
| 68 | sclp_port.low_latency = 0; | ||
| 69 | return 0; | 68 | return 0; |
| 70 | } | 69 | } |
| 71 | 70 | ||
| @@ -560,7 +560,6 @@ sclp_vt220_open(struct tty_struct *tty, struct file *filp) · 559 unmodified lines | |||
| 560 | { | 560 | { |
| 561 | if (tty->count == 1) { | 561 | if (tty->count == 1) { |
| 562 | tty_port_tty_set(&sclp_vt220_port, tty); | 562 | tty_port_tty_set(&sclp_vt220_port, tty); |
| 563 | sclp_vt220_port.low_latency = 0; | ||
| 564 | if (!tty->winsize.ws_row && !tty->winsize.ws_col) { | 563 | if (!tty->winsize.ws_row && !tty->winsize.ws_col) { |
| 565 | tty->winsize.ws_row = 24; | 564 | tty->winsize.ws_row = 24; |
| 566 | tty->winsize.ws_col = 80; | 565 | tty->winsize.ws_col = 80; |
| @@ -967,7 +967,6 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty) · 966 unmodified lines | |||
| 967 | tty->driver_data = tp; | 967 | tty->driver_data = tp; |
| 968 | tty->winsize.ws_row = tp->view.rows - 2; | 968 | tty->winsize.ws_row = tp->view.rows - 2; |
| 969 | tty->winsize.ws_col = tp->view.cols; | 969 | tty->winsize.ws_col = tp->view.cols; |
| 970 | tp->port.low_latency = 0; | ||
| 971 | tp->inattr = TF_INPUT; | 970 | tp->inattr = TF_INPUT; |
| 972 | goto port_install; | 971 | goto port_install; |
| 973 | } | 972 | } |
| @@ -996,7 +995,6 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty) · 22 unmodified lines | |||
| 996 | return rc; | 995 | return rc; |
| 997 | } | 996 | } |
| 998 | 997 | ||
| 999 | tp->port.low_latency = 0; | ||
| 1000 | tty->winsize.ws_row = tp->view.rows - 2; | 998 | tty->winsize.ws_row = tp->view.rows - 2; |
| 1001 | tty->winsize.ws_col = tp->view.cols; | 999 | tty->winsize.ws_col = tp->view.cols; |
| 1002 | 1000 | ||
| @@ -998,7 +998,6 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss) · 997 unmodified lines | |||
| 998 | state->custom_divisor = ss->custom_divisor; | 998 | state->custom_divisor = ss->custom_divisor; |
| 999 | port->close_delay = ss->close_delay * HZ/100; | 999 | port->close_delay = ss->close_delay * HZ/100; |
| 1000 | port->closing_wait = ss->closing_wait * HZ/100; | 1000 | port->closing_wait = ss->closing_wait * HZ/100; |
| 1001 | port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | ||
| 1002 | 1001 | ||
| 1003 | check_and_exit: | 1002 | check_and_exit: |
| 1004 | if (tty_port_initialized(port)) { | 1003 | if (tty_port_initialized(port)) { |
| @@ -1386,8 +1385,6 @@ static int rs_open(struct tty_struct *tty, struct file * filp) · 381 unmodified lines | |||
| 1386 | tty->driver_data = info; | 1385 | tty->driver_data = info; |
| 1387 | tty->port = port; | 1386 | tty->port = port; |
| 1388 | 1387 | ||
| 1389 | port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | ||
| 1390 | |||
| 1391 | retval = startup(tty, info); | 1388 | retval = startup(tty, info); |
| 1392 | if (retval) { | 1389 | if (retval) { |
| 1393 | return retval; | 1390 | return retval; |
| @@ -605,7 +605,7 @@ static int hvcs_io(struct hvcs_struct *hvcsd) · 604 unmodified lines | |||
| 605 | hvcsd->todo_mask |= HVCS_QUICK_READ; | 605 | hvcsd->todo_mask |= HVCS_QUICK_READ; |
| 606 | 606 | ||
| 607 | spin_unlock_irqrestore(&hvcsd->lock, flags); | 607 | spin_unlock_irqrestore(&hvcsd->lock, flags); |
| 608 | /* This is synch because tty->low_latency == 1 */ | 608 | /* This is synch -- FIXME :js: it is not! */ |
| 609 | if(got) | 609 | if(got) |
| 610 | tty_flip_buffer_push(&hvcsd->port); | 610 | tty_flip_buffer_push(&hvcsd->port); |
| 611 | 611 | ||
| @@ -825,9 +825,6 @@ static int hvcs_remove(struct vio_dev *dev) · 213 unmodified lines | |||
| 825 | unsigned long flags; | 825 | unsigned long flags; |
| 826 | struct tty_struct *tty; | 826 | struct tty_struct *tty; |
| 827 | 827 | ||
| 828 | if (!hvcsd) | ||
| 829 | return -ENODEV; | ||
| 830 | |||
| 831 | /* By this time the vty-server won't be getting any more interrupts */ | 828 | /* By this time the vty-server won't be getting any more interrupts */ |
| 832 | 829 | ||
| 833 | spin_lock_irqsave(&hvcsd->lock, flags); | 830 | spin_lock_irqsave(&hvcsd->lock, flags); |
| @@ -101,7 +101,6 @@ static int ipw_open(struct tty_struct *linux_tty, struct file *filp) · 100 unmodified lines | |||
| 101 | 101 | ||
| 102 | tty->port.tty = linux_tty; | 102 | tty->port.tty = linux_tty; |
| 103 | linux_tty->driver_data = tty; | 103 | linux_tty->driver_data = tty; |
| 104 | tty->port.low_latency = 1; | ||
| 105 | 104 | ||
| 106 | if (tty->tty_type == TTYTYPE_MODEM) | 105 | if (tty->tty_type == TTYTYPE_MODEM) |
| 107 | ipwireless_ppp_open(tty->network); | 106 | ipwireless_ppp_open(tty->network); |
| @@ -1273,7 +1273,6 @@ static int mxser_set_serial_info(struct tty_struct *tty, · 1272 unmodified lines | |||
| 1273 | (ss->flags & ASYNC_FLAGS)); | 1273 | (ss->flags & ASYNC_FLAGS)); |
| 1274 | port->close_delay = ss->close_delay * HZ / 100; | 1274 | port->close_delay = ss->close_delay * HZ / 100; |
| 1275 | port->closing_wait = ss->closing_wait * HZ / 100; | 1275 | port->closing_wait = ss->closing_wait * HZ / 100; |
| 1276 | port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | ||
| 1277 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && | 1276 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && |
| 1278 | (ss->baud_base != info->baud_base || | 1277 | (ss->baud_base != info->baud_base || |
| 1279 | ss->custom_divisor != | 1278 | ss->custom_divisor != |
| @@ -2559,7 +2559,8 @@ static void gsmld_write_wakeup(struct tty_struct *tty) · 2558 unmodified lines | |||
| 2559 | */ | 2559 | */ |
| 2560 | 2560 | ||
| 2561 | static ssize_t gsmld_read(struct tty_struct *tty, struct file *file, | 2561 | static ssize_t gsmld_read(struct tty_struct *tty, struct file *file, |
| 2562 | unsigned char __user *buf, size_t nr) | 2562 | unsigned char *buf, size_t nr, |
| 2563 | void **cookie, unsigned long offset) | ||
| 2563 | { | 2564 | { |
| 2564 | return -EOPNOTSUPP; | 2565 | return -EOPNOTSUPP; |
| 2565 | } | 2566 | } |
| @@ -416,13 +416,19 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data, · 415 unmodified lines | |||
| 416 | * Returns the number of bytes returned or error code. | 416 | * Returns the number of bytes returned or error code. |
| 417 | */ | 417 | */ |
| 418 | static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, | 418 | static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, |
| 419 | __u8 __user *buf, size_t nr) | 419 | __u8 *kbuf, size_t nr, |
| 420 | void **cookie, unsigned long offset) | ||
| 420 | { | 421 | { |
| 421 | struct n_hdlc *n_hdlc = tty->disc_data; | 422 | struct n_hdlc *n_hdlc = tty->disc_data; |
| 422 | int ret = 0; | 423 | int ret = 0; |
| 423 | struct n_hdlc_buf *rbuf; | 424 | struct n_hdlc_buf *rbuf; |
| 424 | DECLARE_WAITQUEUE(wait, current); | 425 | DECLARE_WAITQUEUE(wait, current); |
| 425 | 426 | ||
| 427 | /* Is this a repeated call for an rbuf we already found earlier? */ | ||
| 428 | rbuf = *cookie; | ||
| 429 | if (rbuf) | ||
| 430 | goto have_rbuf; | ||
| 431 | |||
| 426 | add_wait_queue(&tty->read_wait, &wait); | 432 | add_wait_queue(&tty->read_wait, &wait); |
| 427 | 433 | ||
| 428 | for (;;) { | 434 | for (;;) { |
| @@ -436,25 +442,8 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, · 7 unmodified lines | |||
| 436 | set_current_state(TASK_INTERRUPTIBLE); | 442 | set_current_state(TASK_INTERRUPTIBLE); |
| 437 | 443 | ||
| 438 | rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list); | 444 | rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list); |
| 439 | if (rbuf) { | 445 | if (rbuf) |
| 440 | if (rbuf->count > nr) { | ||
| 441 | /* too large for caller's buffer */ | ||
| 442 | ret = -EOVERFLOW; | ||
| 443 | } else { | ||
| 444 | __set_current_state(TASK_RUNNING); | ||
| 445 | if (copy_to_user(buf, rbuf->buf, rbuf->count)) | ||
| 446 | ret = -EFAULT; | ||
| 447 | else | ||
| 448 | ret = rbuf->count; | ||
| 449 | } | ||
| 450 | |||
| 451 | if (n_hdlc->rx_free_buf_list.count > | ||
| 452 | DEFAULT_RX_BUF_COUNT) | ||
| 453 | kfree(rbuf); | ||
| 454 | else | ||
| 455 | n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, rbuf); | ||
| 456 | break; | 446 | break; |
| 457 | } | ||
| 458 | 447 | ||
| 459 | /* no data */ | 448 | /* no data */ |
| 460 | if (tty_io_nonblock(tty, file)) { | 449 | if (tty_io_nonblock(tty, file)) { |
| @@ -473,6 +462,39 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, · 12 unmodified lines | |||
| 473 | remove_wait_queue(&tty->read_wait, &wait); | 462 | remove_wait_queue(&tty->read_wait, &wait); |
| 474 | __set_current_state(TASK_RUNNING); | 463 | __set_current_state(TASK_RUNNING); |
| 475 | 464 | ||
| 465 | if (!rbuf) | ||
| 466 | return ret; | ||
| 467 | *cookie = rbuf; | ||
| 468 | |||
| 469 | have_rbuf: | ||
| 470 | /* Have we used it up entirely? */ | ||
| 471 | if (offset >= rbuf->count) | ||
| 472 | goto done_with_rbuf; | ||
| 473 | |||
| 474 | /* More data to go, but can't copy any more? EOVERFLOW */ | ||
| 475 | ret = -EOVERFLOW; | ||
| 476 | if (!nr) | ||
| 477 | goto done_with_rbuf; | ||
| 478 | |||
| 479 | /* Copy as much data as possible */ | ||
| 480 | ret = rbuf->count - offset; | ||
| 481 | if (ret > nr) | ||
| 482 | ret = nr; | ||
| 483 | memcpy(kbuf, rbuf->buf+offset, ret); | ||
| 484 | offset += ret; | ||
| 485 | |||
| 486 | /* If we still have data left, we leave the rbuf in the cookie */ | ||
| 487 | if (offset < rbuf->count) | ||
| 488 | return ret; | ||
| 489 | |||
| 490 | done_with_rbuf: | ||
| 491 | *cookie = NULL; | ||
| 492 | |||
| 493 | if (n_hdlc->rx_free_buf_list.count > DEFAULT_RX_BUF_COUNT) | ||
| 494 | kfree(rbuf); | ||
| 495 | else | ||
| 496 | n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, rbuf); | ||
| 497 | |||
| 476 | return ret; | 498 | return ret; |
| 477 | 499 | ||
| 478 | } /* end of n_hdlc_tty_read() */ | 500 | } /* end of n_hdlc_tty_read() */ |
| @@ -20,7 +20,8 @@ static void n_null_close(struct tty_struct *tty) · 19 unmodified lines | |||
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | static ssize_t n_null_read(struct tty_struct *tty, struct file *file, | 22 | static ssize_t n_null_read(struct tty_struct *tty, struct file *file, |
| 23 | unsigned char __user * buf, size_t nr) | 23 | unsigned char *buf, size_t nr, |
| 24 | void **cookie, unsigned long offset) | ||
| 24 | { | 25 | { |
| 25 | return -EOPNOTSUPP; | 26 | return -EOPNOTSUPP; |
| 26 | } | 27 | } |
| @@ -129,7 +129,7 @@ static void remove_client_block(struct r3964_info *pInfo, · 128 unmodified lines | |||
| 129 | static int r3964_open(struct tty_struct *tty); | 129 | static int r3964_open(struct tty_struct *tty); |
| 130 | static void r3964_close(struct tty_struct *tty); | 130 | static void r3964_close(struct tty_struct *tty); |
| 131 | static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | 131 | static ssize_t r3964_read(struct tty_struct *tty, struct file *file, |
| 132 | unsigned char __user * buf, size_t nr); | 132 | void *cookie, unsigned char *buf, size_t nr); |
| 133 | static ssize_t r3964_write(struct tty_struct *tty, struct file *file, | 133 | static ssize_t r3964_write(struct tty_struct *tty, struct file *file, |
| 134 | const unsigned char *buf, size_t nr); | 134 | const unsigned char *buf, size_t nr); |
| 135 | static int r3964_ioctl(struct tty_struct *tty, struct file *file, | 135 | static int r3964_ioctl(struct tty_struct *tty, struct file *file, |
| @@ -1058,7 +1058,8 @@ static void r3964_close(struct tty_struct *tty) · 922 unmodified lines | |||
| 1058 | } | 1058 | } |
| 1059 | 1059 | ||
| 1060 | static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | 1060 | static ssize_t r3964_read(struct tty_struct *tty, struct file *file, |
| 1061 | unsigned char __user * buf, size_t nr) | 1061 | unsigned char *kbuf, size_t nr, |
| 1062 | void **cookie, unsigned long offset) | ||
| 1062 | { | 1063 | { |
| 1063 | struct r3964_info *pInfo = tty->disc_data; | 1064 | struct r3964_info *pInfo = tty->disc_data; |
| 1064 | struct r3964_client_info *pClient; | 1065 | struct r3964_client_info *pClient; |
| @@ -1109,10 +1110,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, · 44 unmodified lines | |||
| 1109 | kfree(pMsg); | 1110 | kfree(pMsg); |
| 1110 | TRACE_M("r3964_read - msg kfree %p", pMsg); | 1111 | TRACE_M("r3964_read - msg kfree %p", pMsg); |
| 1111 | 1112 | ||
| 1112 | if (copy_to_user(buf, &theMsg, ret)) { | 1113 | memcpy(kbuf, &theMsg, ret); |
| 1113 | ret = -EFAULT; | ||
| 1114 | goto unlock; | ||
| 1115 | } | ||
| 1116 | 1114 | ||
| 1117 | TRACE_PS("read - return %d", ret); | 1115 | TRACE_PS("read - return %d", ret); |
| 1118 | goto unlock; | 1116 | goto unlock; |
| @@ -118,7 +118,9 @@ static void n_tracerouter_close(struct tty_struct *tty) · 117 unmodified lines | |||
| 118 | * -EINVAL | 118 | * -EINVAL |
| 119 | */ | 119 | */ |
| 120 | static ssize_t n_tracerouter_read(struct tty_struct *tty, struct file *file, | 120 | static ssize_t n_tracerouter_read(struct tty_struct *tty, struct file *file, |
| 121 | unsigned char __user *buf, size_t nr) { | 121 | unsigned char *buf, size_t nr, |
| 122 | void **cookie, unsigned long offset) | ||
| 123 | { | ||
| 122 | return -EINVAL; | 124 | return -EINVAL; |
| 123 | } | 125 | } |
| 124 | 126 | ||
| @@ -115,7 +115,9 @@ static void n_tracesink_close(struct tty_struct *tty) · 114 unmodified lines | |||
| 115 | * -EINVAL | 115 | * -EINVAL |
| 116 | */ | 116 | */ |
| 117 | static ssize_t n_tracesink_read(struct tty_struct *tty, struct file *file, | 117 | static ssize_t n_tracesink_read(struct tty_struct *tty, struct file *file, |
| 118 | unsigned char __user *buf, size_t nr) { | 118 | unsigned char *buf, size_t nr, |
| 119 | void **cookie, unsigned long offset) | ||
| 120 | { | ||
| 119 | return -EINVAL; | 121 | return -EINVAL; |
| 120 | } | 122 | } |
| 121 | 123 | ||
| @@ -164,29 +164,24 @@ static void zero_buffer(struct tty_struct *tty, u8 *buffer, int size) · 163 unmodified lines | |||
| 164 | memset(buffer, 0x00, size); | 164 | memset(buffer, 0x00, size); |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | static int tty_copy_to_user(struct tty_struct *tty, void __user *to, | 167 | static void tty_copy(struct tty_struct *tty, void *to, size_t tail, size_t n) |
| 168 | size_t tail, size_t n) | ||
| 169 | { | 168 | { |
| 170 | struct n_tty_data *ldata = tty->disc_data; | 169 | struct n_tty_data *ldata = tty->disc_data; |
| 171 | size_t size = N_TTY_BUF_SIZE - tail; | 170 | size_t size = N_TTY_BUF_SIZE - tail; |
| 172 | void *from = read_buf_addr(ldata, tail); | 171 | void *from = read_buf_addr(ldata, tail); |
| 173 | int uncopied; | ||
| 174 | 172 | ||
| 175 | if (n > size) { | 173 | if (n > size) { |
| 176 | tty_audit_add_data(tty, from, size); | 174 | tty_audit_add_data(tty, from, size); |
| 177 | uncopied = copy_to_user(to, from, size); | 175 | memcpy(to, from, size); |
| 178 | zero_buffer(tty, from, size - uncopied); | 176 | zero_buffer(tty, from, size); |
| 179 | if (uncopied) | ||
| 180 | return uncopied; | ||
| 181 | to += size; | 177 | to += size; |
| 182 | n -= size; | 178 | n -= size; |
| 183 | from = ldata->read_buf; | 179 | from = ldata->read_buf; |
| 184 | } | 180 | } |
| 185 | 181 | ||
| 186 | tty_audit_add_data(tty, from, n); | 182 | tty_audit_add_data(tty, from, n); |
| 187 | uncopied = copy_to_user(to, from, n); | 183 | memcpy(to, from, n); |
| 188 | zero_buffer(tty, from, n - uncopied); | 184 | zero_buffer(tty, from, n); |
| 189 | return uncopied; | ||
| 190 | } | 185 | } |
| 191 | 186 | ||
| 192 | /** | 187 | /** |
| @@ -1894,8 +1889,10 @@ static void n_tty_close(struct tty_struct *tty) · 1701 unmodified lines | |||
| 1894 | if (tty->link) | 1889 | if (tty->link) |
| 1895 | n_tty_packet_mode_flush(tty); | 1890 | n_tty_packet_mode_flush(tty); |
| 1896 | 1891 | ||
| 1892 | down_write(&tty->termios_rwsem); | ||
| 1897 | vfree(ldata); | 1893 | vfree(ldata); |
| 1898 | tty->disc_data = NULL; | 1894 | tty->disc_data = NULL; |
| 1895 | up_write(&tty->termios_rwsem); | ||
| 1899 | } | 1896 | } |
| 1900 | 1897 | ||
| 1901 | /** | 1898 | /** |
| @@ -1944,42 +1941,38 @@ static inline int input_available_p(struct tty_struct *tty, int poll) · 42 unmodified lines | |||
| 1944 | /** | 1941 | /** |
| 1945 | * copy_from_read_buf - copy read data directly | 1942 | * copy_from_read_buf - copy read data directly |
| 1946 | * @tty: terminal device | 1943 | * @tty: terminal device |
| 1947 | * @b: user data | 1944 | * @kbp: data |
| 1948 | * @nr: size of data | 1945 | * @nr: size of data |
| 1949 | * | 1946 | * |
| 1950 | * Helper function to speed up n_tty_read. It is only called when | 1947 | * Helper function to speed up n_tty_read. It is only called when |
| 1951 | * ICANON is off; it copies characters straight from the tty queue to | 1948 | * ICANON is off; it copies characters straight from the tty queue. |
| 1952 | * user space directly. It can be profitably called twice; once to | ||
| 1953 | * drain the space from the tail pointer to the (physical) end of the | ||
| 1954 | * buffer, and once to drain the space from the (physical) beginning of | ||
| 1955 | * the buffer to head pointer. | ||
| 1956 | * | 1949 | * |
| 1957 | * Called under the ldata->atomic_read_lock sem | 1950 | * Called under the ldata->atomic_read_lock sem |
| 1958 | * | 1951 | * |
| 1952 | * Returns true if it successfully copied data, but there is still | ||
| 1953 | * more data to be had. | ||
| 1954 | * | ||
| 1959 | * n_tty_read()/consumer path: | 1955 | * n_tty_read()/consumer path: |
| 1960 | * caller holds non-exclusive termios_rwsem | 1956 | * caller holds non-exclusive termios_rwsem |
| 1961 | * read_tail published | 1957 | * read_tail published |
| 1962 | */ | 1958 | */ |
| 1963 | 1959 | ||
| 1964 | static int copy_from_read_buf(struct tty_struct *tty, | 1960 | static bool copy_from_read_buf(struct tty_struct *tty, |
| 1965 | unsigned char __user **b, | 1961 | unsigned char **kbp, |
| 1966 | size_t *nr) | 1962 | size_t *nr) |
| 1967 | 1963 | ||
| 1968 | { | 1964 | { |
| 1969 | struct n_tty_data *ldata = tty->disc_data; | 1965 | struct n_tty_data *ldata = tty->disc_data; |
| 1970 | int retval; | ||
| 1971 | size_t n; | 1966 | size_t n; |
| 1972 | bool is_eof; | 1967 | bool is_eof; |
| 1973 | size_t head = smp_load_acquire(&ldata->commit_head); | 1968 | size_t head = smp_load_acquire(&ldata->commit_head); |
| 1974 | size_t tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1); | 1969 | size_t tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1); |
| 1975 | 1970 | ||
| 1976 | retval = 0; | ||
| 1977 | n = min(head - ldata->read_tail, N_TTY_BUF_SIZE - tail); | 1971 | n = min(head - ldata->read_tail, N_TTY_BUF_SIZE - tail); |
| 1978 | n = min(*nr, n); | 1972 | n = min(*nr, n); |
| 1979 | if (n) { | 1973 | if (n) { |
| 1980 | unsigned char *from = read_buf_addr(ldata, tail); | 1974 | unsigned char *from = read_buf_addr(ldata, tail); |
| 1981 | retval = copy_to_user(*b, from, n); | 1975 | memcpy(*kbp, from, n); |
| 1982 | n -= retval; | ||
| 1983 | is_eof = n == 1 && *from == EOF_CHAR(tty); | 1976 | is_eof = n == 1 && *from == EOF_CHAR(tty); |
| 1984 | tty_audit_add_data(tty, from, n); | 1977 | tty_audit_add_data(tty, from, n); |
| 1985 | zero_buffer(tty, from, n); | 1978 | zero_buffer(tty, from, n); |
| @@ -1987,22 +1980,25 @@ static int copy_from_read_buf(struct tty_struct *tty, · 1 unmodified line | |||
| 1987 | /* Turn single EOF into zero-length read */ | 1980 | /* Turn single EOF into zero-length read */ |
| 1988 | if (L_EXTPROC(tty) && ldata->icanon && is_eof && | 1981 | if (L_EXTPROC(tty) && ldata->icanon && is_eof && |
| 1989 | (head == ldata->read_tail)) | 1982 | (head == ldata->read_tail)) |
| 1990 | n = 0; | 1983 | return false; |
| 1991 | *b += n; | 1984 | *kbp += n; |
| 1992 | *nr -= n; | 1985 | *nr -= n; |
| 1986 | |||
| 1987 | /* If we have more to copy, let the caller know */ | ||
| 1988 | return head != ldata->read_tail; | ||
| 1993 | } | 1989 | } |
| 1994 | return retval; | 1990 | return false; |
| 1995 | } | 1991 | } |
| 1996 | 1992 | ||
| 1997 | /** | 1993 | /** |
| 1998 | * canon_copy_from_read_buf - copy read data in canonical mode | 1994 | * canon_copy_from_read_buf - copy read data in canonical mode |
| 1999 | * @tty: terminal device | 1995 | * @tty: terminal device |
| 2000 | * @b: user data | 1996 | * @kbp: data |
| 2001 | * @nr: size of data | 1997 | * @nr: size of data |
| 2002 | * | 1998 | * |
| 2003 | * Helper function for n_tty_read. It is only called when ICANON is on; | 1999 | * Helper function for n_tty_read. It is only called when ICANON is on; |
| 2004 | * it copies one line of input up to and including the line-delimiting | 2000 | * it copies one line of input up to and including the line-delimiting |
| 2005 | * character into the user-space buffer. | 2001 | * character into the result buffer. |
| 2006 | * | 2002 | * |
| 2007 | * NB: When termios is changed from non-canonical to canonical mode and | 2003 | * NB: When termios is changed from non-canonical to canonical mode and |
| 2008 | * the read buffer contains data, n_tty_set_termios() simulates an EOF | 2004 | * the read buffer contains data, n_tty_set_termios() simulates an EOF |
| @@ -2017,21 +2013,22 @@ static int copy_from_read_buf(struct tty_struct *tty, · 8 unmodified lines | |||
| 2017 | * read_tail published | 2013 | * read_tail published |
| 2018 | */ | 2014 | */ |
| 2019 | 2015 | ||
| 2020 | static int canon_copy_from_read_buf(struct tty_struct *tty, | 2016 | static bool canon_copy_from_read_buf(struct tty_struct *tty, |
| 2021 | unsigned char __user **b, | 2017 | unsigned char **kbp, |
| 2022 | size_t *nr) | 2018 | size_t *nr) |
| 2023 | { | 2019 | { |
| 2024 | struct n_tty_data *ldata = tty->disc_data; | 2020 | struct n_tty_data *ldata = tty->disc_data; |
| 2025 | size_t n, size, more, c; | 2021 | size_t n, size, more, c; |
| 2026 | size_t eol; | 2022 | size_t eol; |
| 2027 | size_t tail; | 2023 | size_t tail, canon_head; |
| 2028 | int ret, found = 0; | 2024 | int found = 0; |
| 2029 | 2025 | ||
| 2030 | /* N.B. avoid overrun if nr == 0 */ | 2026 | /* N.B. avoid overrun if nr == 0 */ |
| 2031 | if (!*nr) | 2027 | if (!*nr) |
| 2032 | return 0; | 2028 | return false; |
| 2033 | 2029 | ||
| 2034 | n = min(*nr + 1, smp_load_acquire(&ldata->canon_head) - ldata->read_tail); | 2030 | canon_head = smp_load_acquire(&ldata->canon_head); |
| 2031 | n = min(*nr + 1, canon_head - ldata->read_tail); | ||
| 2035 | 2032 | ||
| 2036 | tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1); | 2033 | tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1); |
| 2037 | size = min_t(size_t, tail + n, N_TTY_BUF_SIZE); | 2034 | size = min_t(size_t, tail + n, N_TTY_BUF_SIZE); |
| @@ -2061,10 +2058,8 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, · 23 unmodified lines | |||
| 2061 | n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu tail:%zu more:%zu\n", | 2058 | n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu tail:%zu more:%zu\n", |
| 2062 | __func__, eol, found, n, c, tail, more); | 2059 | __func__, eol, found, n, c, tail, more); |
| 2063 | 2060 | ||
| 2064 | ret = tty_copy_to_user(tty, *b, tail, n); | 2061 | tty_copy(tty, *kbp, tail, n); |
| 2065 | if (ret) | 2062 | *kbp += n; |
| 2066 | return -EFAULT; | ||
| 2067 | *b += n; | ||
| 2068 | *nr -= n; | 2063 | *nr -= n; |
| 2069 | 2064 | ||
| 2070 | if (found) | 2065 | if (found) |
| @@ -2077,8 +2072,11 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, · 6 unmodified lines | |||
| 2077 | else | 2072 | else |
| 2078 | ldata->push = 0; | 2073 | ldata->push = 0; |
| 2079 | tty_audit_push(); | 2074 | tty_audit_push(); |
| 2075 | return false; | ||
| 2080 | } | 2076 | } |
| 2081 | return 0; | 2077 | |
| 2078 | /* No EOL found - do a continuation retry if there is more data */ | ||
| 2079 | return ldata->read_tail != canon_head; | ||
| 2082 | } | 2080 | } |
| 2083 | 2081 | ||
| 2084 | /** | 2082 | /** |
| @@ -2129,10 +2127,11 @@ static int job_control(struct tty_struct *tty, struct file *file) · 44 unmodified lines | |||
| 2129 | */ | 2127 | */ |
| 2130 | 2128 | ||
| 2131 | static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, | 2129 | static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, |
| 2132 | unsigned char __user *buf, size_t nr) | 2130 | unsigned char *kbuf, size_t nr, |
| 2131 | void **cookie, unsigned long offset) | ||
| 2133 | { | 2132 | { |
| 2134 | struct n_tty_data *ldata = tty->disc_data; | 2133 | struct n_tty_data *ldata = tty->disc_data; |
| 2135 | unsigned char __user *b = buf; | 2134 | unsigned char *kb = kbuf; |
| 2136 | DEFINE_WAIT_FUNC(wait, woken_wake_function); | 2135 | DEFINE_WAIT_FUNC(wait, woken_wake_function); |
| 2137 | int c; | 2136 | int c; |
| 2138 | int minimum, time; | 2137 | int minimum, time; |
| @@ -2141,6 +2140,30 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, · 2 unmodified lines | |||
| 2141 | int packet; | 2140 | int packet; |
| 2142 | size_t tail; | 2141 | size_t tail; |
| 2143 | 2142 | ||
| 2143 | /* | ||
| 2144 | * Is this a continuation of a read started earler? | ||
| 2145 | * | ||
| 2146 | * If so, we still hold the atomic_read_lock and the | ||
| 2147 | * termios_rwsem, and can just continue to copy data. | ||
| 2148 | */ | ||
| 2149 | if (*cookie) { | ||
| 2150 | if (ldata->icanon && !L_EXTPROC(tty)) { | ||
| 2151 | if (canon_copy_from_read_buf(tty, &kb, &nr)) | ||
| 2152 | return kb - kbuf; | ||
| 2153 | } else { | ||
| 2154 | if (copy_from_read_buf(tty, &kb, &nr)) | ||
| 2155 | return kb - kbuf; | ||
| 2156 | } | ||
| 2157 | |||
| 2158 | /* No more data - release locks and stop retries */ | ||
| 2159 | n_tty_kick_worker(tty); | ||
| 2160 | n_tty_check_unthrottle(tty); | ||
| 2161 | up_read(&tty->termios_rwsem); | ||
| 2162 | mutex_unlock(&ldata->atomic_read_lock); | ||
| 2163 | *cookie = NULL; | ||
| 2164 | return kb - kbuf; | ||
| 2165 | } | ||
| 2166 | |||
| 2144 | c = job_control(tty, file); | 2167 | c = job_control(tty, file); |
| 2145 | if (c < 0) | 2168 | if (c < 0) |
| 2146 | return c; | 2169 | return c; |
| @@ -2178,17 +2201,13 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, · 31 unmodified lines | |||
| 2178 | /* First test for status change. */ | 2201 | /* First test for status change. */ |
| 2179 | if (packet && tty->link->ctrl_status) { | 2202 | if (packet && tty->link->ctrl_status) { |
| 2180 | unsigned char cs; | 2203 | unsigned char cs; |
| 2181 | if (b != buf) | 2204 | if (kb != kbuf) |
| 2182 | break; | 2205 | break; |
| 2183 | spin_lock_irq(&tty->link->ctrl_lock); | 2206 | spin_lock_irq(&tty->link->ctrl_lock); |
| 2184 | cs = tty->link->ctrl_status; | 2207 | cs = tty->link->ctrl_status; |
| 2185 | tty->link->ctrl_status = 0; | 2208 | tty->link->ctrl_status = 0; |
| 2186 | spin_unlock_irq(&tty->link->ctrl_lock); | 2209 | spin_unlock_irq(&tty->link->ctrl_lock); |
| 2187 | if (put_user(cs, b)) { | 2210 | *kb++ = cs; |
| 2188 | retval = -EFAULT; | ||
| 2189 | break; | ||
| 2190 | } | ||
| 2191 | b++; | ||
| 2192 | nr--; | 2211 | nr--; |
| 2193 | break; | 2212 | break; |
| 2194 | } | 2213 | } |
| @@ -2231,33 +2250,35 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, · 36 unmodified lines | |||
| 2231 | } | 2250 | } |
| 2232 | 2251 | ||
| 2233 | if (ldata->icanon && !L_EXTPROC(tty)) { | 2252 | if (ldata->icanon && !L_EXTPROC(tty)) { |
| 2234 | retval = canon_copy_from_read_buf(tty, &b, &nr); | 2253 | if (canon_copy_from_read_buf(tty, &kb, &nr)) |
| 2235 | if (retval) | 2254 | goto more_to_be_read; |
| 2236 | break; | ||
| 2237 | } else { | 2255 | } else { |
| 2238 | int uncopied; | ||
| 2239 | |||
| 2240 | /* Deal with packet mode. */ | 2256 | /* Deal with packet mode. */ |
| 2241 | if (packet && b == buf) { | 2257 | if (packet && kb == kbuf) { |
| 2242 | if (put_user(TIOCPKT_DATA, b)) { | 2258 | *kb++ = TIOCPKT_DATA; |
| 2243 | retval = -EFAULT; | ||
| 2244 | break; | ||
| 2245 | } | ||
| 2246 | b++; | ||
| 2247 | nr--; | 2259 | nr--; |
| 2248 | } | 2260 | } |
| 2249 | 2261 | ||
| 2250 | uncopied = copy_from_read_buf(tty, &b, &nr); | 2262 | /* |
| 2251 | uncopied += copy_from_read_buf(tty, &b, &nr); | 2263 | * Copy data, and if there is more to be had |
| 2252 | if (uncopied) { | 2264 | * and we have nothing more to wait for, then |
| 2253 | retval = -EFAULT; | 2265 | * let's mark us for retries. |
| 2254 | break; | 2266 | * |
| 2267 | * NOTE! We return here with both the termios_sem | ||
| 2268 | * and atomic_read_lock still held, the retries | ||
| 2269 | * will release them when done. | ||
| 2270 | */ | ||
| 2271 | if (copy_from_read_buf(tty, &kb, &nr) && kb - kbuf >= minimum) { | ||
| 2272 | more_to_be_read: | ||
| 2273 | remove_wait_queue(&tty->read_wait, &wait); | ||
| 2274 | *cookie = cookie; | ||
| 2275 | return kb - kbuf; | ||
| 2255 | } | 2276 | } |
| 2256 | } | 2277 | } |
| 2257 | 2278 | ||
| 2258 | n_tty_check_unthrottle(tty); | 2279 | n_tty_check_unthrottle(tty); |
| 2259 | 2280 | ||
| 2260 | if (b - buf >= minimum) | 2281 | if (kb - kbuf >= minimum) |
| 2261 | break; | 2282 | break; |
| 2262 | if (time) | 2283 | if (time) |
| 2263 | timeout = time; | 2284 | timeout = time; |
| @@ -2269,8 +2290,8 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, · 5 unmodified lines | |||
| 2269 | remove_wait_queue(&tty->read_wait, &wait); | 2290 | remove_wait_queue(&tty->read_wait, &wait); |
| 2270 | mutex_unlock(&ldata->atomic_read_lock); | 2291 | mutex_unlock(&ldata->atomic_read_lock); |
| 2271 | 2292 | ||
| 2272 | if (b - buf) | 2293 | if (kb - kbuf) |
| 2273 | retval = b - buf; | 2294 | retval = kb - kbuf; |
| 2274 | 2295 | ||
| 2275 | return retval; | 2296 | return retval; |
| 2276 | } | 2297 | } |
| @@ -45,7 +45,6 @@ static DEFINE_MUTEX(devpts_mutex); · 44 unmodified lines | |||
| 45 | 45 | ||
| 46 | static void pty_close(struct tty_struct *tty, struct file *filp) | 46 | static void pty_close(struct tty_struct *tty, struct file *filp) |
| 47 | { | 47 | { |
| 48 | BUG_ON(!tty); | ||
| 49 | if (tty->driver->subtype == PTY_TYPE_MASTER) | 48 | if (tty->driver->subtype == PTY_TYPE_MASTER) |
| 50 | WARN_ON(tty->count > 1); | 49 | WARN_ON(tty->count > 1); |
| 51 | else { | 50 | else { |
| @@ -67,7 +66,8 @@ static void pty_close(struct tty_struct *tty, struct file *filp) · 15 unmodified lines | |||
| 67 | wake_up_interruptible(&tty->link->read_wait); | 66 | wake_up_interruptible(&tty->link->read_wait); |
| 68 | wake_up_interruptible(&tty->link->write_wait); | 67 | wake_up_interruptible(&tty->link->write_wait); |
| 69 | if (tty->driver->subtype == PTY_TYPE_MASTER) { | 68 | if (tty->driver->subtype == PTY_TYPE_MASTER) { |
| 70 | set_bit(TTY_OTHER_CLOSED, &tty->flags); | 69 | struct file *f; |
| 70 | |||
| 71 | #ifdef CONFIG_UNIX98_PTYS | 71 | #ifdef CONFIG_UNIX98_PTYS |
| 72 | if (tty->driver == ptm_driver) { | 72 | if (tty->driver == ptm_driver) { |
| 73 | mutex_lock(&devpts_mutex); | 73 | mutex_lock(&devpts_mutex); |
| @@ -76,7 +76,17 @@ static void pty_close(struct tty_struct *tty, struct file *filp) · 2 unmodified lines | |||
| 76 | mutex_unlock(&devpts_mutex); | 76 | mutex_unlock(&devpts_mutex); |
| 77 | } | 77 | } |
| 78 | #endif | 78 | #endif |
| 79 | tty_vhangup(tty->link); | 79 | |
| 80 | /* | ||
| 81 | * This hack is required because a program can open a | ||
| 82 | * pty and redirect a console to it, but if the pty is | ||
| 83 | * closed and the console is not released, then the | ||
| 84 | * slave side will never close. So release the | ||
| 85 | * redirect when the master closes. | ||
| 86 | */ | ||
| 87 | f = tty_release_redirect(tty->link); | ||
| 88 | if (f) | ||
| 89 | fput(f); | ||
| 80 | } | 90 | } |
| 81 | } | 91 | } |
| 82 | 92 | ||
| @@ -26,16 +26,17 @@ static void tegra_uart_handle_break(struct uart_port *p) · 25 unmodified lines | |||
| 26 | { | 26 | { |
| 27 | unsigned int status, tmout = 10000; | 27 | unsigned int status, tmout = 10000; |
| 28 | 28 | ||
| 29 | do { | 29 | while (1) { |
| 30 | status = p->serial_in(p, UART_LSR); | 30 | status = p->serial_in(p, UART_LSR); |
| 31 | if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) | 31 | if (!(status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))) |
| 32 | status = p->serial_in(p, UART_RX); | ||
| 33 | else | ||
| 34 | break; | 32 | break; |
| 33 | |||
| 34 | p->serial_in(p, UART_RX); | ||
| 35 | |||
| 35 | if (--tmout == 0) | 36 | if (--tmout == 0) |
| 36 | break; | 37 | break; |
| 37 | udelay(1); | 38 | udelay(1); |
| 38 | } while (1); | 39 | } |
| 39 | } | 40 | } |
| 40 | 41 | ||
| 41 | static int tegra_uart_probe(struct platform_device *pdev) | 42 | static int tegra_uart_probe(struct platform_device *pdev) |
| @@ -276,28 +276,6 @@ config SERIAL_SAMSUNG_CONSOLE · 275 unmodified lines | |||
| 276 | your boot loader about how to pass options to the kernel at | 276 | your boot loader about how to pass options to the kernel at |
| 277 | boot time.) | 277 | boot time.) |
| 278 | 278 | ||
| 279 | config SERIAL_SIRFSOC | ||
| 280 | tristate "SiRF SoC Platform Serial port support" | ||
| 281 | depends on ARCH_SIRF | ||
| 282 | select SERIAL_CORE | ||
| 283 | help | ||
| 284 | Support for the on-chip UART on the CSR SiRFprimaII series, | ||
| 285 | providing /dev/ttySiRF0, 1 and 2 (note, some machines may not | ||
| 286 | provide all of these ports, depending on how the serial port | ||
| 287 | pins are configured). | ||
| 288 | |||
| 289 | config SERIAL_SIRFSOC_CONSOLE | ||
| 290 | bool "Support for console on SiRF SoC serial port" | ||
| 291 | depends on SERIAL_SIRFSOC=y | ||
| 292 | select SERIAL_CORE_CONSOLE | ||
| 293 | help | ||
| 294 | Even if you say Y here, the currently visible virtual console | ||
| 295 | (/dev/tty0) will still be used as the system console by default, but | ||
| 296 | you can alter that using a kernel command line option such as | ||
| 297 | "console=ttySiRFx". (Try "man bootparam" or see the documentation of | ||
| 298 | your boot loader about how to pass options to the kernel at | ||
| 299 | boot time.) | ||
| 300 | |||
| 301 | config SERIAL_TEGRA | 279 | config SERIAL_TEGRA |
| 302 | tristate "NVIDIA Tegra20/30 SoC serial controller" | 280 | tristate "NVIDIA Tegra20/30 SoC serial controller" |
| 303 | depends on ARCH_TEGRA && TEGRA20_APB_DMA | 281 | depends on ARCH_TEGRA && TEGRA20_APB_DMA |
| @@ -1204,13 +1182,6 @@ config SERIAL_ALTERA_UART_CONSOLE · 900 unmodified lines | |||
| 1204 | help | 1182 | help |
| 1205 | Enable a Altera UART port to be the system console. | 1183 | Enable a Altera UART port to be the system console. |
| 1206 | 1184 | ||
| 1207 | config SERIAL_IFX6X60 | ||
| 1208 | tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)" | ||
| 1209 | depends on GPIOLIB || COMPILE_TEST | ||
| 1210 | depends on SPI && HAS_DMA | ||
| 1211 | help | ||
| 1212 | Support for the IFX6x60 modem devices on Intel MID platforms. | ||
| 1213 | |||
| 1214 | config SERIAL_PCH_UART | 1185 | config SERIAL_PCH_UART |
| 1215 | tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) UART" | 1186 | tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) UART" |
| 1216 | depends on PCI && (X86_32 || MIPS || COMPILE_TEST) | 1187 | depends on PCI && (X86_32 || MIPS || COMPILE_TEST) |
| @@ -1295,14 +1266,6 @@ config SERIAL_AR933X_NR_UARTS · 78 unmodified lines | |||
| 1295 | Set this to the number of serial ports you want the driver | 1266 | Set this to the number of serial ports you want the driver |
| 1296 | to support. | 1267 | to support. |
| 1297 | 1268 | ||
| 1298 | config SERIAL_EFM32_UART | ||
| 1299 | tristate "EFM32 UART/USART port" | ||
| 1300 | depends on ARM && (ARCH_EFM32 || COMPILE_TEST) | ||
| 1301 | select SERIAL_CORE | ||
| 1302 | help | ||
| 1303 | This driver support the USART and UART ports on | ||
| 1304 | Energy Micro's efm32 SoCs. | ||
| 1305 | |||
| 1306 | config SERIAL_MPS2_UART_CONSOLE | 1269 | config SERIAL_MPS2_UART_CONSOLE |
| 1307 | bool "MPS2 UART console support" | 1270 | bool "MPS2 UART console support" |
| 1308 | depends on SERIAL_MPS2_UART | 1271 | depends on SERIAL_MPS2_UART |
| @@ -1316,11 +1279,6 @@ config SERIAL_MPS2_UART · 7 unmodified lines | |||
| 1316 | help | 1279 | help |
| 1317 | This driver support the UART ports on ARM MPS2. | 1280 | This driver support the UART ports on ARM MPS2. |
| 1318 | 1281 | ||
| 1319 | config SERIAL_EFM32_UART_CONSOLE | ||
| 1320 | bool "EFM32 UART/USART console support" | ||
| 1321 | depends on SERIAL_EFM32_UART=y | ||
| 1322 | select SERIAL_CORE_CONSOLE | ||
| 1323 | |||
| 1324 | config SERIAL_ARC | 1282 | config SERIAL_ARC |
| 1325 | tristate "ARC UART driver support" | 1283 | tristate "ARC UART driver support" |
| 1326 | select SERIAL_CORE | 1284 | select SERIAL_CORE |
| @@ -64,16 +64,13 @@ obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o · 63 unmodified lines | |||
| 64 | obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o | 64 | obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o |
| 65 | obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o | 65 | obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o |
| 66 | obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o | 66 | obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o |
| 67 | obj-$(CONFIG_SERIAL_IFX6X60) += ifx6x60.o | ||
| 68 | obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o | 67 | obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o |
| 69 | obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o | 68 | obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o |
| 70 | obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o | 69 | obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o |
| 71 | obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o | 70 | obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o |
| 72 | obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o | ||
| 73 | obj-$(CONFIG_SERIAL_TEGRA) += serial-tegra.o | 71 | obj-$(CONFIG_SERIAL_TEGRA) += serial-tegra.o |
| 74 | obj-$(CONFIG_SERIAL_TEGRA_TCU) += tegra-tcu.o | 72 | obj-$(CONFIG_SERIAL_TEGRA_TCU) += tegra-tcu.o |
| 75 | obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o | 73 | obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o |
| 76 | obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o | ||
| 77 | obj-$(CONFIG_SERIAL_ARC) += arc_uart.o | 74 | obj-$(CONFIG_SERIAL_ARC) += arc_uart.o |
| 78 | obj-$(CONFIG_SERIAL_RP2) += rp2.o | 75 | obj-$(CONFIG_SERIAL_RP2) += rp2.o |
| 79 | obj-$(CONFIG_SERIAL_FSL_LPUART) += fsl_lpuart.o | 76 | obj-$(CONFIG_SERIAL_FSL_LPUART) += fsl_lpuart.o |
| @@ -499,8 +499,7 @@ static void cpm_uart_set_termios(struct uart_port *port, · 498 unmodified lines | |||
| 499 | pr_debug("CPM uart[%d]:set_termios\n", port->line); | 499 | pr_debug("CPM uart[%d]:set_termios\n", port->line); |
| 500 | 500 | ||
| 501 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); | 501 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); |
| 502 | if (baud < HW_BUF_SPD_THRESHOLD || | 502 | if (baud < HW_BUF_SPD_THRESHOLD || port->flags & UPF_LOW_LATENCY) |
| 503 | (pinfo->port.state && pinfo->port.state->port.low_latency)) | ||
| 504 | pinfo->rx_fifosize = 1; | 503 | pinfo->rx_fifosize = 1; |
| 505 | else | 504 | else |
| 506 | pinfo->rx_fifosize = RX_BUF_SIZE; | 505 | pinfo->rx_fifosize = RX_BUF_SIZE; |
| @@ -1107,6 +1106,32 @@ static void cpm_put_poll_char(struct uart_port *port, · 600 unmodified lines | |||
| 1107 | ch[0] = (char)c; | 1106 | ch[0] = (char)c; |
| 1108 | cpm_uart_early_write(pinfo, ch, 1, false); | 1107 | cpm_uart_early_write(pinfo, ch, 1, false); |
| 1109 | } | 1108 | } |
| 1109 | |||
| 1110 | static struct uart_port *udbg_port; | ||
| 1111 | |||
| 1112 | static void udbg_cpm_putc(char c) | ||
| 1113 | { | ||
| 1114 | if (c == '\n') | ||
| 1115 | cpm_put_poll_char(udbg_port, '\r'); | ||
| 1116 | cpm_put_poll_char(udbg_port, c); | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | static int udbg_cpm_getc_poll(void) | ||
| 1120 | { | ||
| 1121 | int c = cpm_get_poll_char(udbg_port); | ||
| 1122 | |||
| 1123 | return c == NO_POLL_CHAR ? -1 : c; | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | static int udbg_cpm_getc(void) | ||
| 1127 | { | ||
| 1128 | int c; | ||
| 1129 | |||
| 1130 | while ((c = udbg_cpm_getc_poll()) == -1) | ||
| 1131 | cpu_relax(); | ||
| 1132 | return c; | ||
| 1133 | } | ||
| 1134 | |||
| 1110 | #endif /* CONFIG_CONSOLE_POLL */ | 1135 | #endif /* CONFIG_CONSOLE_POLL */ |
| 1111 | 1136 | ||
| 1112 | static const struct uart_ops cpm_uart_pops = { | 1137 | static const struct uart_ops cpm_uart_pops = { |
| @@ -1237,7 +1262,10 @@ static int cpm_uart_init_port(struct device_node *np, · 124 unmodified lines | |||
| 1237 | } | 1262 | } |
| 1238 | 1263 | ||
| 1239 | #ifdef CONFIG_PPC_EARLY_DEBUG_CPM | 1264 | #ifdef CONFIG_PPC_EARLY_DEBUG_CPM |
| 1240 | udbg_putc = NULL; | 1265 | #ifdef CONFIG_CONSOLE_POLL |
| 1266 | if (!udbg_port) | ||
| 1267 | #endif | ||
| 1268 | udbg_putc = NULL; | ||
| 1241 | #endif | 1269 | #endif |
| 1242 | 1270 | ||
| 1243 | return cpm_uart_request_port(&pinfo->port); | 1271 | return cpm_uart_request_port(&pinfo->port); |
| @@ -1358,6 +1386,15 @@ static int __init cpm_uart_console_setup(struct console *co, char *options) · 114 unmodified lines | |||
| 1358 | uart_set_options(port, co, baud, parity, bits, flow); | 1386 | uart_set_options(port, co, baud, parity, bits, flow); |
| 1359 | cpm_line_cr_cmd(pinfo, CPM_CR_RESTART_TX); | 1387 | cpm_line_cr_cmd(pinfo, CPM_CR_RESTART_TX); |
| 1360 | 1388 | ||
| 1389 | #ifdef CONFIG_CONSOLE_POLL | ||
| 1390 | if (!udbg_port) { | ||
| 1391 | udbg_port = &pinfo->port; | ||
| 1392 | udbg_putc = udbg_cpm_putc; | ||
| 1393 | udbg_getc = udbg_cpm_getc; | ||
| 1394 | udbg_getc_poll = udbg_cpm_getc_poll; | ||
| 1395 | } | ||
| 1396 | #endif | ||
| 1397 | |||
| 1361 | return 0; | 1398 | return 0; |
| 1362 | } | 1399 | } |
| 1363 | 1400 | ||
| @@ -1,852 +0,0 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | #include <linux/kernel.h> | ||
| 3 | #include <linux/module.h> | ||
| 4 | #include <linux/io.h> | ||
| 5 | #include <linux/platform_device.h> | ||
| 6 | #include <linux/console.h> | ||
| 7 | #include <linux/sysrq.h> | ||
| 8 | #include <linux/serial_core.h> | ||
| 9 | #include <linux/tty_flip.h> | ||
| 10 | #include <linux/slab.h> | ||
| 11 | #include <linux/clk.h> | ||
| 12 | #include <linux/of.h> | ||
| 13 | #include <linux/of_device.h> | ||
| 14 | |||
| 15 | #include <linux/platform_data/efm32-uart.h> | ||
| 16 | |||
| 17 | #define DRIVER_NAME "efm32-uart" | ||
| 18 | #define DEV_NAME "ttyefm" | ||
| 19 | |||
| 20 | #define UARTn_CTRL 0x00 | ||
| 21 | #define UARTn_CTRL_SYNC 0x0001 | ||
| 22 | #define UARTn_CTRL_TXBIL 0x1000 | ||
| 23 | |||
| 24 | #define UARTn_FRAME 0x04 | ||
| 25 | #define UARTn_FRAME_DATABITS__MASK 0x000f | ||
| 26 | #define UARTn_FRAME_DATABITS(n) ((n) - 3) | ||
| 27 | #define UARTn_FRAME_PARITY__MASK 0x0300 | ||
| 28 | #define UARTn_FRAME_PARITY_NONE 0x0000 | ||
| 29 | #define UARTn_FRAME_PARITY_EVEN 0x0200 | ||
| 30 | #define UARTn_FRAME_PARITY_ODD 0x0300 | ||
| 31 | #define UARTn_FRAME_STOPBITS_HALF 0x0000 | ||
| 32 | #define UARTn_FRAME_STOPBITS_ONE 0x1000 | ||
| 33 | #define UARTn_FRAME_STOPBITS_TWO 0x3000 | ||
| 34 | |||
| 35 | #define UARTn_CMD 0x0c | ||
| 36 | #define UARTn_CMD_RXEN 0x0001 | ||
| 37 | #define UARTn_CMD_RXDIS 0x0002 | ||
| 38 | #define UARTn_CMD_TXEN 0x0004 | ||
| 39 | #define UARTn_CMD_TXDIS 0x0008 | ||
| 40 | |||
| 41 | #define UARTn_STATUS 0x10 | ||
| 42 | #define UARTn_STATUS_TXENS 0x0002 | ||
| 43 | #define UARTn_STATUS_TXC 0x0020 | ||
| 44 | #define UARTn_STATUS_TXBL 0x0040 | ||
| 45 | #define UARTn_STATUS_RXDATAV 0x0080 | ||
| 46 | |||
| 47 | #define UARTn_CLKDIV 0x14 | ||
| 48 | |||
| 49 | #define UARTn_RXDATAX 0x18 | ||
| 50 | #define UARTn_RXDATAX_RXDATA__MASK 0x01ff | ||
| 51 | #define UARTn_RXDATAX_PERR 0x4000 | ||
| 52 | #define UARTn_RXDATAX_FERR 0x8000 | ||
| 53 | /* | ||
| 54 | * This is a software only flag used for ignore_status_mask and | ||
| 55 | * read_status_mask! It's used for breaks that the hardware doesn't report | ||
| 56 | * explicitly. | ||
| 57 | */ | ||
| 58 | #define SW_UARTn_RXDATAX_BERR 0x2000 | ||
| 59 | |||
| 60 | #define UARTn_TXDATA 0x34 | ||
| 61 | |||
| 62 | #define UARTn_IF 0x40 | ||
| 63 | #define UARTn_IF_TXC 0x0001 | ||
| 64 | #define UARTn_IF_TXBL 0x0002 | ||
| 65 | #define UARTn_IF_RXDATAV 0x0004 | ||
| 66 | #define UARTn_IF_RXOF 0x0010 | ||
| 67 | |||
| 68 | #define UARTn_IFS 0x44 | ||
| 69 | #define UARTn_IFC 0x48 | ||
| 70 | #define UARTn_IEN 0x4c | ||
| 71 | |||
| 72 | #define UARTn_ROUTE 0x54 | ||
| 73 | #define UARTn_ROUTE_LOCATION__MASK 0x0700 | ||
| 74 | #define UARTn_ROUTE_LOCATION(n) (((n) << 8) & UARTn_ROUTE_LOCATION__MASK) | ||
| 75 | #define UARTn_ROUTE_RXPEN 0x0001 | ||
| 76 | #define UARTn_ROUTE_TXPEN 0x0002 | ||
| 77 | |||
| 78 | struct efm32_uart_port { | ||
| 79 | struct uart_port port; | ||
| 80 | unsigned int txirq; | ||
| 81 | struct clk *clk; | ||
| 82 | struct efm32_uart_pdata pdata; | ||
| 83 | }; | ||
| 84 | #define to_efm_port(_port) container_of(_port, struct efm32_uart_port, port) | ||
| 85 | #define efm_debug(efm_port, format, arg...) \ | ||
| 86 | dev_dbg(efm_port->port.dev, format, ##arg) | ||
| 87 | |||
| 88 | static void efm32_uart_write32(struct efm32_uart_port *efm_port, | ||
| 89 | u32 value, unsigned offset) | ||
| 90 | { | ||
| 91 | writel_relaxed(value, efm_port->port.membase + offset); | ||
| 92 | } | ||
| 93 | |||
| 94 | static u32 efm32_uart_read32(struct efm32_uart_port *efm_port, | ||
| 95 | unsigned offset) | ||
| 96 | { | ||
| 97 | return readl_relaxed(efm_port->port.membase + offset); | ||
| 98 | } | ||
| 99 | |||
| 100 | static unsigned int efm32_uart_tx_empty(struct uart_port *port) | ||
| 101 | { | ||
| 102 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
| 103 | u32 status = efm32_uart_read32(efm_port, UARTn_STATUS); | ||
| 104 | |||
| 105 | if (status & UARTn_STATUS_TXC) | ||
| 106 | return TIOCSER_TEMT; | ||
| 107 | else | ||
| 108 | return 0; | ||
| 109 | } | ||
| 110 | |||
| 111 | static void efm32_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
| 112 | { | ||
| 113 | /* sorry, neither handshaking lines nor loop functionallity */ | ||
| 114 | } | ||
| 115 | |||
| 116 | static unsigned int efm32_uart_get_mctrl(struct uart_port *port) | ||
| 117 | { | ||
| 118 | /* sorry, no handshaking lines available */ | ||
| 119 | return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR; | ||
| 120 | } | ||
| 121 | |||
| 122 | static void efm32_uart_stop_tx(struct uart_port *port) | ||
| 123 | { | ||
| 124 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
| 125 | u32 ien = efm32_uart_read32(efm_port, UARTn_IEN); | ||
| 126 | |||
| 127 | efm32_uart_write32(efm_port, UARTn_CMD_TXDIS, UARTn_CMD); | ||
| 128 | ien &= ~(UARTn_IF_TXC | UARTn_IF_TXBL); | ||
| 129 | efm32_uart_write32(efm_port, ien, UARTn_IEN); | ||
| 130 | } | ||
| 131 | |||
| 132 | static void efm32_uart_tx_chars(struct efm32_uart_port *efm_port) | ||
| 133 | { | ||
| 134 | struct uart_port *port = &efm_port->port; | ||
| 135 | struct circ_buf *xmit = &port->state->xmit; | ||
| 136 | |||
| 137 | while (efm32_uart_read32(efm_port, UARTn_STATUS) & | ||
| 138 | UARTn_STATUS_TXBL) { | ||
| 139 | if (port->x_char) { | ||
| 140 | port->icount.tx++; | ||
| 141 | efm32_uart_write32(efm_port, port->x_char, | ||
| 142 | UARTn_TXDATA); | ||
| 143 | port->x_char = 0; | ||
| 144 | continue; | ||
| 145 | } | ||
| 146 | if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) { | ||
| 147 | port->icount.tx++; | ||
| 148 | efm32_uart_write32(efm_port, xmit->buf[xmit->tail], | ||
| 149 | UARTn_TXDATA); | ||
| 150 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
| 151 | } else | ||
| 152 | break; | ||
| 153 | } | ||
| 154 | |||
| 155 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
| 156 | uart_write_wakeup(port); | ||
| 157 | |||
| 158 | if (!port->x_char && uart_circ_empty(xmit) && | ||
| 159 | efm32_uart_read32(efm_port, UARTn_STATUS) & | ||
| 160 | UARTn_STATUS_TXC) | ||
| 161 | efm32_uart_stop_tx(port); | ||
| 162 | } | ||
| 163 | |||
| 164 | static void efm32_uart_start_tx(struct uart_port *port) | ||
| 165 | { | ||
| 166 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
| 167 | u32 ien; | ||
| 168 | |||
| 169 | efm32_uart_write32(efm_port, | ||
| 170 | UARTn_IF_TXBL | UARTn_IF_TXC, UARTn_IFC); | ||
| 171 | ien = efm32_uart_read32(efm_port, UARTn_IEN); | ||
| 172 | efm32_uart_write32(efm_port, | ||
| 173 | ien | UARTn_IF_TXBL | UARTn_IF_TXC, UARTn_IEN); | ||
| 174 | efm32_uart_write32(efm_port, UARTn_CMD_TXEN, UARTn_CMD); | ||
| 175 | |||
| 176 | efm32_uart_tx_chars(efm_port); | ||
| 177 | } | ||
| 178 | |||
| 179 | static void efm32_uart_stop_rx(struct uart_port *port) | ||
| 180 | { | ||
| 181 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
| 182 | |||
| 183 | efm32_uart_write32(efm_port, UARTn_CMD_RXDIS, UARTn_CMD); | ||
| 184 | } | ||
| 185 | |||
| 186 | static void efm32_uart_break_ctl(struct uart_port *port, int ctl) | ||
| 187 | { | ||
| 188 | /* not possible without fiddling with gpios */ | ||
| 189 | } | ||
| 190 | |||
| 191 | static void efm32_uart_rx_chars(struct efm32_uart_port *efm_port) | ||
| 192 | { | ||
| 193 | struct uart_port *port = &efm_port->port; | ||
| 194 | |||
| 195 | while (efm32_uart_read32(efm_port, UARTn_STATUS) & | ||
| 196 | UARTn_STATUS_RXDATAV) { | ||
| 197 | u32 rxdata = efm32_uart_read32(efm_port, UARTn_RXDATAX); | ||
| 198 | int flag = 0; | ||
| 199 | |||
| 200 | /* | ||
| 201 | * This is a reserved bit and I only saw it read as 0. But to be | ||
| 202 | * sure not to be confused too much by new devices adhere to the | ||
| 203 | * warning in the reference manual that reserved bits might | ||
| 204 | * read as 1 in the future. | ||
| 205 | */ | ||
| 206 | rxdata &= ~SW_UARTn_RXDATAX_BERR; | ||
| 207 | |||
| 208 | port->icount.rx++; | ||
| 209 | |||
| 210 | if ((rxdata & UARTn_RXDATAX_FERR) && | ||
| 211 | !(rxdata & UARTn_RXDATAX_RXDATA__MASK)) { | ||
| 212 | rxdata |= SW_UARTn_RXDATAX_BERR; | ||
| 213 | port->icount.brk++; | ||
| 214 | if (uart_handle_break(port)) | ||
| 215 | continue; | ||
| 216 | } else if (rxdata & UARTn_RXDATAX_PERR) | ||
| 217 | port->icount.parity++; | ||
| 218 | else if (rxdata & UARTn_RXDATAX_FERR) | ||
| 219 | port->icount.frame++; | ||
| 220 | |||
| 221 | rxdata &= port->read_status_mask; | ||
| 222 | |||
| 223 | if (rxdata & SW_UARTn_RXDATAX_BERR) | ||
| 224 | flag = TTY_BREAK; | ||
| 225 | else if (rxdata & UARTn_RXDATAX_PERR) | ||
| 226 | flag = TTY_PARITY; | ||
| 227 | else if (rxdata & UARTn_RXDATAX_FERR) | ||
| 228 | flag = TTY_FRAME; | ||
| 229 | else if (uart_handle_sysrq_char(port, | ||
| 230 | rxdata & UARTn_RXDATAX_RXDATA__MASK)) | ||
| 231 | continue; | ||
| 232 | |||
| 233 | if ((rxdata & port->ignore_status_mask) == 0) | ||
| 234 | tty_insert_flip_char(&port->state->port, | ||
| 235 | rxdata & UARTn_RXDATAX_RXDATA__MASK, flag); | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 239 | static irqreturn_t efm32_uart_rxirq(int irq, void *data) | ||
| 240 | { | ||
| 241 | struct efm32_uart_port *efm_port = data; | ||
| 242 | u32 irqflag = efm32_uart_read32(efm_port, UARTn_IF); | ||
| 243 | int handled = IRQ_NONE; | ||
| 244 | struct uart_port *port = &efm_port->port; | ||
| 245 | struct tty_port *tport = &port->state->port; | ||
| 246 | |||
| 247 | spin_lock(&port->lock); | ||
| 248 | |||
| 249 | if (irqflag & UARTn_IF_RXDATAV) { | ||
| 250 | efm32_uart_write32(efm_port, UARTn_IF_RXDATAV, UARTn_IFC); | ||
| 251 | efm32_uart_rx_chars(efm_port); | ||
| 252 | |||
| 253 | handled = IRQ_HANDLED; | ||
| 254 | } | ||
| 255 | |||
| 256 | if (irqflag & UARTn_IF_RXOF) { | ||
| 257 | efm32_uart_write32(efm_port, UARTn_IF_RXOF, UARTn_IFC); | ||
| 258 | port->icount.overrun++; | ||
| 259 | tty_insert_flip_char(tport, 0, TTY_OVERRUN); | ||
| 260 | |||
| 261 | handled = IRQ_HANDLED; | ||
| 262 | } | ||
| 263 | |||
| 264 | spin_unlock(&port->lock); | ||
| 265 | |||
| 266 | tty_flip_buffer_push(tport); | ||
| 267 | |||
| 268 | return handled; | ||
| 269 | } | ||
| 270 | |||
| 271 | static irqreturn_t efm32_uart_txirq(int irq, void *data) | ||
| 272 | { | ||
| 273 | struct efm32_uart_port *efm_port = data; | ||
| 274 | u32 irqflag = efm32_uart_read32(efm_port, UARTn_IF); | ||
| 275 | |||
| 276 | /* TXBL doesn't need to be cleared */ | ||
| 277 | if (irqflag & UARTn_IF_TXC) | ||
| 278 | efm32_uart_write32(efm_port, UARTn_IF_TXC, UARTn_IFC); | ||
| 279 | |||
| 280 | if (irqflag & (UARTn_IF_TXC | UARTn_IF_TXBL)) { | ||
| 281 | efm32_uart_tx_chars(efm_port); | ||
| 282 | return IRQ_HANDLED; | ||
| 283 | } else | ||
| 284 | return IRQ_NONE; | ||
| 285 | } | ||
| 286 | |||
| 287 | static int efm32_uart_startup(struct uart_port *port) | ||
| 288 | { | ||
| 289 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
| 290 | int ret; | ||
| 291 | |||
| 292 | ret = clk_enable(efm_port->clk); | ||
| 293 | if (ret) { | ||
| 294 | efm_debug(efm_port, "failed to enable clk\n"); | ||
| 295 | goto err_clk_enable; | ||
| 296 | } | ||
| 297 | port->uartclk = clk_get_rate(efm_port->clk); | ||
| 298 | |||
| 299 | /* Enable pins at configured location */ | ||
| 300 | efm32_uart_write32(efm_port, | ||
| 301 | UARTn_ROUTE_LOCATION(efm_port->pdata.location) | | ||
| 302 | UARTn_ROUTE_RXPEN | UARTn_ROUTE_TXPEN, | ||
| 303 | UARTn_ROUTE); | ||
| 304 | |||
| 305 | ret = request_irq(port->irq, efm32_uart_rxirq, 0, | ||
| 306 | DRIVER_NAME, efm_port); | ||
| 307 | if (ret) { | ||
| 308 | efm_debug(efm_port, "failed to register rxirq\n"); | ||
| 309 | goto err_request_irq_rx; | ||
| 310 | } | ||
| 311 | |||
| 312 | /* disable all irqs */ | ||
| 313 | efm32_uart_write32(efm_port, 0, UARTn_IEN); | ||
| 314 | |||
| 315 | ret = request_irq(efm_port->txirq, efm32_uart_txirq, 0, | ||
| 316 | DRIVER_NAME, efm_port); | ||
| 317 | if (ret) { | ||
| 318 | efm_debug(efm_port, "failed to register txirq\n"); | ||
| 319 | free_irq(port->irq, efm_port); | ||
| 320 | err_request_irq_rx: | ||
| 321 | |||
| 322 | clk_disable(efm_port->clk); | ||
| 323 | } else { | ||
| 324 | efm32_uart_write32(efm_port, | ||
| 325 | UARTn_IF_RXDATAV | UARTn_IF_RXOF, UARTn_IEN); | ||
| 326 | efm32_uart_write32(efm_port, UARTn_CMD_RXEN, UARTn_CMD); | ||
| 327 | } | ||
| 328 | |||
| 329 | err_clk_enable: | ||
| 330 | return ret; | ||
| 331 | } | ||
| 332 | |||
| 333 | static void efm32_uart_shutdown(struct uart_port *port) | ||
| 334 | { | ||
| 335 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
| 336 | |||
| 337 | efm32_uart_write32(efm_port, 0, UARTn_IEN); | ||
| 338 | free_irq(port->irq, efm_port); | ||
| 339 | |||
| 340 | clk_disable(efm_port->clk); | ||
| 341 | } | ||
| 342 | |||
| 343 | static void efm32_uart_set_termios(struct uart_port *port, | ||
| 344 | struct ktermios *new, struct ktermios *old) | ||
| 345 | { | ||
| 346 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
| 347 | unsigned long flags; | ||
| 348 | unsigned baud; | ||
| 349 | u32 clkdiv; | ||
| 350 | u32 frame = 0; | ||
| 351 | |||
| 352 | /* no modem control lines */ | ||
| 353 | new->c_cflag &= ~(CRTSCTS | CMSPAR); | ||
| 354 | |||
| 355 | baud = uart_get_baud_rate(port, new, old, | ||
| 356 | DIV_ROUND_CLOSEST(port->uartclk, 16 * 8192), | ||
| 357 | DIV_ROUND_CLOSEST(port->uartclk, 16)); | ||
| 358 | |||
| 359 | switch (new->c_cflag & CSIZE) { | ||
| 360 | case CS5: | ||
| 361 | frame |= UARTn_FRAME_DATABITS(5); | ||
| 362 | break; | ||
| 363 | case CS6: | ||
| 364 | frame |= UARTn_FRAME_DATABITS(6); | ||
| 365 | break; | ||
| 366 | case CS7: | ||
| 367 | frame |= UARTn_FRAME_DATABITS(7); | ||
| 368 | break; | ||
| 369 | case CS8: | ||
| 370 | frame |= UARTn_FRAME_DATABITS(8); | ||
| 371 | break; | ||
| 372 | } | ||
| 373 | |||
| 374 | if (new->c_cflag & CSTOPB) | ||
| 375 | /* the receiver only verifies the first stop bit */ | ||
| 376 | frame |= UARTn_FRAME_STOPBITS_TWO; | ||
| 377 | else | ||
| 378 | frame |= UARTn_FRAME_STOPBITS_ONE; | ||
| 379 | |||
| 380 | if (new->c_cflag & PARENB) { | ||
| 381 | if (new->c_cflag & PARODD) | ||
| 382 | frame |= UARTn_FRAME_PARITY_ODD; | ||
| 383 | else | ||
| 384 | frame |= UARTn_FRAME_PARITY_EVEN; | ||
| 385 | } else | ||
| 386 | frame |= UARTn_FRAME_PARITY_NONE; | ||
| 387 | |||
| 388 | /* | ||
| 389 | * the 6 lowest bits of CLKDIV are dc, bit 6 has value 0.25. | ||
| 390 | * port->uartclk <= 14e6, so 4 * port->uartclk doesn't overflow. | ||
| 391 | */ | ||
| 392 | clkdiv = (DIV_ROUND_CLOSEST(4 * port->uartclk, 16 * baud) - 4) << 6; | ||
| 393 | |||
| 394 | spin_lock_irqsave(&port->lock, flags); | ||
| 395 | |||
| 396 | efm32_uart_write32(efm_port, | ||
| 397 | UARTn_CMD_TXDIS | UARTn_CMD_RXDIS, UARTn_CMD); | ||
| 398 | |||
| 399 | port->read_status_mask = UARTn_RXDATAX_RXDATA__MASK; | ||
| 400 | if (new->c_iflag & INPCK) | ||
| 401 | port->read_status_mask |= | ||
| 402 | UARTn_RXDATAX_FERR | UARTn_RXDATAX_PERR; | ||
| 403 | if (new->c_iflag & (IGNBRK | BRKINT | PARMRK)) | ||
| 404 | port->read_status_mask |= SW_UARTn_RXDATAX_BERR; | ||
| 405 | |||
| 406 | port->ignore_status_mask = 0; | ||
| 407 | if (new->c_iflag & IGNPAR) | ||
| 408 | port->ignore_status_mask |= | ||
| 409 | UARTn_RXDATAX_FERR | UARTn_RXDATAX_PERR; | ||
| 410 | if (new->c_iflag & IGNBRK) | ||
| 411 | port->ignore_status_mask |= SW_UARTn_RXDATAX_BERR; | ||
| 412 | |||
| 413 | uart_update_timeout(port, new->c_cflag, baud); | ||
| 414 | |||
| 415 | efm32_uart_write32(efm_port, UARTn_CTRL_TXBIL, UARTn_CTRL); | ||
| 416 | efm32_uart_write32(efm_port, frame, UARTn_FRAME); | ||
| 417 | efm32_uart_write32(efm_port, clkdiv, UARTn_CLKDIV); | ||
| 418 | |||
| 419 | efm32_uart_write32(efm_port, UARTn_CMD_TXEN | UARTn_CMD_RXEN, | ||
| 420 | UARTn_CMD); | ||
| 421 | |||
| 422 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 423 | } | ||
| 424 | |||
| 425 | static const char *efm32_uart_type(struct uart_port *port) | ||
| 426 | { | ||
| 427 | return port->type == PORT_EFMUART ? "efm32-uart" : NULL; | ||
| 428 | } | ||
| 429 | |||
| 430 | static void efm32_uart_release_port(struct uart_port *port) | ||
| 431 | { | ||
| 432 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
| 433 | |||
| 434 | clk_unprepare(efm_port->clk); | ||
| 435 | clk_put(efm_port->clk); | ||
| 436 | iounmap(port->membase); | ||
| 437 | } | ||
| 438 | |||
| 439 | static int efm32_uart_request_port(struct uart_port *port) | ||
| 440 | { | ||
| 441 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
| 442 | int ret; | ||
| 443 | |||
| 444 | port->membase = ioremap(port->mapbase, 60); | ||
| 445 | if (!efm_port->port.membase) { | ||
| 446 | ret = -ENOMEM; | ||
| 447 | efm_debug(efm_port, "failed to remap\n"); | ||
| 448 | goto err_ioremap; | ||
| 449 | } | ||
| 450 | |||
| 451 | efm_port->clk = clk_get(port->dev, NULL); | ||
| 452 | if (IS_ERR(efm_port->clk)) { | ||
| 453 | ret = PTR_ERR(efm_port->clk); | ||
| 454 | efm_debug(efm_port, "failed to get clock\n"); | ||
| 455 | goto err_clk_get; | ||
| 456 | } | ||
| 457 | |||
| 458 | ret = clk_prepare(efm_port->clk); | ||
| 459 | if (ret) { | ||
| 460 | clk_put(efm_port->clk); | ||
| 461 | err_clk_get: | ||
| 462 | |||
| 463 | iounmap(port->membase); | ||
| 464 | err_ioremap: | ||
| 465 | return ret; | ||
| 466 | } | ||
| 467 | return 0; | ||
| 468 | } | ||
| 469 | |||
| 470 | static void efm32_uart_config_port(struct uart_port *port, int type) | ||
| 471 | { | ||
| 472 | if (type & UART_CONFIG_TYPE && | ||
| 473 | !efm32_uart_request_port(port)) | ||
| 474 | port->type = PORT_EFMUART; | ||
| 475 | } | ||
| 476 | |||
| 477 | static int efm32_uart_verify_port(struct uart_port *port, | ||
| 478 | struct serial_struct *serinfo) | ||
| 479 | { | ||
| 480 | int ret = 0; | ||
| 481 | |||
| 482 | if (serinfo->type != PORT_UNKNOWN && serinfo->type != PORT_EFMUART) | ||
| 483 | ret = -EINVAL; | ||
| 484 | |||
| 485 | return ret; | ||
| 486 | } | ||
| 487 | |||
| 488 | static const struct uart_ops efm32_uart_pops = { | ||
| 489 | .tx_empty = efm32_uart_tx_empty, | ||
| 490 | .set_mctrl = efm32_uart_set_mctrl, | ||
| 491 | .get_mctrl = efm32_uart_get_mctrl, | ||
| 492 | .stop_tx = efm32_uart_stop_tx, | ||
| 493 | .start_tx = efm32_uart_start_tx, | ||
| 494 | .stop_rx = efm32_uart_stop_rx, | ||
| 495 | .break_ctl = efm32_uart_break_ctl, | ||
| 496 | .startup = efm32_uart_startup, | ||
| 497 | .shutdown = efm32_uart_shutdown, | ||
| 498 | .set_termios = efm32_uart_set_termios, | ||
| 499 | .type = efm32_uart_type, | ||
| 500 | .release_port = efm32_uart_release_port, | ||
| 501 | .request_port = efm32_uart_request_port, | ||
| 502 | .config_port = efm32_uart_config_port, | ||
| 503 | .verify_port = efm32_uart_verify_port, | ||
| 504 | }; | ||
| 505 | |||
| 506 | static struct efm32_uart_port *efm32_uart_ports[5]; | ||
| 507 | |||
| 508 | #ifdef CONFIG_SERIAL_EFM32_UART_CONSOLE | ||
| 509 | static void efm32_uart_console_putchar(struct uart_port *port, int ch) | ||
| 510 | { | ||
| 511 | struct efm32_uart_port *efm_port = to_efm_port(port); | ||
| 512 | unsigned int timeout = 0x400; | ||
| 513 | u32 status; | ||
| 514 | |||
| 515 | while (1) { | ||
| 516 | status = efm32_uart_read32(efm_port, UARTn_STATUS); | ||
| 517 | |||
| 518 | if (status & UARTn_STATUS_TXBL) | ||
| 519 | break; | ||
| 520 | if (!timeout--) | ||
| 521 | return; | ||
| 522 | } | ||
| 523 | efm32_uart_write32(efm_port, ch, UARTn_TXDATA); | ||
| 524 | } | ||
| 525 | |||
| 526 | static void efm32_uart_console_write(struct console *co, const char *s, | ||
| 527 | unsigned int count) | ||
| 528 | { | ||
| 529 | struct efm32_uart_port *efm_port = efm32_uart_ports[co->index]; | ||
| 530 | u32 status = efm32_uart_read32(efm_port, UARTn_STATUS); | ||
| 531 | unsigned int timeout = 0x400; | ||
| 532 | |||
| 533 | if (!(status & UARTn_STATUS_TXENS)) | ||
| 534 | efm32_uart_write32(efm_port, UARTn_CMD_TXEN, UARTn_CMD); | ||
| 535 | |||
| 536 | uart_console_write(&efm_port->port, s, count, | ||
| 537 | efm32_uart_console_putchar); | ||
| 538 | |||
| 539 | /* Wait for the transmitter to become empty */ | ||
| 540 | while (1) { | ||
| 541 | u32 status = efm32_uart_read32(efm_port, UARTn_STATUS); | ||
| 542 | if (status & UARTn_STATUS_TXC) | ||
| 543 | break; | ||
| 544 | if (!timeout--) | ||
| 545 | break; | ||
| 546 | } | ||
| 547 | |||
| 548 | if (!(status & UARTn_STATUS_TXENS)) | ||
| 549 | efm32_uart_write32(efm_port, UARTn_CMD_TXDIS, UARTn_CMD); | ||
| 550 | } | ||
| 551 | |||
| 552 | static void efm32_uart_console_get_options(struct efm32_uart_port *efm_port, | ||
| 553 | int *baud, int *parity, int *bits) | ||
| 554 | { | ||
| 555 | u32 ctrl = efm32_uart_read32(efm_port, UARTn_CTRL); | ||
| 556 | u32 route, clkdiv, frame; | ||
| 557 | |||
| 558 | if (ctrl & UARTn_CTRL_SYNC) | ||
| 559 | /* not operating in async mode */ | ||
| 560 | return; | ||
| 561 | |||
| 562 | route = efm32_uart_read32(efm_port, UARTn_ROUTE); | ||
| 563 | if (!(route & UARTn_ROUTE_TXPEN)) | ||
| 564 | /* tx pin not routed */ | ||
| 565 | return; | ||
| 566 | |||
| 567 | clkdiv = efm32_uart_read32(efm_port, UARTn_CLKDIV); | ||
| 568 | |||
| 569 | *baud = DIV_ROUND_CLOSEST(4 * efm_port->port.uartclk, | ||
| 570 | 16 * (4 + (clkdiv >> 6))); | ||
| 571 | |||
| 572 | frame = efm32_uart_read32(efm_port, UARTn_FRAME); | ||
| 573 | switch (frame & UARTn_FRAME_PARITY__MASK) { | ||
| 574 | case UARTn_FRAME_PARITY_ODD: | ||
| 575 | *parity = 'o'; | ||
| 576 | break; | ||
| 577 | case UARTn_FRAME_PARITY_EVEN: | ||
| 578 | *parity = 'e'; | ||
| 579 | break; | ||
| 580 | default: | ||
| 581 | *parity = 'n'; | ||
| 582 | } | ||
| 583 | |||
| 584 | *bits = (frame & UARTn_FRAME_DATABITS__MASK) - | ||
| 585 | UARTn_FRAME_DATABITS(4) + 4; | ||
| 586 | |||
| 587 | efm_debug(efm_port, "get_opts: options=%d%c%d\n", | ||
| 588 | *baud, *parity, *bits); | ||
| 589 | } | ||
| 590 | |||
| 591 | static int efm32_uart_console_setup(struct console *co, char *options) | ||
| 592 | { | ||
| 593 | struct efm32_uart_port *efm_port; | ||
| 594 | int baud = 115200; | ||
| 595 | int bits = 8; | ||
| 596 | int parity = 'n'; | ||
| 597 | int flow = 'n'; | ||
| 598 | int ret; | ||
| 599 | |||
| 600 | if (co->index < 0 || co->index >= ARRAY_SIZE(efm32_uart_ports)) { | ||
| 601 | unsigned i; | ||
| 602 | for (i = 0; i < ARRAY_SIZE(efm32_uart_ports); ++i) { | ||
| 603 | if (efm32_uart_ports[i]) { | ||
| 604 | pr_warn("efm32-console: fall back to console index %u (from %hhi)\n", | ||
| 605 | i, co->index); | ||
| 606 | co->index = i; | ||
| 607 | break; | ||
| 608 | } | ||
| 609 | } | ||
| 610 | } | ||
| 611 | |||
| 612 | efm_port = efm32_uart_ports[co->index]; | ||
| 613 | if (!efm_port) { | ||
| 614 | pr_warn("efm32-console: No port at %d\n", co->index); | ||
| 615 | return -ENODEV; | ||
| 616 | } | ||
| 617 | |||
| 618 | ret = clk_prepare(efm_port->clk); | ||
| 619 | if (ret) { | ||
| 620 | dev_warn(efm_port->port.dev, | ||
| 621 | "console: clk_prepare failed: %d\n", ret); | ||
| 622 | return ret; | ||
| 623 | } | ||
| 624 | |||
| 625 | efm_port->port.uartclk = clk_get_rate(efm_port->clk); | ||
| 626 | |||
| 627 | if (options) | ||
| 628 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
| 629 | else | ||
| 630 | efm32_uart_console_get_options(efm_port, | ||
| 631 | &baud, &parity, &bits); | ||
| 632 | |||
| 633 | return uart_set_options(&efm_port->port, co, baud, parity, bits, flow); | ||
| 634 | } | ||
| 635 | |||
| 636 | static struct uart_driver efm32_uart_reg; | ||
| 637 | |||
| 638 | static struct console efm32_uart_console = { | ||
| 639 | .name = DEV_NAME, | ||
| 640 | .write = efm32_uart_console_write, | ||
| 641 | .device = uart_console_device, | ||
| 642 | .setup = efm32_uart_console_setup, | ||
| 643 | .flags = CON_PRINTBUFFER, | ||
| 644 | .index = -1, | ||
| 645 | .data = &efm32_uart_reg, | ||
| 646 | }; | ||
| 647 | |||
| 648 | #else | ||
| 649 | #define efm32_uart_console (*(struct console *)NULL) | ||
| 650 | #endif /* ifdef CONFIG_SERIAL_EFM32_UART_CONSOLE / else */ | ||
| 651 | |||
| 652 | static struct uart_driver efm32_uart_reg = { | ||
| 653 | .owner = THIS_MODULE, | ||
| 654 | .driver_name = DRIVER_NAME, | ||
| 655 | .dev_name = DEV_NAME, | ||
| 656 | .nr = ARRAY_SIZE(efm32_uart_ports), | ||
| 657 | .cons = &efm32_uart_console, | ||
| 658 | }; | ||
| 659 | |||
| 660 | static int efm32_uart_probe_dt(struct platform_device *pdev, | ||
| 661 | struct efm32_uart_port *efm_port) | ||
| 662 | { | ||
| 663 | struct device_node *np = pdev->dev.of_node; | ||
| 664 | u32 location; | ||
| 665 | int ret; | ||
| 666 | |||
| 667 | if (!np) | ||
| 668 | return 1; | ||
| 669 | |||
| 670 | ret = of_property_read_u32(np, "energymicro,location", &location); | ||
| 671 | |||
| 672 | if (ret) | ||
| 673 | /* fall back to wrongly namespaced property */ | ||
| 674 | ret = of_property_read_u32(np, "efm32,location", &location); | ||
| 675 | |||
| 676 | if (ret) | ||
| 677 | /* fall back to old and (wrongly) generic property "location" */ | ||
| 678 | ret = of_property_read_u32(np, "location", &location); | ||
| 679 | |||
| 680 | if (!ret) { | ||
| 681 | if (location > 5) { | ||
| 682 | dev_err(&pdev->dev, "invalid location\n"); | ||
| 683 | return -EINVAL; | ||
| 684 | } | ||
| 685 | efm_debug(efm_port, "using location %u\n", location); | ||
| 686 | efm_port->pdata.location = location; | ||
| 687 | } else { | ||
| 688 | efm_debug(efm_port, "fall back to location 0\n"); | ||
| 689 | } | ||
| 690 | |||
| 691 | ret = of_alias_get_id(np, "serial"); | ||
| 692 | if (ret < 0) { | ||
| 693 | dev_err(&pdev->dev, "failed to get alias id: %d\n", ret); | ||
| 694 | return ret; | ||
| 695 | } else { | ||
| 696 | efm_port->port.line = ret; | ||
| 697 | return 0; | ||
| 698 | } | ||
| 699 | |||
| 700 | } | ||
| 701 | |||
| 702 | static int efm32_uart_probe(struct platform_device *pdev) | ||
| 703 | { | ||
| 704 | struct efm32_uart_port *efm_port; | ||
| 705 | struct resource *res; | ||
| 706 | unsigned int line; | ||
| 707 | int ret; | ||
| 708 | |||
| 709 | efm_port = kzalloc(sizeof(*efm_port), GFP_KERNEL); | ||
| 710 | if (!efm_port) { | ||
| 711 | dev_dbg(&pdev->dev, "failed to allocate private data\n"); | ||
| 712 | return -ENOMEM; | ||
| 713 | } | ||
| 714 | |||
| 715 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 716 | if (!res) { | ||
| 717 | ret = -ENODEV; | ||
| 718 | dev_dbg(&pdev->dev, "failed to determine base address\n"); | ||
| 719 | goto err_get_base; | ||
| 720 | } | ||
| 721 | |||
| 722 | if (resource_size(res) < 60) { | ||
| 723 | ret = -EINVAL; | ||
| 724 | dev_dbg(&pdev->dev, "memory resource too small\n"); | ||
| 725 | goto err_too_small; | ||
| 726 | } | ||
| 727 | |||
| 728 | ret = platform_get_irq(pdev, 0); | ||
| 729 | if (ret <= 0) { | ||
| 730 | dev_dbg(&pdev->dev, "failed to get rx irq\n"); | ||
| 731 | goto err_get_rxirq; | ||
| 732 | } | ||
| 733 | |||
| 734 | efm_port->port.irq = ret; | ||
| 735 | |||
| 736 | ret = platform_get_irq(pdev, 1); | ||
| 737 | if (ret <= 0) | ||
| 738 | ret = efm_port->port.irq + 1; | ||
| 739 | |||
| 740 | efm_port->txirq = ret; | ||
| 741 | |||
| 742 | efm_port->port.dev = &pdev->dev; | ||
| 743 | efm_port->port.mapbase = res->start; | ||
| 744 | efm_port->port.type = PORT_EFMUART; | ||
| 745 | efm_port->port.iotype = UPIO_MEM32; | ||
| 746 | efm_port->port.fifosize = 2; | ||
| 747 | efm_port->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_EFM32_UART_CONSOLE); | ||
| 748 | efm_port->port.ops = &efm32_uart_pops; | ||
| 749 | efm_port->port.flags = UPF_BOOT_AUTOCONF; | ||
| 750 | |||
| 751 | ret = efm32_uart_probe_dt(pdev, efm_port); | ||
| 752 | if (ret > 0) { | ||
| 753 | /* not created by device tree */ | ||
| 754 | const struct efm32_uart_pdata *pdata = dev_get_platdata(&pdev->dev); | ||
| 755 | |||
| 756 | efm_port->port.line = pdev->id; | ||
| 757 | |||
| 758 | if (pdata) | ||
| 759 | efm_port->pdata = *pdata; | ||
| 760 | } else if (ret < 0) | ||
| 761 | goto err_probe_dt; | ||
| 762 | |||
| 763 | line = efm_port->port.line; | ||
| 764 | |||
| 765 | if (line >= 0 && line < ARRAY_SIZE(efm32_uart_ports)) | ||
| 766 | efm32_uart_ports[line] = efm_port; | ||
| 767 | |||
| 768 | ret = uart_add_one_port(&efm32_uart_reg, &efm_port->port); | ||
| 769 | if (ret) { | ||
| 770 | dev_dbg(&pdev->dev, "failed to add port: %d\n", ret); | ||
| 771 | |||
| 772 | if (line >= 0 && line < ARRAY_SIZE(efm32_uart_ports)) | ||
| 773 | efm32_uart_ports[line] = NULL; | ||
| 774 | err_probe_dt: | ||
| 775 | err_get_rxirq: | ||
| 776 | err_too_small: | ||
| 777 | err_get_base: | ||
| 778 | kfree(efm_port); | ||
| 779 | } else { | ||
| 780 | platform_set_drvdata(pdev, efm_port); | ||
| 781 | dev_dbg(&pdev->dev, "\\o/\n"); | ||
| 782 | } | ||
| 783 | |||
| 784 | return ret; | ||
| 785 | } | ||
| 786 | |||
| 787 | static int efm32_uart_remove(struct platform_device *pdev) | ||
| 788 | { | ||
| 789 | struct efm32_uart_port *efm_port = platform_get_drvdata(pdev); | ||
| 790 | unsigned int line = efm_port->port.line; | ||
| 791 | |||
| 792 | uart_remove_one_port(&efm32_uart_reg, &efm_port->port); | ||
| 793 | |||
| 794 | if (line >= 0 && line < ARRAY_SIZE(efm32_uart_ports)) | ||
| 795 | efm32_uart_ports[line] = NULL; | ||
| 796 | |||
| 797 | kfree(efm_port); | ||
| 798 | |||
| 799 | return 0; | ||
| 800 | } | ||
| 801 | |||
| 802 | static const struct of_device_id efm32_uart_dt_ids[] = { | ||
| 803 | { | ||
| 804 | .compatible = "energymicro,efm32-uart", | ||
| 805 | }, { | ||
| 806 | /* doesn't follow the "vendor,device" scheme, don't use */ | ||
| 807 | .compatible = "efm32,uart", | ||
| 808 | }, { | ||
| 809 | /* sentinel */ | ||
| 810 | } | ||
| 811 | }; | ||
| 812 | MODULE_DEVICE_TABLE(of, efm32_uart_dt_ids); | ||
| 813 | |||
| 814 | static struct platform_driver efm32_uart_driver = { | ||
| 815 | .probe = efm32_uart_probe, | ||
| 816 | .remove = efm32_uart_remove, | ||
| 817 | |||
| 818 | .driver = { | ||
| 819 | .name = DRIVER_NAME, | ||
| 820 | .of_match_table = efm32_uart_dt_ids, | ||
| 821 | }, | ||
| 822 | }; | ||
| 823 | |||
| 824 | static int __init efm32_uart_init(void) | ||
| 825 | { | ||
| 826 | int ret; | ||
| 827 | |||
| 828 | ret = uart_register_driver(&efm32_uart_reg); | ||
| 829 | if (ret) | ||
| 830 | return ret; | ||
| 831 | |||
| 832 | ret = platform_driver_register(&efm32_uart_driver); | ||
| 833 | if (ret) | ||
| 834 | uart_unregister_driver(&efm32_uart_reg); | ||
| 835 | |||
| 836 | pr_info("EFM32 UART/USART driver\n"); | ||
| 837 | |||
| 838 | return ret; | ||
| 839 | } | ||
| 840 | module_init(efm32_uart_init); | ||
| 841 | |||
| 842 | static void __exit efm32_uart_exit(void) | ||
| 843 | { | ||
| 844 | platform_driver_unregister(&efm32_uart_driver); | ||
| 845 | uart_unregister_driver(&efm32_uart_reg); | ||
| 846 | } | ||
| 847 | module_exit(efm32_uart_exit); | ||
| 848 | |||
| 849 | MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>"); | ||
| 850 | MODULE_DESCRIPTION("EFM32 UART/USART driver"); | ||
| 851 | MODULE_LICENSE("GPL v2"); | ||
| 852 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
| @@ -2580,9 +2580,7 @@ static struct uart_driver lpuart_reg = { · 2579 unmodified lines | |||
| 2580 | 2580 | ||
| 2581 | static int lpuart_probe(struct platform_device *pdev) | 2581 | static int lpuart_probe(struct platform_device *pdev) |
| 2582 | { | 2582 | { |
| 2583 | const struct of_device_id *of_id = of_match_device(lpuart_dt_ids, | 2583 | const struct lpuart_soc_data *sdata = of_device_get_match_data(&pdev->dev); |
| 2584 | &pdev->dev); | ||
| 2585 | const struct lpuart_soc_data *sdata = of_id->data; | ||
| 2586 | struct device_node *np = pdev->dev.of_node; | 2584 | struct device_node *np = pdev->dev.of_node; |
| 2587 | struct lpuart_port *sport; | 2585 | struct lpuart_port *sport; |
| 2588 | struct resource *res; | 2586 | struct resource *res; |
| @@ -118,7 +118,7 @@ MODULE_DEVICE_TABLE(pci, icom_pci_table); · 117 unmodified lines | |||
| 118 | static LIST_HEAD(icom_adapter_head); | 118 | static LIST_HEAD(icom_adapter_head); |
| 119 | 119 | ||
| 120 | /* spinlock for adapter initialization and changing adapter operations */ | 120 | /* spinlock for adapter initialization and changing adapter operations */ |
| 121 | static spinlock_t icom_lock; | 121 | static DEFINE_SPINLOCK(icom_lock); |
| 122 | 122 | ||
| 123 | #ifdef ICOM_TRACE | 123 | #ifdef ICOM_TRACE |
| 124 | static inline void trace(struct icom_port *icom_port, char *trace_pt, | 124 | static inline void trace(struct icom_port *icom_port, char *trace_pt, |
| @@ -1616,8 +1616,6 @@ static int __init icom_init(void) · 1491 unmodified lines | |||
| 1616 | { | 1616 | { |
| 1617 | int ret; | 1617 | int ret; |
| 1618 | 1618 | ||
| 1619 | spin_lock_init(&icom_lock); | ||
| 1620 | |||
| 1621 | ret = uart_register_driver(&icom_uart_driver); | 1619 | ret = uart_register_driver(&icom_uart_driver); |
| 1622 | if (ret) | 1620 | if (ret) |
| 1623 | return ret; | 1621 | return ret; |
| @@ -1,1390 +0,0 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /**************************************************************************** | ||
| 3 | * | ||
| 4 | * Driver for the IFX 6x60 spi modem. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2008 Option International | ||
| 7 | * Copyright (C) 2008 Filip Aben <f.aben@option.com> | ||
| 8 | * Denis Joseph Barrow <d.barow@option.com> | ||
| 9 | * Jan Dumon <j.dumon@option.com> | ||
| 10 | * | ||
| 11 | * Copyright (C) 2009, 2010 Intel Corp | ||
| 12 | * Russ Gorby <russ.gorby@intel.com> | ||
| 13 | * | ||
| 14 | * Driver modified by Intel from Option gtm501l_spi.c | ||
| 15 | * | ||
| 16 | * Notes | ||
| 17 | * o The driver currently assumes a single device only. If you need to | ||
| 18 | * change this then look for saved_ifx_dev and add a device lookup | ||
| 19 | * o The driver is intended to be big-endian safe but has never been | ||
| 20 | * tested that way (no suitable hardware). There are a couple of FIXME | ||
| 21 | * notes by areas that may need addressing | ||
| 22 | * o Some of the GPIO naming/setup assumptions may need revisiting if | ||
| 23 | * you need to use this driver for another platform. | ||
| 24 | * | ||
| 25 | *****************************************************************************/ | ||
| 26 | #include <linux/dma-mapping.h> | ||
| 27 | #include <linux/module.h> | ||
| 28 | #include <linux/termios.h> | ||
| 29 | #include <linux/tty.h> | ||
| 30 | #include <linux/device.h> | ||
| 31 | #include <linux/spi/spi.h> | ||
| 32 | #include <linux/kfifo.h> | ||
| 33 | #include <linux/tty_flip.h> | ||
| 34 | #include <linux/timer.h> | ||
| 35 | #include <linux/serial.h> | ||
| 36 | #include <linux/interrupt.h> | ||
| 37 | #include <linux/irq.h> | ||
| 38 | #include <linux/rfkill.h> | ||
| 39 | #include <linux/fs.h> | ||
| 40 | #include <linux/ip.h> | ||
| 41 | #include <linux/dmapool.h> | ||
| 42 | #include <linux/gpio/consumer.h> | ||
| 43 | #include <linux/sched.h> | ||
| 44 | #include <linux/time.h> | ||
| 45 | #include <linux/wait.h> | ||
| 46 | #include <linux/pm.h> | ||
| 47 | #include <linux/pm_runtime.h> | ||
| 48 | #include <linux/spi/ifx_modem.h> | ||
| 49 | #include <linux/delay.h> | ||
| 50 | #include <linux/reboot.h> | ||
| 51 | |||
| 52 | #include "ifx6x60.h" | ||
| 53 | |||
| 54 | #define IFX_SPI_MORE_MASK 0x10 | ||
| 55 | #define IFX_SPI_MORE_BIT 4 /* bit position in u8 */ | ||
| 56 | #define IFX_SPI_CTS_BIT 6 /* bit position in u8 */ | ||
| 57 | #define IFX_SPI_MODE SPI_MODE_1 | ||
| 58 | #define IFX_SPI_TTY_ID 0 | ||
| 59 | #define IFX_SPI_TIMEOUT_SEC 2 | ||
| 60 | #define IFX_SPI_HEADER_0 (-1) | ||
| 61 | #define IFX_SPI_HEADER_F (-2) | ||
| 62 | |||
| 63 | #define PO_POST_DELAY 200 | ||
| 64 | |||
| 65 | /* forward reference */ | ||
| 66 | static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev); | ||
| 67 | static int ifx_modem_reboot_callback(struct notifier_block *nfb, | ||
| 68 | unsigned long event, void *data); | ||
| 69 | static int ifx_modem_power_off(struct ifx_spi_device *ifx_dev); | ||
| 70 | |||
| 71 | /* local variables */ | ||
| 72 | static int spi_bpw = 16; /* 8, 16 or 32 bit word length */ | ||
| 73 | static struct tty_driver *tty_drv; | ||
| 74 | static struct ifx_spi_device *saved_ifx_dev; | ||
| 75 | static struct lock_class_key ifx_spi_key; | ||
| 76 | |||
| 77 | static struct notifier_block ifx_modem_reboot_notifier_block = { | ||
| 78 | .notifier_call = ifx_modem_reboot_callback, | ||
| 79 | }; | ||
| 80 | |||
| 81 | static int ifx_modem_power_off(struct ifx_spi_device *ifx_dev) | ||
| 82 | { | ||
| 83 | gpiod_set_value(ifx_dev->gpio.pmu_reset, 1); | ||
| 84 | msleep(PO_POST_DELAY); | ||
| 85 | |||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | static int ifx_modem_reboot_callback(struct notifier_block *nfb, | ||
| 90 | unsigned long event, void *data) | ||
| 91 | { | ||
| 92 | if (saved_ifx_dev) | ||
| 93 | ifx_modem_power_off(saved_ifx_dev); | ||
| 94 | else | ||
| 95 | pr_warn("no ifx modem active;\n"); | ||
| 96 | |||
| 97 | return NOTIFY_OK; | ||
| 98 | } | ||
| 99 | |||
| 100 | /* GPIO/GPE settings */ | ||
| 101 | |||
| 102 | /** | ||
| 103 | * mrdy_set_high - set MRDY GPIO | ||
| 104 | * @ifx: device we are controlling | ||
| 105 | * | ||
| 106 | */ | ||
| 107 | static inline void mrdy_set_high(struct ifx_spi_device *ifx) | ||
| 108 | { | ||
| 109 | gpiod_set_value(ifx->gpio.mrdy, 1); | ||
| 110 | } | ||
| 111 | |||
| 112 | /** | ||
| 113 | * mrdy_set_low - clear MRDY GPIO | ||
| 114 | * @ifx: device we are controlling | ||
| 115 | * | ||
| 116 | */ | ||
| 117 | static inline void mrdy_set_low(struct ifx_spi_device *ifx) | ||
| 118 | { | ||
| 119 | gpiod_set_value(ifx->gpio.mrdy, 0); | ||
| 120 | } | ||
| 121 | |||
| 122 | /** | ||
| 123 | * ifx_spi_power_state_set | ||
| 124 | * @ifx_dev: our SPI device | ||
| 125 | * @val: bits to set | ||
| 126 | * | ||
| 127 | * Set bit in power status and signal power system if status becomes non-0 | ||
| 128 | */ | ||
| 129 | static void | ||
| 130 | ifx_spi_power_state_set(struct ifx_spi_device *ifx_dev, unsigned char val) | ||
| 131 | { | ||
| 132 | unsigned long flags; | ||
| 133 | |||
| 134 | spin_lock_irqsave(&ifx_dev->power_lock, flags); | ||
| 135 | |||
| 136 | /* | ||
| 137 | * if power status is already non-0, just update, else | ||
| 138 | * tell power system | ||
| 139 | */ | ||
| 140 | if (!ifx_dev->power_status) | ||
| 141 | pm_runtime_get(&ifx_dev->spi_dev->dev); | ||
| 142 | ifx_dev->power_status |= val; | ||
| 143 | |||
| 144 | spin_unlock_irqrestore(&ifx_dev->power_lock, flags); | ||
| 145 | } | ||
| 146 | |||
| 147 | /** | ||
| 148 | * ifx_spi_power_state_clear - clear power bit | ||
| 149 | * @ifx_dev: our SPI device | ||
| 150 | * @val: bits to clear | ||
| 151 | * | ||
| 152 | * clear bit in power status and signal power system if status becomes 0 | ||
| 153 | */ | ||
| 154 | static void | ||
| 155 | ifx_spi_power_state_clear(struct ifx_spi_device *ifx_dev, unsigned char val) | ||
| 156 | { | ||
| 157 | unsigned long flags; | ||
| 158 | |||
| 159 | spin_lock_irqsave(&ifx_dev->power_lock, flags); | ||
| 160 | |||
| 161 | if (ifx_dev->power_status) { | ||
| 162 | ifx_dev->power_status &= ~val; | ||
| 163 | if (!ifx_dev->power_status) | ||
| 164 | pm_runtime_put(&ifx_dev->spi_dev->dev); | ||
| 165 | } | ||
| 166 | |||
| 167 | spin_unlock_irqrestore(&ifx_dev->power_lock, flags); | ||
| 168 | } | ||
| 169 | |||
| 170 | /** | ||
| 171 | * swap_buf_8 | ||
| 172 | * @buf: our buffer | ||
| 173 | * @len : number of bytes (not words) in the buffer | ||
| 174 | * @end: end of buffer | ||
| 175 | * | ||
| 176 | * Swap the contents of a buffer into big endian format | ||
| 177 | */ | ||
| 178 | static inline void swap_buf_8(unsigned char *buf, int len, void *end) | ||
| 179 | { | ||
| 180 | /* don't swap buffer if SPI word width is 8 bits */ | ||
| 181 | return; | ||
| 182 | } | ||
| 183 | |||
| 184 | /** | ||
| 185 | * swap_buf_16 | ||
| 186 | * @buf: our buffer | ||
| 187 | * @len : number of bytes (not words) in the buffer | ||
| 188 | * @end: end of buffer | ||
| 189 | * | ||
| 190 | * Swap the contents of a buffer into big endian format | ||
| 191 | */ | ||
| 192 | static inline void swap_buf_16(unsigned char *buf, int len, void *end) | ||
| 193 | { | ||
| 194 | int n; | ||
| 195 | |||
| 196 | u16 *buf_16 = (u16 *)buf; | ||
| 197 | len = ((len + 1) >> 1); | ||
| 198 | if ((void *)&buf_16[len] > end) { | ||
| 199 | pr_err("swap_buf_16: swap exceeds boundary (%p > %p)!", | ||
| 200 | &buf_16[len], end); | ||
| 201 | return; | ||
| 202 | } | ||
| 203 | for (n = 0; n < len; n++) { | ||
| 204 | *buf_16 = cpu_to_be16(*buf_16); | ||
| 205 | buf_16++; | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | /** | ||
| 210 | * swap_buf_32 | ||
| 211 | * @buf: our buffer | ||
| 212 | * @len : number of bytes (not words) in the buffer | ||
| 213 | * @end: end of buffer | ||
| 214 | * | ||
| 215 | * Swap the contents of a buffer into big endian format | ||
| 216 | */ | ||
| 217 | static inline void swap_buf_32(unsigned char *buf, int len, void *end) | ||
| 218 | { | ||
| 219 | int n; | ||
| 220 | |||
| 221 | u32 *buf_32 = (u32 *)buf; | ||
| 222 | len = (len + 3) >> 2; | ||
| 223 | |||
| 224 | if ((void *)&buf_32[len] > end) { | ||
| 225 | pr_err("swap_buf_32: swap exceeds boundary (%p > %p)!\n", | ||
| 226 | &buf_32[len], end); | ||
| 227 | return; | ||
| 228 | } | ||
| 229 | for (n = 0; n < len; n++) { | ||
| 230 | *buf_32 = cpu_to_be32(*buf_32); | ||
| 231 | buf_32++; | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | /** | ||
| 236 | * mrdy_assert - assert MRDY line | ||
| 237 | * @ifx_dev: our SPI device | ||
| 238 | * | ||
| 239 | * Assert mrdy and set timer to wait for SRDY interrupt, if SRDY is low | ||
| 240 | * now. | ||
| 241 | * | ||
| 242 | * FIXME: Can SRDY even go high as we are running this code ? | ||
| 243 | */ | ||
| 244 | static void mrdy_assert(struct ifx_spi_device *ifx_dev) | ||
| 245 | { | ||
| 246 | int val = gpiod_get_value(ifx_dev->gpio.srdy); | ||
| 247 | if (!val) { | ||
| 248 | if (!test_and_set_bit(IFX_SPI_STATE_TIMER_PENDING, | ||
| 249 | &ifx_dev->flags)) { | ||
| 250 | mod_timer(&ifx_dev->spi_timer,jiffies + IFX_SPI_TIMEOUT_SEC*HZ); | ||
| 251 | |||
| 252 | } | ||
| 253 | } | ||
| 254 | ifx_spi_power_state_set(ifx_dev, IFX_SPI_POWER_DATA_PENDING); | ||
| 255 | mrdy_set_high(ifx_dev); | ||
| 256 | } | ||
| 257 | |||
| 258 | /** | ||
| 259 | * ifx_spi_timeout - SPI timeout | ||
| 260 | * @t: timer in our SPI device | ||
| 261 | * | ||
| 262 | * The SPI has timed out: hang up the tty. Users will then see a hangup | ||
| 263 | * and error events. | ||
| 264 | */ | ||
| 265 | static void ifx_spi_timeout(struct timer_list *t) | ||
| 266 | { | ||
| 267 | struct ifx_spi_device *ifx_dev = from_timer(ifx_dev, t, spi_timer); | ||
| 268 | |||
| 269 | dev_warn(&ifx_dev->spi_dev->dev, "*** SPI Timeout ***"); | ||
| 270 | tty_port_tty_hangup(&ifx_dev->tty_port, false); | ||
| 271 | mrdy_set_low(ifx_dev); | ||
| 272 | clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags); | ||
| 273 | } | ||
| 274 | |||
| 275 | /* char/tty operations */ | ||
| 276 | |||
| 277 | /** | ||
| 278 | * ifx_spi_tiocmget - get modem lines | ||
| 279 | * @tty: our tty device | ||
| 280 | * | ||
| 281 | * Map the signal state into Linux modem flags and report the value | ||
| 282 | * in Linux terms | ||
| 283 | */ | ||
| 284 | static int ifx_spi_tiocmget(struct tty_struct *tty) | ||
| 285 | { | ||
| 286 | unsigned int value; | ||
| 287 | struct ifx_spi_device *ifx_dev = tty->driver_data; | ||
| 288 | |||
| 289 | value = | ||
| 290 | (test_bit(IFX_SPI_RTS, &ifx_dev->signal_state) ? TIOCM_RTS : 0) | | ||
| 291 | (test_bit(IFX_SPI_DTR, &ifx_dev->signal_state) ? TIOCM_DTR : 0) | | ||
| 292 | (test_bit(IFX_SPI_CTS, &ifx_dev->signal_state) ? TIOCM_CTS : 0) | | ||
| 293 | (test_bit(IFX_SPI_DSR, &ifx_dev->signal_state) ? TIOCM_DSR : 0) | | ||
| 294 | (test_bit(IFX_SPI_DCD, &ifx_dev->signal_state) ? TIOCM_CAR : 0) | | ||
| 295 | (test_bit(IFX_SPI_RI, &ifx_dev->signal_state) ? TIOCM_RNG : 0); | ||
| 296 | return value; | ||
| 297 | } | ||
| 298 | |||
| 299 | /** | ||
| 300 | * ifx_spi_tiocmset - set modem bits | ||
| 301 | * @tty: the tty structure | ||
| 302 | * @set: bits to set | ||
| 303 | * @clear: bits to clear | ||
| 304 | * | ||
| 305 | * The IFX6x60 only supports DTR and RTS. Set them accordingly | ||
| 306 | * and flag that an update to the modem is needed. | ||
| 307 | * | ||
| 308 | * FIXME: do we need to kick the tranfers when we do this ? | ||
| 309 | */ | ||
| 310 | static int ifx_spi_tiocmset(struct tty_struct *tty, | ||
| 311 | unsigned int set, unsigned int clear) | ||
| 312 | { | ||
| 313 | struct ifx_spi_device *ifx_dev = tty->driver_data; | ||
| 314 | |||
| 315 | if (set & TIOCM_RTS) | ||
| 316 | set_bit(IFX_SPI_RTS, &ifx_dev->signal_state); | ||
| 317 | if (set & TIOCM_DTR) | ||
| 318 | set_bit(IFX_SPI_DTR, &ifx_dev->signal_state); | ||
| 319 | if (clear & TIOCM_RTS) | ||
| 320 | clear_bit(IFX_SPI_RTS, &ifx_dev->signal_state); | ||
| 321 | if (clear & TIOCM_DTR) | ||
| 322 | clear_bit(IFX_SPI_DTR, &ifx_dev->signal_state); | ||
| 323 | |||
| 324 | set_bit(IFX_SPI_UPDATE, &ifx_dev->signal_state); | ||
| 325 | return 0; | ||
| 326 | } | ||
| 327 | |||
| 328 | /** | ||
| 329 | * ifx_spi_open - called on tty open | ||
| 330 | * @tty: our tty device | ||
| 331 | * @filp: file handle being associated with the tty | ||
| 332 | * | ||
| 333 | * Open the tty interface. We let the tty_port layer do all the work | ||
| 334 | * for us. | ||
| 335 | * | ||
| 336 | * FIXME: Remove single device assumption and saved_ifx_dev | ||
| 337 | */ | ||
| 338 | static int ifx_spi_open(struct tty_struct *tty, struct file *filp) | ||
| 339 | { | ||
| 340 | return tty_port_open(&saved_ifx_dev->tty_port, tty, filp); | ||
| 341 | } | ||
| 342 | |||
| 343 | /** | ||
| 344 | * ifx_spi_close - called when our tty closes | ||
| 345 | * @tty: the tty being closed | ||
| 346 | * @filp: the file handle being closed | ||
| 347 | * | ||
| 348 | * Perform the close of the tty. We use the tty_port layer to do all | ||
| 349 | * our hard work. | ||
| 350 | */ | ||
| 351 | static void ifx_spi_close(struct tty_struct *tty, struct file *filp) | ||
| 352 | { | ||
| 353 | struct ifx_spi_device *ifx_dev = tty->driver_data; | ||
| 354 | tty_port_close(&ifx_dev->tty_port, tty, filp); | ||
| 355 | /* FIXME: should we do an ifx_spi_reset here ? */ | ||
| 356 | } | ||
| 357 | |||
| 358 | /** | ||
| 359 | * ifx_decode_spi_header - decode received header | ||
| 360 | * @buffer: the received data | ||
| 361 | * @length: decoded length | ||
| 362 | * @more: decoded more flag | ||
| 363 | * @received_cts: status of cts we received | ||
| 364 | * | ||
| 365 | * Note how received_cts is handled -- if header is all F it is left | ||
| 366 | * the same as it was, if header is all 0 it is set to 0 otherwise it is | ||
| 367 | * taken from the incoming header. | ||
| 368 | * | ||
| 369 | * FIXME: endianness | ||
| 370 | */ | ||
| 371 | static int ifx_spi_decode_spi_header(unsigned char *buffer, int *length, | ||
| 372 | unsigned char *more, unsigned char *received_cts) | ||
| 373 | { | ||
| 374 | u16 h1; | ||
| 375 | u16 h2; | ||
| 376 | u16 *in_buffer = (u16 *)buffer; | ||
| 377 | |||
| 378 | h1 = *in_buffer; | ||
| 379 | h2 = *(in_buffer+1); | ||
| 380 | |||
| 381 | if (h1 == 0 && h2 == 0) { | ||
| 382 | *received_cts = 0; | ||
| 383 | *more = 0; | ||
| 384 | return IFX_SPI_HEADER_0; | ||
| 385 | } else if (h1 == 0xffff && h2 == 0xffff) { | ||
| 386 | *more = 0; | ||
| 387 | /* spi_slave_cts remains as it was */ | ||
| 388 | return IFX_SPI_HEADER_F; | ||
| 389 | } | ||
| 390 | |||
| 391 | *length = h1 & 0xfff; /* upper bits of byte are flags */ | ||
| 392 | *more = (buffer[1] >> IFX_SPI_MORE_BIT) & 1; | ||
| 393 | *received_cts = (buffer[3] >> IFX_SPI_CTS_BIT) & 1; | ||
| 394 | return 0; | ||
| 395 | } | ||
| 396 | |||
| 397 | /** | ||
| 398 | * ifx_setup_spi_header - set header fields | ||
| 399 | * @txbuffer: pointer to start of SPI buffer | ||
| 400 | * @tx_count: bytes | ||
| 401 | * @more: indicate if more to follow | ||
| 402 | * | ||
| 403 | * Format up an SPI header for a transfer | ||
| 404 | * | ||
| 405 | * FIXME: endianness? | ||
| 406 | */ | ||
| 407 | static void ifx_spi_setup_spi_header(unsigned char *txbuffer, int tx_count, | ||
| 408 | unsigned char more) | ||
| 409 | { | ||
| 410 | *(u16 *)(txbuffer) = tx_count; | ||
| 411 | *(u16 *)(txbuffer+2) = IFX_SPI_PAYLOAD_SIZE; | ||
| 412 | txbuffer[1] |= (more << IFX_SPI_MORE_BIT) & IFX_SPI_MORE_MASK; | ||
| 413 | } | ||
| 414 | |||
| 415 | /** | ||
| 416 | * ifx_spi_prepare_tx_buffer - prepare transmit frame | ||
| 417 | * @ifx_dev: our SPI device | ||
| 418 | * | ||
| 419 | * The transmit buffr needs a header and various other bits of | ||
| 420 | * information followed by as much data as we can pull from the FIFO | ||
| 421 | * and transfer. This function formats up a suitable buffer in the | ||
| 422 | * ifx_dev->tx_buffer | ||
| 423 | * | ||
| 424 | * FIXME: performance - should we wake the tty when the queue is half | ||
| 425 | * empty ? | ||
| 426 | */ | ||
| 427 | static int ifx_spi_prepare_tx_buffer(struct ifx_spi_device *ifx_dev) | ||
| 428 | { | ||
| 429 | int temp_count; | ||
| 430 | int queue_length; | ||
| 431 | int tx_count; | ||
| 432 | unsigned char *tx_buffer; | ||
| 433 | |||
| 434 | tx_buffer = ifx_dev->tx_buffer; | ||
| 435 | |||
| 436 | /* make room for required SPI header */ | ||
| 437 | tx_buffer += IFX_SPI_HEADER_OVERHEAD; | ||
| 438 | tx_count = IFX_SPI_HEADER_OVERHEAD; | ||
| 439 | |||
| 440 | /* clear to signal no more data if this turns out to be the | ||
| 441 | * last buffer sent in a sequence */ | ||
| 442 | ifx_dev->spi_more = 0; | ||
| 443 | |||
| 444 | /* if modem cts is set, just send empty buffer */ | ||
| 445 | if (!ifx_dev->spi_slave_cts) { | ||
| 446 | /* see if there's tx data */ | ||
| 447 | queue_length = kfifo_len(&ifx_dev->tx_fifo); | ||
| 448 | if (queue_length != 0) { | ||
| 449 | /* data to mux -- see if there's room for it */ | ||
| 450 | temp_count = min(queue_length, IFX_SPI_PAYLOAD_SIZE); | ||
| 451 | temp_count = kfifo_out_locked(&ifx_dev->tx_fifo, | ||
| 452 | tx_buffer, temp_count, | ||
| 453 | &ifx_dev->fifo_lock); | ||
| 454 | |||
| 455 | /* update buffer pointer and data count in message */ | ||
| 456 | tx_buffer += temp_count; | ||
| 457 | tx_count += temp_count; | ||
| 458 | if (temp_count == queue_length) | ||
| 459 | /* poke port to get more data */ | ||
| 460 | tty_port_tty_wakeup(&ifx_dev->tty_port); | ||
| 461 | else /* more data in port, use next SPI message */ | ||
| 462 | ifx_dev->spi_more = 1; | ||
| 463 | } | ||
| 464 | } | ||
| 465 | /* have data and info for header -- set up SPI header in buffer */ | ||
| 466 | /* spi header needs payload size, not entire buffer size */ | ||
| 467 | ifx_spi_setup_spi_header(ifx_dev->tx_buffer, | ||
| 468 | tx_count-IFX_SPI_HEADER_OVERHEAD, | ||
| 469 | ifx_dev->spi_more); | ||
| 470 | /* swap actual data in the buffer */ | ||
| 471 | ifx_dev->swap_buf((ifx_dev->tx_buffer), tx_count, | ||
| 472 | &ifx_dev->tx_buffer[IFX_SPI_TRANSFER_SIZE]); | ||
| 473 | return tx_count; | ||
| 474 | } | ||
| 475 | |||
| 476 | /** | ||
| 477 | * ifx_spi_write - line discipline write | ||
| 478 | * @tty: our tty device | ||
| 479 | * @buf: pointer to buffer to write (kernel space) | ||
| 480 | * @count: size of buffer | ||
| 481 | * | ||
| 482 | * Write the characters we have been given into the FIFO. If the device | ||
| 483 | * is not active then activate it, when the SRDY line is asserted back | ||
| 484 | * this will commence I/O | ||
| 485 | */ | ||
| 486 | static int ifx_spi_write(struct tty_struct *tty, const unsigned char *buf, | ||
| 487 | int count) | ||
| 488 | { | ||
| 489 | struct ifx_spi_device *ifx_dev = tty->driver_data; | ||
| 490 | unsigned char *tmp_buf = (unsigned char *)buf; | ||
| 491 | unsigned long flags; | ||
| 492 | bool is_fifo_empty; | ||
| 493 | int tx_count; | ||
| 494 | |||
| 495 | spin_lock_irqsave(&ifx_dev->fifo_lock, flags); | ||
| 496 | is_fifo_empty = kfifo_is_empty(&ifx_dev->tx_fifo); | ||
| 497 | tx_count = kfifo_in(&ifx_dev->tx_fifo, tmp_buf, count); | ||
| 498 | spin_unlock_irqrestore(&ifx_dev->fifo_lock, flags); | ||
| 499 | if (is_fifo_empty) | ||
| 500 | mrdy_assert(ifx_dev); | ||
| 501 | |||
| 502 | return tx_count; | ||
| 503 | } | ||
| 504 | |||
| 505 | /** | ||
| 506 | * ifx_spi_chars_in_buffer - line discipline helper | ||
| 507 | * @tty: our tty device | ||
| 508 | * | ||
| 509 | * Report how much data we can accept before we drop bytes. As we use | ||
| 510 | * a simple FIFO this is nice and easy. | ||
| 511 | */ | ||
| 512 | static int ifx_spi_write_room(struct tty_struct *tty) | ||
| 513 | { | ||
| 514 | struct ifx_spi_device *ifx_dev = tty->driver_data; | ||
| 515 | return IFX_SPI_FIFO_SIZE - kfifo_len(&ifx_dev->tx_fifo); | ||
| 516 | } | ||
| 517 | |||
| 518 | /** | ||
| 519 | * ifx_spi_chars_in_buffer - line discipline helper | ||
| 520 | * @tty: our tty device | ||
| 521 | * | ||
| 522 | * Report how many characters we have buffered. In our case this is the | ||
| 523 | * number of bytes sitting in our transmit FIFO. | ||
| 524 | */ | ||
| 525 | static int ifx_spi_chars_in_buffer(struct tty_struct *tty) | ||
| 526 | { | ||
| 527 | struct ifx_spi_device *ifx_dev = tty->driver_data; | ||
| 528 | return kfifo_len(&ifx_dev->tx_fifo); | ||
| 529 | } | ||
| 530 | |||
| 531 | /** | ||
| 532 | * ifx_port_hangup | ||
| 533 | * @tty: our tty | ||
| 534 | * | ||
| 535 | * tty port hang up. Called when tty_hangup processing is invoked either | ||
| 536 | * by loss of carrier, or by software (eg vhangup). Serialized against | ||
| 537 | * activate/shutdown by the tty layer. | ||
| 538 | */ | ||
| 539 | static void ifx_spi_hangup(struct tty_struct *tty) | ||
| 540 | { | ||
| 541 | struct ifx_spi_device *ifx_dev = tty->driver_data; | ||
| 542 | tty_port_hangup(&ifx_dev->tty_port); | ||
| 543 | } | ||
| 544 | |||
| 545 | /** | ||
| 546 | * ifx_port_activate | ||
| 547 | * @port: our tty port | ||
| 548 | * @tty: our tty device | ||
| 549 | * | ||
| 550 | * tty port activate method - called for first open. Serialized | ||
| 551 | * with hangup and shutdown by the tty layer. | ||
| 552 | */ | ||
| 553 | static int ifx_port_activate(struct tty_port *port, struct tty_struct *tty) | ||
| 554 | { | ||
| 555 | struct ifx_spi_device *ifx_dev = | ||
| 556 | container_of(port, struct ifx_spi_device, tty_port); | ||
| 557 | |||
| 558 | /* clear any old data; can't do this in 'close' */ | ||
| 559 | kfifo_reset(&ifx_dev->tx_fifo); | ||
| 560 | |||
| 561 | /* clear any flag which may be set in port shutdown procedure */ | ||
| 562 | clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags); | ||
| 563 | clear_bit(IFX_SPI_STATE_IO_READY, &ifx_dev->flags); | ||
| 564 | |||
| 565 | /* put port data into this tty */ | ||
| 566 | tty->driver_data = ifx_dev; | ||
| 567 | |||
| 568 | /* allows flip string push from int context */ | ||
| 569 | port->low_latency = 1; | ||
| 570 | |||
| 571 | /* set flag to allows data transfer */ | ||
| 572 | set_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags); | ||
| 573 | |||
| 574 | return 0; | ||
| 575 | } | ||
| 576 | |||
| 577 | /** | ||
| 578 | * ifx_port_shutdown | ||
| 579 | * @port: our tty port | ||
| 580 | * | ||
| 581 | * tty port shutdown method - called for last port close. Serialized | ||
| 582 | * with hangup and activate by the tty layer. | ||
| 583 | */ | ||
| 584 | static void ifx_port_shutdown(struct tty_port *port) | ||
| 585 | { | ||
| 586 | struct ifx_spi_device *ifx_dev = | ||
| 587 | container_of(port, struct ifx_spi_device, tty_port); | ||
| 588 | |||
| 589 | clear_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags); | ||
| 590 | mrdy_set_low(ifx_dev); | ||
| 591 | del_timer(&ifx_dev->spi_timer); | ||
| 592 | clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags); | ||
| 593 | tasklet_kill(&ifx_dev->io_work_tasklet); | ||
| 594 | } | ||
| 595 | |||
| 596 | static const struct tty_port_operations ifx_tty_port_ops = { | ||
| 597 | .activate = ifx_port_activate, | ||
| 598 | .shutdown = ifx_port_shutdown, | ||
| 599 | }; | ||
| 600 | |||
| 601 | static const struct tty_operations ifx_spi_serial_ops = { | ||
| 602 | .open = ifx_spi_open, | ||
| 603 | .close = ifx_spi_close, | ||
| 604 | .write = ifx_spi_write, | ||
| 605 | .hangup = ifx_spi_hangup, | ||
| 606 | .write_room = ifx_spi_write_room, | ||
| 607 | .chars_in_buffer = ifx_spi_chars_in_buffer, | ||
| 608 | .tiocmget = ifx_spi_tiocmget, | ||
| 609 | .tiocmset = ifx_spi_tiocmset, | ||
| 610 | }; | ||
| 611 | |||
| 612 | /** | ||
| 613 | * ifx_spi_insert_fip_string - queue received data | ||
| 614 | * @ifx_dev: our SPI device | ||
| 615 | * @chars: buffer we have received | ||
| 616 | * @size: number of chars reeived | ||
| 617 | * | ||
| 618 | * Queue bytes to the tty assuming the tty side is currently open. If | ||
| 619 | * not the discard the data. | ||
| 620 | */ | ||
| 621 | static void ifx_spi_insert_flip_string(struct ifx_spi_device *ifx_dev, | ||
| 622 | unsigned char *chars, size_t size) | ||
| 623 | { | ||
| 624 | tty_insert_flip_string(&ifx_dev->tty_port, chars, size); | ||
| 625 | tty_flip_buffer_push(&ifx_dev->tty_port); | ||
| 626 | } | ||
| 627 | |||
| 628 | /** | ||
| 629 | * ifx_spi_complete - SPI transfer completed | ||
| 630 | * @ctx: our SPI device | ||
| 631 | * | ||
| 632 | * An SPI transfer has completed. Process any received data and kick off | ||
| 633 | * any further transmits we can commence. | ||
| 634 | */ | ||
| 635 | static void ifx_spi_complete(void *ctx) | ||
| 636 | { | ||
| 637 | struct ifx_spi_device *ifx_dev = ctx; | ||
| 638 | int length; | ||
| 639 | int actual_length; | ||
| 640 | unsigned char more = 0; | ||
| 641 | unsigned char cts; | ||
| 642 | int local_write_pending = 0; | ||
| 643 | int queue_length; | ||
| 644 | int srdy; | ||
| 645 | int decode_result; | ||
| 646 | |||
| 647 | mrdy_set_low(ifx_dev); | ||
| 648 | |||
| 649 | if (!ifx_dev->spi_msg.status) { | ||
| 650 | /* check header validity, get comm flags */ | ||
| 651 | ifx_dev->swap_buf(ifx_dev->rx_buffer, IFX_SPI_HEADER_OVERHEAD, | ||
| 652 | &ifx_dev->rx_buffer[IFX_SPI_HEADER_OVERHEAD]); | ||
| 653 | decode_result = ifx_spi_decode_spi_header(ifx_dev->rx_buffer, | ||
| 654 | &length, &more, &cts); | ||
| 655 | if (decode_result == IFX_SPI_HEADER_0) { | ||
| 656 | dev_dbg(&ifx_dev->spi_dev->dev, | ||
| 657 | "ignore input: invalid header 0"); | ||
| 658 | ifx_dev->spi_slave_cts = 0; | ||
| 659 | goto complete_exit; | ||
| 660 | } else if (decode_result == IFX_SPI_HEADER_F) { | ||
| 661 | dev_dbg(&ifx_dev->spi_dev->dev, | ||
| 662 | "ignore input: invalid header F"); | ||
| 663 | goto complete_exit; | ||
| 664 | } | ||
| 665 | |||
| 666 | ifx_dev->spi_slave_cts = cts; | ||
| 667 | |||
| 668 | actual_length = min((unsigned int)length, | ||
| 669 | ifx_dev->spi_msg.actual_length); | ||
| 670 | ifx_dev->swap_buf( | ||
| 671 | (ifx_dev->rx_buffer + IFX_SPI_HEADER_OVERHEAD), | ||
| 672 | actual_length, | ||
| 673 | &ifx_dev->rx_buffer[IFX_SPI_TRANSFER_SIZE]); | ||
| 674 | ifx_spi_insert_flip_string( | ||
| 675 | ifx_dev, | ||
| 676 | ifx_dev->rx_buffer + IFX_SPI_HEADER_OVERHEAD, | ||
| 677 | (size_t)actual_length); | ||
| 678 | } else { | ||
| 679 | more = 0; | ||
| 680 | dev_dbg(&ifx_dev->spi_dev->dev, "SPI transfer error %d", | ||
| 681 | ifx_dev->spi_msg.status); | ||
| 682 | } | ||
| 683 | |||
| 684 | complete_exit: | ||
| 685 | if (ifx_dev->write_pending) { | ||
| 686 | ifx_dev->write_pending = 0; | ||
| 687 | local_write_pending = 1; | ||
| 688 | } | ||
| 689 | |||
| 690 | clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &(ifx_dev->flags)); | ||
| 691 | |||
| 692 | queue_length = kfifo_len(&ifx_dev->tx_fifo); | ||
| 693 | srdy = gpiod_get_value(ifx_dev->gpio.srdy); | ||
| 694 | if (!srdy) | ||
| 695 | ifx_spi_power_state_clear(ifx_dev, IFX_SPI_POWER_SRDY); | ||
| 696 | |||
| 697 | /* schedule output if there is more to do */ | ||
| 698 | if (test_and_clear_bit(IFX_SPI_STATE_IO_READY, &ifx_dev->flags)) | ||
| 699 | tasklet_schedule(&ifx_dev->io_work_tasklet); | ||
| 700 | else { | ||
| 701 | if (more || ifx_dev->spi_more || queue_length > 0 || | ||
| 702 | local_write_pending) { | ||
| 703 | if (ifx_dev->spi_slave_cts) { | ||
| 704 | if (more) | ||
| 705 | mrdy_assert(ifx_dev); | ||
| 706 | } else | ||
| 707 | mrdy_assert(ifx_dev); | ||
| 708 | } else { | ||
| 709 | /* | ||
| 710 | * poke line discipline driver if any for more data | ||
| 711 | * may or may not get more data to write | ||
| 712 | * for now, say not busy | ||
| 713 | */ | ||
| 714 | ifx_spi_power_state_clear(ifx_dev, | ||
| 715 | IFX_SPI_POWER_DATA_PENDING); | ||
| 716 | tty_port_tty_wakeup(&ifx_dev->tty_port); | ||
| 717 | } | ||
| 718 | } | ||
| 719 | } | ||
| 720 | |||
| 721 | /** | ||
| 722 | * ifx_spio_io - I/O tasklet | ||
| 723 | * @t: tasklet construct used to fetch the SPI device | ||
| 724 | * | ||
| 725 | * Queue data for transmission if possible and then kick off the | ||
| 726 | * transfer. | ||
| 727 | */ | ||
| 728 | static void ifx_spi_io(struct tasklet_struct *t) | ||
| 729 | { | ||
| 730 | int retval; | ||
| 731 | struct ifx_spi_device *ifx_dev = from_tasklet(ifx_dev, t, | ||
| 732 | io_work_tasklet); | ||
| 733 | |||
| 734 | if (!test_and_set_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags) && | ||
| 735 | test_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags)) { | ||
| 736 | if (ifx_dev->gpio.unack_srdy_int_nb > 0) | ||
| 737 | ifx_dev->gpio.unack_srdy_int_nb--; | ||
| 738 | |||
| 739 | ifx_spi_prepare_tx_buffer(ifx_dev); | ||
| 740 | |||
| 741 | spi_message_init(&ifx_dev->spi_msg); | ||
| 742 | INIT_LIST_HEAD(&ifx_dev->spi_msg.queue); | ||
| 743 | |||
| 744 | ifx_dev->spi_msg.context = ifx_dev; | ||
| 745 | ifx_dev->spi_msg.complete = ifx_spi_complete; | ||
| 746 | |||
| 747 | /* set up our spi transfer */ | ||
| 748 | /* note len is BYTES, not transfers */ | ||
| 749 | ifx_dev->spi_xfer.len = IFX_SPI_TRANSFER_SIZE; | ||
| 750 | ifx_dev->spi_xfer.cs_change = 0; | ||
| 751 | ifx_dev->spi_xfer.speed_hz = ifx_dev->spi_dev->max_speed_hz; | ||
| 752 | /* ifx_dev->spi_xfer.speed_hz = 390625; */ | ||
| 753 | ifx_dev->spi_xfer.bits_per_word = | ||
| 754 | ifx_dev->spi_dev->bits_per_word; | ||
| 755 | |||
| 756 | ifx_dev->spi_xfer.tx_buf = ifx_dev->tx_buffer; | ||
| 757 | ifx_dev->spi_xfer.rx_buf = ifx_dev->rx_buffer; | ||
| 758 | |||
| 759 | /* | ||
| 760 | * setup dma pointers | ||
| 761 | */ | ||
| 762 | if (ifx_dev->use_dma) { | ||
| 763 | ifx_dev->spi_msg.is_dma_mapped = 1; | ||
| 764 | ifx_dev->tx_dma = ifx_dev->tx_bus; | ||
| 765 | ifx_dev->rx_dma = ifx_dev->rx_bus; | ||
| 766 | ifx_dev->spi_xfer.tx_dma = ifx_dev->tx_dma; | ||
| 767 | ifx_dev->spi_xfer.rx_dma = ifx_dev->rx_dma; | ||
| 768 | } else { | ||
| 769 | ifx_dev->spi_msg.is_dma_mapped = 0; | ||
| 770 | ifx_dev->tx_dma = (dma_addr_t)0; | ||
| 771 | ifx_dev->rx_dma = (dma_addr_t)0; | ||
| 772 | ifx_dev->spi_xfer.tx_dma = (dma_addr_t)0; | ||
| 773 | ifx_dev->spi_xfer.rx_dma = (dma_addr_t)0; | ||
| 774 | } | ||
| 775 | |||
| 776 | spi_message_add_tail(&ifx_dev->spi_xfer, &ifx_dev->spi_msg); | ||
| 777 | |||
| 778 | /* Assert MRDY. This may have already been done by the write | ||
| 779 | * routine. | ||
| 780 | */ | ||
| 781 | mrdy_assert(ifx_dev); | ||
| 782 | |||
| 783 | retval = spi_async(ifx_dev->spi_dev, &ifx_dev->spi_msg); | ||
| 784 | if (retval) { | ||
| 785 | clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, | ||
| 786 | &ifx_dev->flags); | ||
| 787 | tasklet_schedule(&ifx_dev->io_work_tasklet); | ||
| 788 | return; | ||
| 789 | } | ||
| 790 | } else | ||
| 791 | ifx_dev->write_pending = 1; | ||
| 792 | } | ||
| 793 | |||
| 794 | /** | ||
| 795 | * ifx_spi_free_port - free up the tty side | ||
| 796 | * @ifx_dev: IFX device going away | ||
| 797 | * | ||
| 798 | * Unregister and free up a port when the device goes away | ||
| 799 | */ | ||
| 800 | static void ifx_spi_free_port(struct ifx_spi_device *ifx_dev) | ||
| 801 | { | ||
| 802 | if (ifx_dev->tty_dev) | ||
| 803 | tty_unregister_device(tty_drv, ifx_dev->minor); | ||
| 804 | tty_port_destroy(&ifx_dev->tty_port); | ||
| 805 | kfifo_free(&ifx_dev->tx_fifo); | ||
| 806 | } | ||
| 807 | |||
| 808 | /** | ||
| 809 | * ifx_spi_create_port - create a new port | ||
| 810 | * @ifx_dev: our spi device | ||
| 811 | * | ||
| 812 | * Allocate and initialise the tty port that goes with this interface | ||
| 813 | * and add it to the tty layer so that it can be opened. | ||
| 814 | */ | ||
| 815 | static int ifx_spi_create_port(struct ifx_spi_device *ifx_dev) | ||
| 816 | { | ||
| 817 | int ret = 0; | ||
| 818 | struct tty_port *pport = &ifx_dev->tty_port; | ||
| 819 | |||
| 820 | spin_lock_init(&ifx_dev->fifo_lock); | ||
| 821 | lockdep_set_class_and_subclass(&ifx_dev->fifo_lock, | ||
| 822 | &ifx_spi_key, 0); | ||
| 823 | |||
| 824 | if (kfifo_alloc(&ifx_dev->tx_fifo, IFX_SPI_FIFO_SIZE, GFP_KERNEL)) { | ||
| 825 | ret = -ENOMEM; | ||
| 826 | goto error_ret; | ||
| 827 | } | ||
| 828 | |||
| 829 | tty_port_init(pport); | ||
| 830 | pport->ops = &ifx_tty_port_ops; | ||
| 831 | ifx_dev->minor = IFX_SPI_TTY_ID; | ||
| 832 | ifx_dev->tty_dev = tty_port_register_device(pport, tty_drv, | ||
| 833 | ifx_dev->minor, &ifx_dev->spi_dev->dev); | ||
| 834 | if (IS_ERR(ifx_dev->tty_dev)) { | ||
| 835 | dev_dbg(&ifx_dev->spi_dev->dev, | ||
| 836 | "%s: registering tty device failed", __func__); | ||
| 837 | ret = PTR_ERR(ifx_dev->tty_dev); | ||
| 838 | goto error_port; | ||
| 839 | } | ||
| 840 | return 0; | ||
| 841 | |||
| 842 | error_port: | ||
| 843 | tty_port_destroy(pport); | ||
| 844 | error_ret: | ||
| 845 | ifx_spi_free_port(ifx_dev); | ||
| 846 | return ret; | ||
| 847 | } | ||
| 848 | |||
| 849 | /** | ||
| 850 | * ifx_spi_handle_srdy - handle SRDY | ||
| 851 | * @ifx_dev: device asserting SRDY | ||
| 852 | * | ||
| 853 | * Check our device state and see what we need to kick off when SRDY | ||
| 854 | * is asserted. This usually means killing the timer and firing off the | ||
| 855 | * I/O processing. | ||
| 856 | */ | ||
| 857 | static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev) | ||
| 858 | { | ||
| 859 | if (test_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags)) { | ||
| 860 | del_timer(&ifx_dev->spi_timer); | ||
| 861 | clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags); | ||
| 862 | } | ||
| 863 | |||
| 864 | ifx_spi_power_state_set(ifx_dev, IFX_SPI_POWER_SRDY); | ||
| 865 | |||
| 866 | if (!test_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags)) | ||
| 867 | tasklet_schedule(&ifx_dev->io_work_tasklet); | ||
| 868 | else | ||
| 869 | set_bit(IFX_SPI_STATE_IO_READY, &ifx_dev->flags); | ||
| 870 | } | ||
| 871 | |||
| 872 | /** | ||
| 873 | * ifx_spi_srdy_interrupt - SRDY asserted | ||
| 874 | * @irq: our IRQ number | ||
| 875 | * @dev: our ifx device | ||
| 876 | * | ||
| 877 | * The modem asserted SRDY. Handle the srdy event | ||
| 878 | */ | ||
| 879 | static irqreturn_t ifx_spi_srdy_interrupt(int irq, void *dev) | ||
| 880 | { | ||
| 881 | struct ifx_spi_device *ifx_dev = dev; | ||
| 882 | ifx_dev->gpio.unack_srdy_int_nb++; | ||
| 883 | ifx_spi_handle_srdy(ifx_dev); | ||
| 884 | return IRQ_HANDLED; | ||
| 885 | } | ||
| 886 | |||
| 887 | /** | ||
| 888 | * ifx_spi_reset_interrupt - Modem has changed reset state | ||
| 889 | * @irq: interrupt number | ||
| 890 | * @dev: our device pointer | ||
| 891 | * | ||
| 892 | * The modem has either entered or left reset state. Check the GPIO | ||
| 893 | * line to see which. | ||
| 894 | * | ||
| 895 | * FIXME: review locking on MR_INPROGRESS versus | ||
| 896 | * parallel unsolicited reset/solicited reset | ||
| 897 | */ | ||
| 898 | static irqreturn_t ifx_spi_reset_interrupt(int irq, void *dev) | ||
| 899 | { | ||
| 900 | struct ifx_spi_device *ifx_dev = dev; | ||
| 901 | int val = gpiod_get_value(ifx_dev->gpio.reset_out); | ||
| 902 | int solreset = test_bit(MR_START, &ifx_dev->mdm_reset_state); | ||
| 903 | |||
| 904 | if (val == 0) { | ||
| 905 | /* entered reset */ | ||
| 906 | set_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state); | ||
| 907 | if (!solreset) { | ||
| 908 | /* unsolicited reset */ | ||
| 909 | tty_port_tty_hangup(&ifx_dev->tty_port, false); | ||
| 910 | } | ||
| 911 | } else { | ||
| 912 | /* exited reset */ | ||
| 913 | clear_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state); | ||
| 914 | if (solreset) { | ||
| 915 | set_bit(MR_COMPLETE, &ifx_dev->mdm_reset_state); | ||
| 916 | wake_up(&ifx_dev->mdm_reset_wait); | ||
| 917 | } | ||
| 918 | } | ||
| 919 | return IRQ_HANDLED; | ||
| 920 | } | ||
| 921 | |||
| 922 | /** | ||
| 923 | * ifx_spi_free_device - free device | ||
| 924 | * @ifx_dev: device to free | ||
| 925 | * | ||
| 926 | * Free the IFX device | ||
| 927 | */ | ||
| 928 | static void ifx_spi_free_device(struct ifx_spi_device *ifx_dev) | ||
| 929 | { | ||
| 930 | ifx_spi_free_port(ifx_dev); | ||
| 931 | dma_free_coherent(&ifx_dev->spi_dev->dev, | ||
| 932 | IFX_SPI_TRANSFER_SIZE, | ||
| 933 | ifx_dev->tx_buffer, | ||
| 934 | ifx_dev->tx_bus); | ||
| 935 | dma_free_coherent(&ifx_dev->spi_dev->dev, | ||
| 936 | IFX_SPI_TRANSFER_SIZE, | ||
| 937 | ifx_dev->rx_buffer, | ||
| 938 | ifx_dev->rx_bus); | ||
| 939 | } | ||
| 940 | |||
| 941 | /** | ||
| 942 | * ifx_spi_reset - reset modem | ||
| 943 | * @ifx_dev: modem to reset | ||
| 944 | * | ||
| 945 | * Perform a reset on the modem | ||
| 946 | */ | ||
| 947 | static int ifx_spi_reset(struct ifx_spi_device *ifx_dev) | ||
| 948 | { | ||
| 949 | int ret; | ||
| 950 | /* | ||
| 951 | * set up modem power, reset | ||
| 952 | * | ||
| 953 | * delays are required on some platforms for the modem | ||
| 954 | * to reset properly | ||
| 955 | */ | ||
| 956 | set_bit(MR_START, &ifx_dev->mdm_reset_state); | ||
| 957 | gpiod_set_value(ifx_dev->gpio.po, 0); | ||
| 958 | gpiod_set_value(ifx_dev->gpio.reset, 0); | ||
| 959 | msleep(25); | ||
| 960 | gpiod_set_value(ifx_dev->gpio.reset, 1); | ||
| 961 | msleep(1); | ||
| 962 | gpiod_set_value(ifx_dev->gpio.po, 1); | ||
| 963 | msleep(1); | ||
| 964 | gpiod_set_value(ifx_dev->gpio.po, 0); | ||
| 965 | ret = wait_event_timeout(ifx_dev->mdm_reset_wait, | ||
| 966 | test_bit(MR_COMPLETE, | ||
| 967 | &ifx_dev->mdm_reset_state), | ||
| 968 | IFX_RESET_TIMEOUT); | ||
| 969 | if (!ret) | ||
| 970 | dev_warn(&ifx_dev->spi_dev->dev, "Modem reset timeout: (state:%lx)", | ||
| 971 | ifx_dev->mdm_reset_state); | ||
| 972 | |||
| 973 | ifx_dev->mdm_reset_state = 0; | ||
| 974 | return ret; | ||
| 975 | } | ||
| 976 | |||
| 977 | /** | ||
| 978 | * ifx_spi_spi_probe - probe callback | ||
| 979 | * @spi: our possible matching SPI device | ||
| 980 | * | ||
| 981 | * Probe for a 6x60 modem on SPI bus. Perform any needed device and | ||
| 982 | * GPIO setup. | ||
| 983 | * | ||
| 984 | * FIXME: | ||
| 985 | * - Support for multiple devices | ||
| 986 | * - Split out MID specific GPIO handling eventually | ||
| 987 | */ | ||
| 988 | |||
| 989 | static int ifx_spi_spi_probe(struct spi_device *spi) | ||
| 990 | { | ||
| 991 | int ret; | ||
| 992 | int srdy; | ||
| 993 | struct ifx_modem_platform_data *pl_data; | ||
| 994 | struct ifx_spi_device *ifx_dev; | ||
| 995 | struct device *dev = &spi->dev; | ||
| 996 | |||
| 997 | if (saved_ifx_dev) { | ||
| 998 | dev_dbg(dev, "ignoring subsequent detection"); | ||
| 999 | return -ENODEV; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | pl_data = dev_get_platdata(dev); | ||
| 1003 | if (!pl_data) { | ||
| 1004 | dev_err(dev, "missing platform data!"); | ||
| 1005 | return -ENODEV; | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | /* initialize structure to hold our device variables */ | ||
| 1009 | ifx_dev = kzalloc(sizeof(struct ifx_spi_device), GFP_KERNEL); | ||
| 1010 | if (!ifx_dev) { | ||
| 1011 | dev_err(dev, "spi device allocation failed"); | ||
| 1012 | return -ENOMEM; | ||
| 1013 | } | ||
| 1014 | saved_ifx_dev = ifx_dev; | ||
| 1015 | ifx_dev->spi_dev = spi; | ||
| 1016 | clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags); | ||
| 1017 | spin_lock_init(&ifx_dev->write_lock); | ||
| 1018 | spin_lock_init(&ifx_dev->power_lock); | ||
| 1019 | ifx_dev->power_status = 0; | ||
| 1020 | timer_setup(&ifx_dev->spi_timer, ifx_spi_timeout, 0); | ||
| 1021 | ifx_dev->modem = pl_data->modem_type; | ||
| 1022 | ifx_dev->use_dma = pl_data->use_dma; | ||
| 1023 | ifx_dev->max_hz = pl_data->max_hz; | ||
| 1024 | /* initialize spi mode, etc */ | ||
| 1025 | spi->max_speed_hz = ifx_dev->max_hz; | ||
| 1026 | spi->mode = IFX_SPI_MODE | (SPI_LOOP & spi->mode); | ||
| 1027 | spi->bits_per_word = spi_bpw; | ||
| 1028 | ret = spi_setup(spi); | ||
| 1029 | if (ret) { | ||
| 1030 | dev_err(dev, "SPI setup wasn't successful %d", ret); | ||
| 1031 | kfree(ifx_dev); | ||
| 1032 | return -ENODEV; | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | /* init swap_buf function according to word width configuration */ | ||
| 1036 | if (spi->bits_per_word == 32) | ||
| 1037 | ifx_dev->swap_buf = swap_buf_32; | ||
| 1038 | else if (spi->bits_per_word == 16) | ||
| 1039 | ifx_dev->swap_buf = swap_buf_16; | ||
| 1040 | else | ||
| 1041 | ifx_dev->swap_buf = swap_buf_8; | ||
| 1042 | |||
| 1043 | /* ensure SPI protocol flags are initialized to enable transfer */ | ||
| 1044 | ifx_dev->spi_more = 0; | ||
| 1045 | ifx_dev->spi_slave_cts = 0; | ||
| 1046 | |||
| 1047 | /*initialize transfer and dma buffers */ | ||
| 1048 | ifx_dev->tx_buffer = dma_alloc_coherent(ifx_dev->spi_dev->dev.parent, | ||
| 1049 | IFX_SPI_TRANSFER_SIZE, | ||
| 1050 | &ifx_dev->tx_bus, | ||
| 1051 | GFP_KERNEL); | ||
| 1052 | if (!ifx_dev->tx_buffer) { | ||
| 1053 | dev_err(dev, "DMA-TX buffer allocation failed"); | ||
| 1054 | ret = -ENOMEM; | ||
| 1055 | goto error_ret; | ||
| 1056 | } | ||
| 1057 | ifx_dev->rx_buffer = dma_alloc_coherent(ifx_dev->spi_dev->dev.parent, | ||
| 1058 | IFX_SPI_TRANSFER_SIZE, | ||
| 1059 | &ifx_dev->rx_bus, | ||
| 1060 | GFP_KERNEL); | ||
| 1061 | if (!ifx_dev->rx_buffer) { | ||
| 1062 | dev_err(dev, "DMA-RX buffer allocation failed"); | ||
| 1063 | ret = -ENOMEM; | ||
| 1064 | goto error_ret; | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | /* initialize waitq for modem reset */ | ||
| 1068 | init_waitqueue_head(&ifx_dev->mdm_reset_wait); | ||
| 1069 | |||
| 1070 | spi_set_drvdata(spi, ifx_dev); | ||
| 1071 | tasklet_setup(&ifx_dev->io_work_tasklet, ifx_spi_io); | ||
| 1072 | |||
| 1073 | set_bit(IFX_SPI_STATE_PRESENT, &ifx_dev->flags); | ||
| 1074 | |||
| 1075 | /* create our tty port */ | ||
| 1076 | ret = ifx_spi_create_port(ifx_dev); | ||
| 1077 | if (ret != 0) { | ||
| 1078 | dev_err(dev, "create default tty port failed"); | ||
| 1079 | goto error_ret; | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | ifx_dev->gpio.reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); | ||
| 1083 | if (IS_ERR(ifx_dev->gpio.reset)) { | ||
| 1084 | dev_err(dev, "could not obtain reset GPIO\n"); | ||
| 1085 | ret = PTR_ERR(ifx_dev->gpio.reset); | ||
| 1086 | goto error_ret; | ||
| 1087 | } | ||
| 1088 | gpiod_set_consumer_name(ifx_dev->gpio.reset, "ifxModem reset"); | ||
| 1089 | ifx_dev->gpio.po = devm_gpiod_get(dev, "power", GPIOD_OUT_LOW); | ||
| 1090 | if (IS_ERR(ifx_dev->gpio.po)) { | ||
| 1091 | dev_err(dev, "could not obtain power GPIO\n"); | ||
| 1092 | ret = PTR_ERR(ifx_dev->gpio.po); | ||
| 1093 | goto error_ret; | ||
| 1094 | } | ||
| 1095 | gpiod_set_consumer_name(ifx_dev->gpio.po, "ifxModem power"); | ||
| 1096 | ifx_dev->gpio.mrdy = devm_gpiod_get(dev, "mrdy", GPIOD_OUT_LOW); | ||
| 1097 | if (IS_ERR(ifx_dev->gpio.mrdy)) { | ||
| 1098 | dev_err(dev, "could not obtain mrdy GPIO\n"); | ||
| 1099 | ret = PTR_ERR(ifx_dev->gpio.mrdy); | ||
| 1100 | goto error_ret; | ||
| 1101 | } | ||
| 1102 | gpiod_set_consumer_name(ifx_dev->gpio.mrdy, "ifxModem mrdy"); | ||
| 1103 | ifx_dev->gpio.srdy = devm_gpiod_get(dev, "srdy", GPIOD_IN); | ||
| 1104 | if (IS_ERR(ifx_dev->gpio.srdy)) { | ||
| 1105 | dev_err(dev, "could not obtain srdy GPIO\n"); | ||
| 1106 | ret = PTR_ERR(ifx_dev->gpio.srdy); | ||
| 1107 | goto error_ret; | ||
| 1108 | } | ||
| 1109 | gpiod_set_consumer_name(ifx_dev->gpio.srdy, "ifxModem srdy"); | ||
| 1110 | ifx_dev->gpio.reset_out = devm_gpiod_get(dev, "rst_out", GPIOD_IN); | ||
| 1111 | if (IS_ERR(ifx_dev->gpio.reset_out)) { | ||
| 1112 | dev_err(dev, "could not obtain rst_out GPIO\n"); | ||
| 1113 | ret = PTR_ERR(ifx_dev->gpio.reset_out); | ||
| 1114 | goto error_ret; | ||
| 1115 | } | ||
| 1116 | gpiod_set_consumer_name(ifx_dev->gpio.reset_out, "ifxModem reset out"); | ||
| 1117 | ifx_dev->gpio.pmu_reset = devm_gpiod_get(dev, "pmu_reset", GPIOD_ASIS); | ||
| 1118 | if (IS_ERR(ifx_dev->gpio.pmu_reset)) { | ||
| 1119 | dev_err(dev, "could not obtain pmu_reset GPIO\n"); | ||
| 1120 | ret = PTR_ERR(ifx_dev->gpio.pmu_reset); | ||
| 1121 | goto error_ret; | ||
| 1122 | } | ||
| 1123 | gpiod_set_consumer_name(ifx_dev->gpio.pmu_reset, "ifxModem PMU reset"); | ||
| 1124 | |||
| 1125 | ret = request_irq(gpiod_to_irq(ifx_dev->gpio.reset_out), | ||
| 1126 | ifx_spi_reset_interrupt, | ||
| 1127 | IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, DRVNAME, | ||
| 1128 | ifx_dev); | ||
| 1129 | if (ret) { | ||
| 1130 | dev_err(dev, "Unable to get irq %x\n", | ||
| 1131 | gpiod_to_irq(ifx_dev->gpio.reset_out)); | ||
| 1132 | goto error_ret; | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | ret = ifx_spi_reset(ifx_dev); | ||
| 1136 | |||
| 1137 | ret = request_irq(gpiod_to_irq(ifx_dev->gpio.srdy), | ||
| 1138 | ifx_spi_srdy_interrupt, IRQF_TRIGGER_RISING, DRVNAME, | ||
| 1139 | ifx_dev); | ||
| 1140 | if (ret) { | ||
| 1141 | dev_err(dev, "Unable to get irq %x", | ||
| 1142 | gpiod_to_irq(ifx_dev->gpio.srdy)); | ||
| 1143 | goto error_ret2; | ||
| 1144 | } | ||
| 1145 | |||
| 1146 | /* set pm runtime power state and register with power system */ | ||
| 1147 | pm_runtime_set_active(dev); | ||
| 1148 | pm_runtime_enable(dev); | ||
| 1149 | |||
| 1150 | /* handle case that modem is already signaling SRDY */ | ||
| 1151 | /* no outgoing tty open at this point, this just satisfies the | ||
| 1152 | * modem's read and should reset communication properly | ||
| 1153 | */ | ||
| 1154 | srdy = gpiod_get_value(ifx_dev->gpio.srdy); | ||
| 1155 | |||
| 1156 | if (srdy) { | ||
| 1157 | mrdy_assert(ifx_dev); | ||
| 1158 | ifx_spi_handle_srdy(ifx_dev); | ||
| 1159 | } else | ||
| 1160 | mrdy_set_low(ifx_dev); | ||
| 1161 | return 0; | ||
| 1162 | |||
| 1163 | error_ret2: | ||
| 1164 | free_irq(gpiod_to_irq(ifx_dev->gpio.reset_out), ifx_dev); | ||
| 1165 | error_ret: | ||
| 1166 | ifx_spi_free_device(ifx_dev); | ||
| 1167 | saved_ifx_dev = NULL; | ||
| 1168 | return ret; | ||
| 1169 | } | ||
| 1170 | |||
| 1171 | /** | ||
| 1172 | * ifx_spi_spi_remove - SPI device was removed | ||
| 1173 | * @spi: SPI device | ||
| 1174 | * | ||
| 1175 | * FIXME: We should be shutting the device down here not in | ||
| 1176 | * the module unload path. | ||
| 1177 | */ | ||
| 1178 | |||
| 1179 | static int ifx_spi_spi_remove(struct spi_device *spi) | ||
| 1180 | { | ||
| 1181 | struct ifx_spi_device *ifx_dev = spi_get_drvdata(spi); | ||
| 1182 | /* stop activity */ | ||
| 1183 | tasklet_kill(&ifx_dev->io_work_tasklet); | ||
| 1184 | |||
| 1185 | pm_runtime_disable(&spi->dev); | ||
| 1186 | |||
| 1187 | /* free irq */ | ||
| 1188 | free_irq(gpiod_to_irq(ifx_dev->gpio.reset_out), ifx_dev); | ||
| 1189 | free_irq(gpiod_to_irq(ifx_dev->gpio.srdy), ifx_dev); | ||
| 1190 | |||
| 1191 | /* free allocations */ | ||
| 1192 | ifx_spi_free_device(ifx_dev); | ||
| 1193 | |||
| 1194 | saved_ifx_dev = NULL; | ||
| 1195 | return 0; | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | /** | ||
| 1199 | * ifx_spi_spi_shutdown - called on SPI shutdown | ||
| 1200 | * @spi: SPI device | ||
| 1201 | * | ||
| 1202 | * No action needs to be taken here | ||
| 1203 | */ | ||
| 1204 | |||
| 1205 | static void ifx_spi_spi_shutdown(struct spi_device *spi) | ||
| 1206 | { | ||
| 1207 | struct ifx_spi_device *ifx_dev = spi_get_drvdata(spi); | ||
| 1208 | |||
| 1209 | ifx_modem_power_off(ifx_dev); | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | /* | ||
| 1213 | * various suspends and resumes have nothing to do | ||
| 1214 | * no hardware to save state for | ||
| 1215 | */ | ||
| 1216 | |||
| 1217 | /** | ||
| 1218 | * ifx_spi_pm_suspend - suspend modem on system suspend | ||
| 1219 | * @dev: device being suspended | ||
| 1220 | * | ||
| 1221 | * Suspend the modem. No action needed on Intel MID platforms, may | ||
| 1222 | * need extending for other systems. | ||
| 1223 | */ | ||
| 1224 | static int ifx_spi_pm_suspend(struct device *dev) | ||
| 1225 | { | ||
| 1226 | return 0; | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | /** | ||
| 1230 | * ifx_spi_pm_resume - resume modem on system resume | ||
| 1231 | * @dev: device being suspended | ||
| 1232 | * | ||
| 1233 | * Allow the modem to resume. No action needed. | ||
| 1234 | * | ||
| 1235 | * FIXME: do we need to reset anything here ? | ||
| 1236 | */ | ||
| 1237 | static int ifx_spi_pm_resume(struct device *dev) | ||
| 1238 | { | ||
| 1239 | return 0; | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | /** | ||
| 1243 | * ifx_spi_pm_runtime_resume - suspend modem | ||
| 1244 | * @dev: device being suspended | ||
| 1245 | * | ||
| 1246 | * Allow the modem to resume. No action needed. | ||
| 1247 | */ | ||
| 1248 | static int ifx_spi_pm_runtime_resume(struct device *dev) | ||
| 1249 | { | ||
| 1250 | return 0; | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | /** | ||
| 1254 | * ifx_spi_pm_runtime_suspend - suspend modem | ||
| 1255 | * @dev: device being suspended | ||
| 1256 | * | ||
| 1257 | * Allow the modem to suspend and thus suspend to continue up the | ||
| 1258 | * device tree. | ||
| 1259 | */ | ||
| 1260 | static int ifx_spi_pm_runtime_suspend(struct device *dev) | ||
| 1261 | { | ||
| 1262 | return 0; | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | /** | ||
| 1266 | * ifx_spi_pm_runtime_idle - check if modem idle | ||
| 1267 | * @dev: our device | ||
| 1268 | * | ||
| 1269 | * Check conditions and queue runtime suspend if idle. | ||
| 1270 | */ | ||
| 1271 | static int ifx_spi_pm_runtime_idle(struct device *dev) | ||
| 1272 | { | ||
| 1273 | struct spi_device *spi = to_spi_device(dev); | ||
| 1274 | struct ifx_spi_device *ifx_dev = spi_get_drvdata(spi); | ||
| 1275 | |||
| 1276 | if (!ifx_dev->power_status) | ||
| 1277 | pm_runtime_suspend(dev); | ||
| 1278 | |||
| 1279 | return 0; | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | static const struct dev_pm_ops ifx_spi_pm = { | ||
| 1283 | .resume = ifx_spi_pm_resume, | ||
| 1284 | .suspend = ifx_spi_pm_suspend, | ||
| 1285 | .runtime_resume = ifx_spi_pm_runtime_resume, | ||
| 1286 | .runtime_suspend = ifx_spi_pm_runtime_suspend, | ||
| 1287 | .runtime_idle = ifx_spi_pm_runtime_idle | ||
| 1288 | }; | ||
| 1289 | |||
| 1290 | static const struct spi_device_id ifx_id_table[] = { | ||
| 1291 | {"ifx6160", 0}, | ||
| 1292 | {"ifx6260", 0}, | ||
| 1293 | { } | ||
| 1294 | }; | ||
| 1295 | MODULE_DEVICE_TABLE(spi, ifx_id_table); | ||
| 1296 | |||
| 1297 | /* spi operations */ | ||
| 1298 | static struct spi_driver ifx_spi_driver = { | ||
| 1299 | .driver = { | ||
| 1300 | .name = DRVNAME, | ||
| 1301 | .pm = &ifx_spi_pm, | ||
| 1302 | }, | ||
| 1303 | .probe = ifx_spi_spi_probe, | ||
| 1304 | .shutdown = ifx_spi_spi_shutdown, | ||
| 1305 | .remove = ifx_spi_spi_remove, | ||
| 1306 | .id_table = ifx_id_table | ||
| 1307 | }; | ||
| 1308 | |||
| 1309 | /** | ||
| 1310 | * ifx_spi_exit - module exit | ||
| 1311 | * | ||
| 1312 | * Unload the module. | ||
| 1313 | */ | ||
| 1314 | |||
| 1315 | static void __exit ifx_spi_exit(void) | ||
| 1316 | { | ||
| 1317 | /* unregister */ | ||
| 1318 | spi_unregister_driver(&ifx_spi_driver); | ||
| 1319 | tty_unregister_driver(tty_drv); | ||
| 1320 | put_tty_driver(tty_drv); | ||
| 1321 | unregister_reboot_notifier(&ifx_modem_reboot_notifier_block); | ||
| 1322 | } | ||
| 1323 | |||
| 1324 | /** | ||
| 1325 | * ifx_spi_init - module entry point | ||
| 1326 | * | ||
| 1327 | * Initialise the SPI and tty interfaces for the IFX SPI driver | ||
| 1328 | * We need to initialize upper-edge spi driver after the tty | ||
| 1329 | * driver because otherwise the spi probe will race | ||
| 1330 | */ | ||
| 1331 | |||
| 1332 | static int __init ifx_spi_init(void) | ||
| 1333 | { | ||
| 1334 | int result; | ||
| 1335 | |||
| 1336 | tty_drv = alloc_tty_driver(1); | ||
| 1337 | if (!tty_drv) { | ||
| 1338 | pr_err("%s: alloc_tty_driver failed", DRVNAME); | ||
| 1339 | return -ENOMEM; | ||
| 1340 | } | ||
| 1341 | |||
| 1342 | tty_drv->driver_name = DRVNAME; | ||
| 1343 | tty_drv->name = TTYNAME; | ||
| 1344 | tty_drv->minor_start = IFX_SPI_TTY_ID; | ||
| 1345 | tty_drv->type = TTY_DRIVER_TYPE_SERIAL; | ||
| 1346 | tty_drv->subtype = SERIAL_TYPE_NORMAL; | ||
| 1347 | tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | ||
| 1348 | tty_drv->init_termios = tty_std_termios; | ||
| 1349 | |||
| 1350 | tty_set_operations(tty_drv, &ifx_spi_serial_ops); | ||
| 1351 | |||
| 1352 | result = tty_register_driver(tty_drv); | ||
| 1353 | if (result) { | ||
| 1354 | pr_err("%s: tty_register_driver failed(%d)", | ||
| 1355 | DRVNAME, result); | ||
| 1356 | goto err_free_tty; | ||
| 1357 | } | ||
| 1358 | |||
| 1359 | result = spi_register_driver(&ifx_spi_driver); | ||
| 1360 | if (result) { | ||
| 1361 | pr_err("%s: spi_register_driver failed(%d)", | ||
| 1362 | DRVNAME, result); | ||
| 1363 | goto err_unreg_tty; | ||
| 1364 | } | ||
| 1365 | |||
| 1366 | result = register_reboot_notifier(&ifx_modem_reboot_notifier_block); | ||
| 1367 | if (result) { | ||
| 1368 | pr_err("%s: register ifx modem reboot notifier failed(%d)", | ||
| 1369 | DRVNAME, result); | ||
| 1370 | goto err_unreg_spi; | ||
| 1371 | } | ||
| 1372 | |||
| 1373 | return 0; | ||
| 1374 | err_unreg_spi: | ||
| 1375 | spi_unregister_driver(&ifx_spi_driver); | ||
| 1376 | err_unreg_tty: | ||
| 1377 | tty_unregister_driver(tty_drv); | ||
| 1378 | err_free_tty: | ||
| 1379 | put_tty_driver(tty_drv); | ||
| 1380 | |||
| 1381 | return result; | ||
| 1382 | } | ||
| 1383 | |||
| 1384 | module_init(ifx_spi_init); | ||
| 1385 | module_exit(ifx_spi_exit); | ||
| 1386 | |||
| 1387 | MODULE_AUTHOR("Intel"); | ||
| 1388 | MODULE_DESCRIPTION("IFX6x60 spi driver"); | ||
| 1389 | MODULE_LICENSE("GPL"); | ||
| 1390 | MODULE_INFO(Version, "0.1-IFX6x60"); | ||
| @@ -1,118 +0,0 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /**************************************************************************** | ||
| 3 | * | ||
| 4 | * Driver for the IFX spi modem. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2009, 2010 Intel Corp | ||
| 7 | * Jim Stanley <jim.stanley@intel.com> | ||
| 8 | * | ||
| 9 | *****************************************************************************/ | ||
| 10 | #ifndef _IFX6X60_H | ||
| 11 | #define _IFX6X60_H | ||
| 12 | |||
| 13 | struct gpio_desc; | ||
| 14 | |||
| 15 | #define DRVNAME "ifx6x60" | ||
| 16 | #define TTYNAME "ttyIFX" | ||
| 17 | |||
| 18 | #define IFX_SPI_MAX_MINORS 1 | ||
| 19 | #define IFX_SPI_TRANSFER_SIZE 2048 | ||
| 20 | #define IFX_SPI_FIFO_SIZE 4096 | ||
| 21 | |||
| 22 | #define IFX_SPI_HEADER_OVERHEAD 4 | ||
| 23 | #define IFX_RESET_TIMEOUT msecs_to_jiffies(50) | ||
| 24 | |||
| 25 | /* device flags bitfield definitions */ | ||
| 26 | #define IFX_SPI_STATE_PRESENT 0 | ||
| 27 | #define IFX_SPI_STATE_IO_IN_PROGRESS 1 | ||
| 28 | #define IFX_SPI_STATE_IO_READY 2 | ||
| 29 | #define IFX_SPI_STATE_TIMER_PENDING 3 | ||
| 30 | #define IFX_SPI_STATE_IO_AVAILABLE 4 | ||
| 31 | |||
| 32 | /* flow control bitfields */ | ||
| 33 | #define IFX_SPI_DCD 0 | ||
| 34 | #define IFX_SPI_CTS 1 | ||
| 35 | #define IFX_SPI_DSR 2 | ||
| 36 | #define IFX_SPI_RI 3 | ||
| 37 | #define IFX_SPI_DTR 4 | ||
| 38 | #define IFX_SPI_RTS 5 | ||
| 39 | #define IFX_SPI_TX_FC 6 | ||
| 40 | #define IFX_SPI_RX_FC 7 | ||
| 41 | #define IFX_SPI_UPDATE 8 | ||
| 42 | |||
| 43 | #define IFX_SPI_PAYLOAD_SIZE (IFX_SPI_TRANSFER_SIZE - \ | ||
| 44 | IFX_SPI_HEADER_OVERHEAD) | ||
| 45 | |||
| 46 | #define IFX_SPI_IRQ_TYPE DETECT_EDGE_RISING | ||
| 47 | #define IFX_SPI_GPIO_TARGET 0 | ||
| 48 | #define IFX_SPI_GPIO0 0x105 | ||
| 49 | |||
| 50 | #define IFX_SPI_STATUS_TIMEOUT (2000*HZ) | ||
| 51 | |||
| 52 | /* values for bits in power status byte */ | ||
| 53 | #define IFX_SPI_POWER_DATA_PENDING 1 | ||
| 54 | #define IFX_SPI_POWER_SRDY 2 | ||
| 55 | |||
| 56 | struct ifx_spi_device { | ||
| 57 | /* Our SPI device */ | ||
| 58 | struct spi_device *spi_dev; | ||
| 59 | |||
| 60 | /* Port specific data */ | ||
| 61 | struct kfifo tx_fifo; | ||
| 62 | spinlock_t fifo_lock; | ||
| 63 | unsigned long signal_state; | ||
| 64 | |||
| 65 | /* TTY Layer logic */ | ||
| 66 | struct tty_port tty_port; | ||
| 67 | struct device *tty_dev; | ||
| 68 | int minor; | ||
| 69 | |||
| 70 | /* Low level I/O work */ | ||
| 71 | struct tasklet_struct io_work_tasklet; | ||
| 72 | unsigned long flags; | ||
| 73 | dma_addr_t rx_dma; | ||
| 74 | dma_addr_t tx_dma; | ||
| 75 | |||
| 76 | int modem; /* Modem type */ | ||
| 77 | int use_dma; /* provide dma-able addrs in SPI msg */ | ||
| 78 | long max_hz; /* max SPI frequency */ | ||
| 79 | |||
| 80 | spinlock_t write_lock; | ||
| 81 | int write_pending; | ||
| 82 | spinlock_t power_lock; | ||
| 83 | unsigned char power_status; | ||
| 84 | |||
| 85 | unsigned char *rx_buffer; | ||
| 86 | unsigned char *tx_buffer; | ||
| 87 | dma_addr_t rx_bus; | ||
| 88 | dma_addr_t tx_bus; | ||
| 89 | unsigned char spi_more; | ||
| 90 | unsigned char spi_slave_cts; | ||
| 91 | |||
| 92 | struct timer_list spi_timer; | ||
| 93 | |||
| 94 | struct spi_message spi_msg; | ||
| 95 | struct spi_transfer spi_xfer; | ||
| 96 | |||
| 97 | struct { | ||
| 98 | /* gpio lines */ | ||
| 99 | struct gpio_desc *srdy; /* slave-ready gpio */ | ||
| 100 | struct gpio_desc *mrdy; /* master-ready gpio */ | ||
| 101 | struct gpio_desc *reset; /* modem-reset gpio */ | ||
| 102 | struct gpio_desc *po; /* modem-on gpio */ | ||
| 103 | struct gpio_desc *reset_out; /* modem-in-reset gpio */ | ||
| 104 | struct gpio_desc *pmu_reset; /* PMU reset gpio */ | ||
| 105 | /* state/stats */ | ||
| 106 | int unack_srdy_int_nb; | ||
| 107 | } gpio; | ||
| 108 | |||
| 109 | /* modem reset */ | ||
| 110 | unsigned long mdm_reset_state; | ||
| 111 | #define MR_START 0 | ||
| 112 | #define MR_INPROGRESS 1 | ||
| 113 | #define MR_COMPLETE 2 | ||
| 114 | wait_queue_head_t mdm_reset_wait; | ||
| 115 | void (*swap_buf)(unsigned char *buf, int len, void *end); | ||
| 116 | }; | ||
| 117 | |||
| 118 | #endif /* _IFX6X60_H */ | ||
| @@ -2248,7 +2248,7 @@ static int imx_uart_probe(struct platform_device *pdev) · 2247 unmodified lines | |||
| 2248 | sport->port.dev = &pdev->dev; | 2248 | sport->port.dev = &pdev->dev; |
| 2249 | sport->port.mapbase = res->start; | 2249 | sport->port.mapbase = res->start; |
| 2250 | sport->port.membase = base; | 2250 | sport->port.membase = base; |
| 2251 | sport->port.type = PORT_IMX, | 2251 | sport->port.type = PORT_IMX; |
| 2252 | sport->port.iotype = UPIO_MEM; | 2252 | sport->port.iotype = UPIO_MEM; |
| 2253 | sport->port.irq = rxirq; | 2253 | sport->port.irq = rxirq; |
| 2254 | sport->port.fifosize = 32; | 2254 | sport->port.fifosize = 32; |
| @@ -876,7 +876,7 @@ static int lqasc_probe(struct platform_device *pdev) · 875 unmodified lines | |||
| 876 | port->flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP; | 876 | port->flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP; |
| 877 | port->ops = &lqasc_pops; | 877 | port->ops = &lqasc_pops; |
| 878 | port->fifosize = 16; | 878 | port->fifosize = 16; |
| 879 | port->type = PORT_LTQ_ASC, | 879 | port->type = PORT_LTQ_ASC; |
| 880 | port->line = line; | 880 | port->line = line; |
| 881 | port->dev = &pdev->dev; | 881 | port->dev = &pdev->dev; |
| 882 | /* unused, just to be backward-compatible */ | 882 | /* unused, just to be backward-compatible */ |
| @@ -521,9 +521,6 @@ max3100_set_termios(struct uart_port *port, struct ktermios *termios, · 520 unmodified lines | |||
| 521 | MAX3100_STATUS_PE | MAX3100_STATUS_FE | | 521 | MAX3100_STATUS_PE | MAX3100_STATUS_FE | |
| 522 | MAX3100_STATUS_OE; | 522 | MAX3100_STATUS_OE; |
| 523 | 523 | ||
| 524 | /* we are sending char from a workqueue so enable */ | ||
| 525 | s->port.state->port.low_latency = 1; | ||
| 526 | |||
| 527 | if (s->poll_time > 0) | 524 | if (s->poll_time > 0) |
| 528 | del_timer_sync(&s->timer); | 525 | del_timer_sync(&s->timer); |
| 529 | 526 | ||
| @@ -34,8 +34,6 @@ · 33 unmodified lines | |||
| 34 | #include <linux/dma-mapping.h> | 34 | #include <linux/dma-mapping.h> |
| 35 | #include <linux/dmaengine.h> | 35 | #include <linux/dmaengine.h> |
| 36 | 36 | ||
| 37 | #include <asm/cacheflush.h> | ||
| 38 | |||
| 39 | #include <linux/gpio/consumer.h> | 37 | #include <linux/gpio/consumer.h> |
| 40 | #include <linux/err.h> | 38 | #include <linux/err.h> |
| 41 | #include <linux/irq.h> | 39 | #include <linux/irq.h> |
| @@ -1535,34 +1533,6 @@ disable_clk_ahb: · 1493 unmodified lines | |||
| 1535 | return err; | 1533 | return err; |
| 1536 | } | 1534 | } |
| 1537 | 1535 | ||
| 1538 | /* | ||
| 1539 | * This function returns 1 if pdev isn't a device instatiated by dt, 0 if it | ||
| 1540 | * could successfully get all information from dt or a negative errno. | ||
| 1541 | */ | ||
| 1542 | static int serial_mxs_probe_dt(struct mxs_auart_port *s, | ||
| 1543 | struct platform_device *pdev) | ||
| 1544 | { | ||
| 1545 | struct device_node *np = pdev->dev.of_node; | ||
| 1546 | int ret; | ||
| 1547 | |||
| 1548 | if (!np) | ||
| 1549 | /* no device tree device */ | ||
| 1550 | return 1; | ||
| 1551 | |||
| 1552 | ret = of_alias_get_id(np, "serial"); | ||
| 1553 | if (ret < 0) { | ||
| 1554 | dev_err(&pdev->dev, "failed to get alias id: %d\n", ret); | ||
| 1555 | return ret; | ||
| 1556 | } | ||
| 1557 | s->port.line = ret; | ||
| 1558 | |||
| 1559 | if (of_get_property(np, "uart-has-rtscts", NULL) || | ||
| 1560 | of_get_property(np, "fsl,uart-has-rtscts", NULL) /* deprecated */) | ||
| 1561 | set_bit(MXS_AUART_RTSCTS, &s->flags); | ||
| 1562 | |||
| 1563 | return 0; | ||
| 1564 | } | ||
| 1565 | |||
| 1566 | static int mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev) | 1536 | static int mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev) |
| 1567 | { | 1537 | { |
| 1568 | enum mctrl_gpio_idx i; | 1538 | enum mctrl_gpio_idx i; |
| @@ -1631,6 +1601,7 @@ static int mxs_auart_request_gpio_irq(struct mxs_auart_port *s) · 62 unmodified lines | |||
| 1631 | 1601 | ||
| 1632 | static int mxs_auart_probe(struct platform_device *pdev) | 1602 | static int mxs_auart_probe(struct platform_device *pdev) |
| 1633 | { | 1603 | { |
| 1604 | struct device_node *np = pdev->dev.of_node; | ||
| 1634 | struct mxs_auart_port *s; | 1605 | struct mxs_auart_port *s; |
| 1635 | u32 version; | 1606 | u32 version; |
| 1636 | int ret, irq; | 1607 | int ret, irq; |
| @@ -1643,11 +1614,17 @@ static int mxs_auart_probe(struct platform_device *pdev) · 6 unmodified lines | |||
| 1643 | s->port.dev = &pdev->dev; | 1614 | s->port.dev = &pdev->dev; |
| 1644 | s->dev = &pdev->dev; | 1615 | s->dev = &pdev->dev; |
| 1645 | 1616 | ||
| 1646 | ret = serial_mxs_probe_dt(s, pdev); | 1617 | ret = of_alias_get_id(np, "serial"); |
| 1647 | if (ret > 0) | 1618 | if (ret < 0) { |
| 1648 | s->port.line = pdev->id < 0 ? 0 : pdev->id; | 1619 | dev_err(&pdev->dev, "failed to get alias id: %d\n", ret); |
| 1649 | else if (ret < 0) | ||
| 1650 | return ret; | 1620 | return ret; |
| 1621 | } | ||
| 1622 | s->port.line = ret; | ||
| 1623 | |||
| 1624 | if (of_get_property(np, "uart-has-rtscts", NULL) || | ||
| 1625 | of_get_property(np, "fsl,uart-has-rtscts", NULL) /* deprecated */) | ||
| 1626 | set_bit(MXS_AUART_RTSCTS, &s->flags); | ||
| 1627 | |||
| 1651 | if (s->port.line >= ARRAY_SIZE(auart_port)) { | 1628 | if (s->port.line >= ARRAY_SIZE(auart_port)) { |
| 1652 | dev_err(&pdev->dev, "serial%d out of range\n", s->port.line); | 1629 | dev_err(&pdev->dev, "serial%d out of range\n", s->port.line); |
| 1653 | return -EINVAL; | 1630 | return -EINVAL; |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | |||
| 12 | #include <linux/console.h> | 12 | #include <linux/console.h> |
| 13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
| 14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
| 15 | #include <linux/iopoll.h> | ||
| 15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 16 | #include <linux/of.h> | 17 | #include <linux/of.h> |
| 17 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
| @@ -62,6 +63,9 @@ · 44 unmodified lines | |||
| 62 | #define OWL_UART_STAT_TRFL_MASK GENMASK(16, 11) | 63 | #define OWL_UART_STAT_TRFL_MASK GENMASK(16, 11) |
| 63 | #define OWL_UART_STAT_UTBB BIT(17) | 64 | #define OWL_UART_STAT_UTBB BIT(17) |
| 64 | 65 | ||
| 66 | #define OWL_UART_POLL_USEC 5 | ||
| 67 | #define OWL_UART_TIMEOUT_USEC 10000 | ||
| 68 | |||
| 65 | static struct uart_driver owl_uart_driver; | 69 | static struct uart_driver owl_uart_driver; |
| 66 | 70 | ||
| 67 | struct owl_uart_info { | 71 | struct owl_uart_info { |
| @@ -461,6 +465,36 @@ static void owl_uart_config_port(struct uart_port *port, int flags) · 393 unmodified lines | |||
| 461 | } | 465 | } |
| 462 | } | 466 | } |
| 463 | 467 | ||
| 468 | #ifdef CONFIG_CONSOLE_POLL | ||
| 469 | |||
| 470 | static int owl_uart_poll_get_char(struct uart_port *port) | ||
| 471 | { | ||
| 472 | if (owl_uart_read(port, OWL_UART_STAT) & OWL_UART_STAT_RFEM) | ||
| 473 | return NO_POLL_CHAR; | ||
| 474 | |||
| 475 | return owl_uart_read(port, OWL_UART_RXDAT); | ||
| 476 | } | ||
| 477 | |||
| 478 | static void owl_uart_poll_put_char(struct uart_port *port, unsigned char ch) | ||
| 479 | { | ||
| 480 | u32 reg; | ||
| 481 | int ret; | ||
| 482 | |||
| 483 | /* Wait while FIFO is full or timeout */ | ||
| 484 | ret = readl_poll_timeout_atomic(port->membase + OWL_UART_STAT, reg, | ||
| 485 | !(reg & OWL_UART_STAT_TFFU), | ||
| 486 | OWL_UART_POLL_USEC, | ||
| 487 | OWL_UART_TIMEOUT_USEC); | ||
| 488 | if (ret == -ETIMEDOUT) { | ||
| 489 | dev_err(port->dev, "Timeout waiting while UART TX FULL\n"); | ||
| 490 | return; | ||
| 491 | } | ||
| 492 | |||
| 493 | owl_uart_write(port, ch, OWL_UART_TXDAT); | ||
| 494 | } | ||
| 495 | |||
| 496 | #endif /* CONFIG_CONSOLE_POLL */ | ||
| 497 | |||
| 464 | static const struct uart_ops owl_uart_ops = { | 498 | static const struct uart_ops owl_uart_ops = { |
| 465 | .set_mctrl = owl_uart_set_mctrl, | 499 | .set_mctrl = owl_uart_set_mctrl, |
| 466 | .get_mctrl = owl_uart_get_mctrl, | 500 | .get_mctrl = owl_uart_get_mctrl, |
| @@ -476,6 +510,10 @@ static const struct uart_ops owl_uart_ops = { · 9 unmodified lines | |||
| 476 | .request_port = owl_uart_request_port, | 510 | .request_port = owl_uart_request_port, |
| 477 | .release_port = owl_uart_release_port, | 511 | .release_port = owl_uart_release_port, |
| 478 | .verify_port = owl_uart_verify_port, | 512 | .verify_port = owl_uart_verify_port, |
| 513 | #ifdef CONFIG_CONSOLE_POLL | ||
| 514 | .poll_get_char = owl_uart_poll_get_char, | ||
| 515 | .poll_put_char = owl_uart_poll_put_char, | ||
| 516 | #endif | ||
| 479 | }; | 517 | }; |
| 480 | 518 | ||
| 481 | #ifdef CONFIG_SERIAL_OWL_CONSOLE | 519 | #ifdef CONFIG_SERIAL_OWL_CONSOLE |
| @@ -975,7 +975,6 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port, · 974 unmodified lines | |||
| 975 | port->closing_wait = closing_wait; | 975 | port->closing_wait = closing_wait; |
| 976 | if (new_info->xmit_fifo_size) | 976 | if (new_info->xmit_fifo_size) |
| 977 | uport->fifosize = new_info->xmit_fifo_size; | 977 | uport->fifosize = new_info->xmit_fifo_size; |
| 978 | port->low_latency = (uport->flags & UPF_LOW_LATENCY) ? 1 : 0; | ||
| 979 | 978 | ||
| 980 | check_and_exit: | 979 | check_and_exit: |
| 981 | retval = 0; | 980 | retval = 0; |
| @@ -1795,8 +1794,6 @@ static int uart_port_activate(struct tty_port *port, struct tty_struct *tty) · 813 unmodified lines | |||
| 1795 | if (!uport || uport->flags & UPF_DEAD) | 1794 | if (!uport || uport->flags & UPF_DEAD) |
| 1796 | return -ENXIO; | 1795 | return -ENXIO; |
| 1797 | 1796 | ||
| 1798 | port->low_latency = (uport->flags & UPF_LOW_LATENCY) ? 1 : 0; | ||
| 1799 | |||
| 1800 | /* | 1797 | /* |
| 1801 | * Start up the serial port. | 1798 | * Start up the serial port. |
| 1802 | */ | 1799 | */ |
| @@ -2851,6 +2848,8 @@ static const struct attribute_group tty_dev_attr_group = { · 1048 unmodified lines | |||
| 2851 | * @drv: pointer to the uart low level driver structure for this port | 2848 | * @drv: pointer to the uart low level driver structure for this port |
| 2852 | * @uport: uart port structure to use for this port. | 2849 | * @uport: uart port structure to use for this port. |
| 2853 | * | 2850 | * |
| 2851 | * Context: task context, might sleep | ||
| 2852 | * | ||
| 2854 | * This allows the driver to register its own uart_port structure | 2853 | * This allows the driver to register its own uart_port structure |
| 2855 | * with the core driver. The main purpose is to allow the low | 2854 | * with the core driver. The main purpose is to allow the low |
| 2856 | * level uart drivers to expand uart_port, rather than having yet | 2855 | * level uart drivers to expand uart_port, rather than having yet |
| @@ -2864,8 +2863,6 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) · 7 unmodified lines | |||
| 2864 | struct device *tty_dev; | 2863 | struct device *tty_dev; |
| 2865 | int num_groups; | 2864 | int num_groups; |
| 2866 | 2865 | ||
| 2867 | BUG_ON(in_interrupt()); | ||
| 2868 | |||
| 2869 | if (uport->line >= drv->nr) | 2866 | if (uport->line >= drv->nr) |
| 2870 | return -EINVAL; | 2867 | return -EINVAL; |
| 2871 | 2868 | ||
| @@ -2954,6 +2951,8 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) · 82 unmodified lines | |||
| 2954 | * @drv: pointer to the uart low level driver structure for this port | 2951 | * @drv: pointer to the uart low level driver structure for this port |
| 2955 | * @uport: uart port structure for this port | 2952 | * @uport: uart port structure for this port |
| 2956 | * | 2953 | * |
| 2954 | * Context: task context, might sleep | ||
| 2955 | * | ||
| 2957 | * This unhooks (and hangs up) the specified port structure from the | 2956 | * This unhooks (and hangs up) the specified port structure from the |
| 2958 | * core driver. No further calls will be made to the low-level code | 2957 | * core driver. No further calls will be made to the low-level code |
| 2959 | * for this port. | 2958 | * for this port. |
| @@ -2966,8 +2965,6 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport) · 6 unmodified lines | |||
| 2966 | struct tty_struct *tty; | 2965 | struct tty_struct *tty; |
| 2967 | int ret = 0; | 2966 | int ret = 0; |
| 2968 | 2967 | ||
| 2969 | BUG_ON(in_interrupt()); | ||
| 2970 | |||
| 2971 | mutex_lock(&port_mutex); | 2968 | mutex_lock(&port_mutex); |
| 2972 | 2969 | ||
| 2973 | /* | 2970 | /* |
| @@ -1,1503 +0,0 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0+ | ||
| 2 | /* | ||
| 3 | * Driver for CSR SiRFprimaII onboard UARTs. | ||
| 4 | * | ||
| 5 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/module.h> | ||
| 9 | #include <linux/ioport.h> | ||
| 10 | #include <linux/platform_device.h> | ||
| 11 | #include <linux/init.h> | ||
| 12 | #include <linux/sysrq.h> | ||
| 13 | #include <linux/console.h> | ||
| 14 | #include <linux/tty.h> | ||
| 15 | #include <linux/tty_flip.h> | ||
| 16 | #include <linux/serial_core.h> | ||
| 17 | #include <linux/serial.h> | ||
| 18 | #include <linux/clk.h> | ||
| 19 | #include <linux/of.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/io.h> | ||
| 22 | #include <linux/of_gpio.h> | ||
| 23 | #include <linux/dmaengine.h> | ||
| 24 | #include <linux/dma-direction.h> | ||
| 25 | #include <linux/dma-mapping.h> | ||
| 26 | #include <asm/irq.h> | ||
| 27 | #include <asm/mach/irq.h> | ||
| 28 | |||
| 29 | #include "sirfsoc_uart.h" | ||
| 30 | |||
| 31 | static unsigned int | ||
| 32 | sirfsoc_uart_pio_tx_chars(struct sirfsoc_uart_port *sirfport, int count); | ||
| 33 | static unsigned int | ||
| 34 | sirfsoc_uart_pio_rx_chars(struct uart_port *port, unsigned int max_rx_count); | ||
| 35 | static struct uart_driver sirfsoc_uart_drv; | ||
| 36 | |||
| 37 | static void sirfsoc_uart_tx_dma_complete_callback(void *param); | ||
| 38 | static const struct sirfsoc_baudrate_to_regv baudrate_to_regv[] = { | ||
| 39 | {4000000, 2359296}, | ||
| 40 | {3500000, 1310721}, | ||
| 41 | {3000000, 1572865}, | ||
| 42 | {2500000, 1245186}, | ||
| 43 | {2000000, 1572866}, | ||
| 44 | {1500000, 1245188}, | ||
| 45 | {1152000, 1638404}, | ||
| 46 | {1000000, 1572869}, | ||
| 47 | {921600, 1114120}, | ||
| 48 | {576000, 1245196}, | ||
| 49 | {500000, 1245198}, | ||
| 50 | {460800, 1572876}, | ||
| 51 | {230400, 1310750}, | ||
| 52 | {115200, 1310781}, | ||
| 53 | {57600, 1310843}, | ||
| 54 | {38400, 1114328}, | ||
| 55 | {19200, 1114545}, | ||
| 56 | {9600, 1114979}, | ||
| 57 | }; | ||
| 58 | |||
| 59 | static struct sirfsoc_uart_port *sirf_ports[SIRFSOC_UART_NR]; | ||
| 60 | |||
| 61 | static inline struct sirfsoc_uart_port *to_sirfport(struct uart_port *port) | ||
| 62 | { | ||
| 63 | return container_of(port, struct sirfsoc_uart_port, port); | ||
| 64 | } | ||
| 65 | |||
| 66 | static inline unsigned int sirfsoc_uart_tx_empty(struct uart_port *port) | ||
| 67 | { | ||
| 68 | unsigned long reg; | ||
| 69 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
| 70 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | ||
| 71 | struct sirfsoc_fifo_status *ufifo_st = &sirfport->uart_reg->fifo_status; | ||
| 72 | reg = rd_regl(port, ureg->sirfsoc_tx_fifo_status); | ||
| 73 | return (reg & ufifo_st->ff_empty(port)) ? TIOCSER_TEMT : 0; | ||
| 74 | } | ||
| 75 | |||
| 76 | static unsigned int sirfsoc_uart_get_mctrl(struct uart_port *port) | ||
| 77 | { | ||
| 78 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
| 79 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | ||
| 80 | if (!sirfport->hw_flow_ctrl || !sirfport->ms_enabled) | ||
| 81 | goto cts_asserted; | ||
| 82 | if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { | ||
| 83 | if (!(rd_regl(port, ureg->sirfsoc_afc_ctrl) & | ||
| 84 | SIRFUART_AFC_CTS_STATUS)) | ||
| 85 | goto cts_asserted; | ||
| 86 | else | ||
| 87 | goto cts_deasserted; | ||
| 88 | } else { | ||
| 89 | if (!gpio_get_value(sirfport->cts_gpio)) | ||
| 90 | goto cts_asserted; | ||
| 91 | else | ||
| 92 | goto cts_deasserted; | ||
| 93 | } | ||
| 94 | cts_deasserted: | ||
| 95 | return TIOCM_CAR | TIOCM_DSR; | ||
| 96 | cts_asserted: | ||
| 97 | return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; | ||
| 98 | } | ||
| 99 | |||
| 100 | static void sirfsoc_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
| 101 | { | ||
| 102 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
| 103 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | ||
| 104 | unsigned int assert = mctrl & TIOCM_RTS; | ||
| 105 | unsigned int val = assert ? SIRFUART_AFC_CTRL_RX_THD : 0x0; | ||
| 106 | unsigned int current_val; | ||
| 107 | |||
| 108 | if (mctrl & TIOCM_LOOP) { | ||
| 109 | if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) | ||
| 110 | wr_regl(port, ureg->sirfsoc_line_ctrl, | ||
| 111 | rd_regl(port, ureg->sirfsoc_line_ctrl) | | ||
| 112 | SIRFUART_LOOP_BACK); | ||
| 113 | else | ||
| 114 | wr_regl(port, ureg->sirfsoc_mode1, | ||
| 115 | rd_regl(port, ureg->sirfsoc_mode1) | | ||
| 116 | SIRFSOC_USP_LOOP_BACK_CTRL); | ||
| 117 | } else { | ||
| 118 | if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) | ||
| 119 | wr_regl(port, ureg->sirfsoc_line_ctrl, | ||
| 120 | rd_regl(port, ureg->sirfsoc_line_ctrl) & | ||
| 121 | ~SIRFUART_LOOP_BACK); | ||
| 122 | else | ||
| 123 | wr_regl(port, ureg->sirfsoc_mode1, | ||
| 124 | rd_regl(port, ureg->sirfsoc_mode1) & | ||
| 125 | ~SIRFSOC_USP_LOOP_BACK_CTRL); | ||
| 126 | } | ||
| 127 | |||
| 128 | if (!sirfport->hw_flow_ctrl || !sirfport->ms_enabled) | ||
| 129 | return; | ||
| 130 | if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { | ||
| 131 | current_val = rd_regl(port, ureg->sirfsoc_afc_ctrl) & ~0xFF; | ||
| 132 | val |= current_val; | ||
| 133 | wr_regl(port, ureg->sirfsoc_afc_ctrl, val); | ||
| 134 | } else { | ||
| 135 | if (!val) | ||
| 136 | gpio_set_value(sirfport->rts_gpio, 1); | ||
| 137 | else | ||
| 138 | gpio_set_value(sirfport->rts_gpio, 0); | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | static void sirfsoc_uart_stop_tx(struct uart_port *port) | ||
| 143 | { | ||
| 144 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
| 145 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | ||
| 146 | struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; | ||
| 147 | |||
| 148 | if (sirfport->tx_dma_chan) { | ||
| 149 | if (sirfport->tx_dma_state == TX_DMA_RUNNING) { | ||
| 150 | dmaengine_pause(sirfport->tx_dma_chan); | ||
| 151 | sirfport->tx_dma_state = TX_DMA_PAUSE; | ||
| 152 | } else { | ||
| 153 | if (!sirfport->is_atlas7) | ||
| 154 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 155 | rd_regl(port, ureg->sirfsoc_int_en_reg) & | ||
| 156 | ~uint_en->sirfsoc_txfifo_empty_en); | ||
| 157 | else | ||
| 158 | wr_regl(port, ureg->sirfsoc_int_en_clr_reg, | ||
| 159 | uint_en->sirfsoc_txfifo_empty_en); | ||
| 160 | } | ||
| 161 | } else { | ||
| 162 | if (sirfport->uart_reg->uart_type == SIRF_USP_UART) | ||
| 163 | wr_regl(port, ureg->sirfsoc_tx_rx_en, rd_regl(port, | ||
| 164 | ureg->sirfsoc_tx_rx_en) & ~SIRFUART_TX_EN); | ||
| 165 | if (!sirfport->is_atlas7) | ||
| 166 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 167 | rd_regl(port, ureg->sirfsoc_int_en_reg) & | ||
| 168 | ~uint_en->sirfsoc_txfifo_empty_en); | ||
| 169 | else | ||
| 170 | wr_regl(port, ureg->sirfsoc_int_en_clr_reg, | ||
| 171 | uint_en->sirfsoc_txfifo_empty_en); | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | static void sirfsoc_uart_tx_with_dma(struct sirfsoc_uart_port *sirfport) | ||
| 176 | { | ||
| 177 | struct uart_port *port = &sirfport->port; | ||
| 178 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | ||
| 179 | struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; | ||
| 180 | struct circ_buf *xmit = &port->state->xmit; | ||
| 181 | unsigned long tran_size; | ||
| 182 | unsigned long tran_start; | ||
| 183 | unsigned long pio_tx_size; | ||
| 184 | |||
| 185 | tran_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); | ||
| 186 | tran_start = (unsigned long)(xmit->buf + xmit->tail); | ||
| 187 | if (uart_circ_empty(xmit) || uart_tx_stopped(port) || | ||
| 188 | !tran_size) | ||
| 189 | return; | ||
| 190 | if (sirfport->tx_dma_state == TX_DMA_PAUSE) { | ||
| 191 | dmaengine_resume(sirfport->tx_dma_chan); | ||
| 192 | return; | ||
| 193 | } | ||
| 194 | if (sirfport->tx_dma_state == TX_DMA_RUNNING) | ||
| 195 | return; | ||
| 196 | if (!sirfport->is_atlas7) | ||
| 197 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 198 | rd_regl(port, ureg->sirfsoc_int_en_reg)& | ||
| 199 | ~(uint_en->sirfsoc_txfifo_empty_en)); | ||
| 200 | else | ||
| 201 | wr_regl(port, ureg->sirfsoc_int_en_clr_reg, | ||
| 202 | uint_en->sirfsoc_txfifo_empty_en); | ||
| 203 | /* | ||
| 204 | * DMA requires buffer address and buffer length are both aligned with | ||
| 205 | * 4 bytes, so we use PIO for | ||
| 206 | * 1. if address is not aligned with 4bytes, use PIO for the first 1~3 | ||
| 207 | * bytes, and move to DMA for the left part aligned with 4bytes | ||
| 208 | * 2. if buffer length is not aligned with 4bytes, use DMA for aligned | ||
| 209 | * part first, move to PIO for the left 1~3 bytes | ||
| 210 | */ | ||
| 211 | if (tran_size < 4 || BYTES_TO_ALIGN(tran_start)) { | ||
| 212 | wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_STOP); | ||
| 213 | wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, | ||
| 214 | rd_regl(port, ureg->sirfsoc_tx_dma_io_ctrl)| | ||
| 215 | SIRFUART_IO_MODE); | ||
| 216 | if (BYTES_TO_ALIGN(tran_start)) { | ||
| 217 | pio_tx_size = sirfsoc_uart_pio_tx_chars(sirfport, | ||
| 218 | BYTES_TO_ALIGN(tran_start)); | ||
| 219 | tran_size -= pio_tx_size; | ||
| 220 | } | ||
| 221 | if (tran_size < 4) | ||
| 222 | sirfsoc_uart_pio_tx_chars(sirfport, tran_size); | ||
| 223 | if (!sirfport->is_atlas7) | ||
| 224 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 225 | rd_regl(port, ureg->sirfsoc_int_en_reg)| | ||
| 226 | uint_en->sirfsoc_txfifo_empty_en); | ||
| 227 | else | ||
| 228 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 229 | uint_en->sirfsoc_txfifo_empty_en); | ||
| 230 | wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_START); | ||
| 231 | } else { | ||
| 232 | /* tx transfer mode switch into dma mode */ | ||
| 233 | wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_STOP); | ||
| 234 | wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, | ||
| 235 | rd_regl(port, ureg->sirfsoc_tx_dma_io_ctrl)& | ||
| 236 | ~SIRFUART_IO_MODE); | ||
| 237 | wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_START); | ||
| 238 | tran_size &= ~(0x3); | ||
| 239 | |||
| 240 | sirfport->tx_dma_addr = dma_map_single(port->dev, | ||
| 241 | xmit->buf + xmit->tail, | ||
| 242 | tran_size, DMA_TO_DEVICE); | ||
| 243 | sirfport->tx_dma_desc = dmaengine_prep_slave_single( | ||
| 244 | sirfport->tx_dma_chan, sirfport->tx_dma_addr, | ||
| 245 | tran_size, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); | ||
| 246 | if (!sirfport->tx_dma_desc) { | ||
| 247 | dev_err(port->dev, "DMA prep slave single fail\n"); | ||
| 248 | return; | ||
| 249 | } | ||
| 250 | sirfport->tx_dma_desc->callback = | ||
| 251 | sirfsoc_uart_tx_dma_complete_callback; | ||
| 252 | sirfport->tx_dma_desc->callback_param = (void *)sirfport; | ||
| 253 | sirfport->transfer_size = tran_size; | ||
| 254 | |||
| 255 | dmaengine_submit(sirfport->tx_dma_desc); | ||
| 256 | dma_async_issue_pending(sirfport->tx_dma_chan); | ||
| 257 | sirfport->tx_dma_state = TX_DMA_RUNNING; | ||
| 258 | } | ||
| 259 | } | ||
| 260 | |||
| 261 | static void sirfsoc_uart_start_tx(struct uart_port *port) | ||
| 262 | { | ||
| 263 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
| 264 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | ||
| 265 | struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; | ||
| 266 | if (sirfport->tx_dma_chan) | ||
| 267 | sirfsoc_uart_tx_with_dma(sirfport); | ||
| 268 | else { | ||
| 269 | if (sirfport->uart_reg->uart_type == SIRF_USP_UART) | ||
| 270 | wr_regl(port, ureg->sirfsoc_tx_rx_en, rd_regl(port, | ||
| 271 | ureg->sirfsoc_tx_rx_en) | SIRFUART_TX_EN); | ||
| 272 | wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_STOP); | ||
| 273 | sirfsoc_uart_pio_tx_chars(sirfport, port->fifosize); | ||
| 274 | wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_START); | ||
| 275 | if (!sirfport->is_atlas7) | ||
| 276 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 277 | rd_regl(port, ureg->sirfsoc_int_en_reg)| | ||
| 278 | uint_en->sirfsoc_txfifo_empty_en); | ||
| 279 | else | ||
| 280 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 281 | uint_en->sirfsoc_txfifo_empty_en); | ||
| 282 | } | ||
| 283 | } | ||
| 284 | |||
| 285 | static void sirfsoc_uart_stop_rx(struct uart_port *port) | ||
| 286 | { | ||
| 287 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
| 288 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | ||
| 289 | struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; | ||
| 290 | |||
| 291 | wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0); | ||
| 292 | if (sirfport->rx_dma_chan) { | ||
| 293 | if (!sirfport->is_atlas7) | ||
| 294 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 295 | rd_regl(port, ureg->sirfsoc_int_en_reg) & | ||
| 296 | ~(SIRFUART_RX_DMA_INT_EN(uint_en, | ||
| 297 | sirfport->uart_reg->uart_type) | | ||
| 298 | uint_en->sirfsoc_rx_done_en)); | ||
| 299 | else | ||
| 300 | wr_regl(port, ureg->sirfsoc_int_en_clr_reg, | ||
| 301 | SIRFUART_RX_DMA_INT_EN(uint_en, | ||
| 302 | sirfport->uart_reg->uart_type)| | ||
| 303 | uint_en->sirfsoc_rx_done_en); | ||
| 304 | dmaengine_terminate_all(sirfport->rx_dma_chan); | ||
| 305 | } else { | ||
| 306 | if (!sirfport->is_atlas7) | ||
| 307 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 308 | rd_regl(port, ureg->sirfsoc_int_en_reg)& | ||
| 309 | ~(SIRFUART_RX_IO_INT_EN(uint_en, | ||
| 310 | sirfport->uart_reg->uart_type))); | ||
| 311 | else | ||
| 312 | wr_regl(port, ureg->sirfsoc_int_en_clr_reg, | ||
| 313 | SIRFUART_RX_IO_INT_EN(uint_en, | ||
| 314 | sirfport->uart_reg->uart_type)); | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | static void sirfsoc_uart_disable_ms(struct uart_port *port) | ||
| 319 | { | ||
| 320 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
| 321 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | ||
| 322 | struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; | ||
| 323 | |||
| 324 | if (!sirfport->hw_flow_ctrl) | ||
| 325 | return; | ||
| 326 | sirfport->ms_enabled = false; | ||
| 327 | if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { | ||
| 328 | wr_regl(port, ureg->sirfsoc_afc_ctrl, | ||
| 329 | rd_regl(port, ureg->sirfsoc_afc_ctrl) & ~0x3FF); | ||
| 330 | if (!sirfport->is_atlas7) | ||
| 331 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 332 | rd_regl(port, ureg->sirfsoc_int_en_reg)& | ||
| 333 | ~uint_en->sirfsoc_cts_en); | ||
| 334 | else | ||
| 335 | wr_regl(port, ureg->sirfsoc_int_en_clr_reg, | ||
| 336 | uint_en->sirfsoc_cts_en); | ||
| 337 | } else | ||
| 338 | disable_irq(gpio_to_irq(sirfport->cts_gpio)); | ||
| 339 | } | ||
| 340 | |||
| 341 | static irqreturn_t sirfsoc_uart_usp_cts_handler(int irq, void *dev_id) | ||
| 342 | { | ||
| 343 | struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)dev_id; | ||
| 344 | struct uart_port *port = &sirfport->port; | ||
| 345 | spin_lock(&port->lock); | ||
| 346 | if (gpio_is_valid(sirfport->cts_gpio) && sirfport->ms_enabled) | ||
| 347 | uart_handle_cts_change(port, | ||
| 348 | !gpio_get_value(sirfport->cts_gpio)); | ||
| 349 | spin_unlock(&port->lock); | ||
| 350 | return IRQ_HANDLED; | ||
| 351 | } | ||
| 352 | |||
| 353 | static void sirfsoc_uart_enable_ms(struct uart_port *port) | ||
| 354 | { | ||
| 355 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
| 356 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | ||
| 357 | struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; | ||
| 358 | |||
| 359 | if (!sirfport->hw_flow_ctrl) | ||
| 360 | return; | ||
| 361 | sirfport->ms_enabled = true; | ||
| 362 | if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { | ||
| 363 | wr_regl(port, ureg->sirfsoc_afc_ctrl, | ||
| 364 | rd_regl(port, ureg->sirfsoc_afc_ctrl) | | ||
| 365 | SIRFUART_AFC_TX_EN | SIRFUART_AFC_RX_EN | | ||
| 366 | SIRFUART_AFC_CTRL_RX_THD); | ||
| 367 | if (!sirfport->is_atlas7) | ||
| 368 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 369 | rd_regl(port, ureg->sirfsoc_int_en_reg) | ||
| 370 | | uint_en->sirfsoc_cts_en); | ||
| 371 | else | ||
| 372 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 373 | uint_en->sirfsoc_cts_en); | ||
| 374 | } else | ||
| 375 | enable_irq(gpio_to_irq(sirfport->cts_gpio)); | ||
| 376 | } | ||
| 377 | |||
| 378 | static void sirfsoc_uart_break_ctl(struct uart_port *port, int break_state) | ||
| 379 | { | ||
| 380 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
| 381 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | ||
| 382 | if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { | ||
| 383 | unsigned long ulcon = rd_regl(port, ureg->sirfsoc_line_ctrl); | ||
| 384 | if (break_state) | ||
| 385 | ulcon |= SIRFUART_SET_BREAK; | ||
| 386 | else | ||
| 387 | ulcon &= ~SIRFUART_SET_BREAK; | ||
| 388 | wr_regl(port, ureg->sirfsoc_line_ctrl, ulcon); | ||
| 389 | } | ||
| 390 | } | ||
| 391 | |||
| 392 | static unsigned int | ||
| 393 | sirfsoc_uart_pio_rx_chars(struct uart_port *port, unsigned int max_rx_count) | ||
| 394 | { | ||
| 395 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
| 396 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | ||
| 397 | struct sirfsoc_fifo_status *ufifo_st = &sirfport->uart_reg->fifo_status; | ||
| 398 | unsigned int ch, rx_count = 0; | ||
| 399 | struct tty_struct *tty; | ||
| 400 | tty = tty_port_tty_get(&port->state->port); | ||
| 401 | if (!tty) | ||
| 402 | return -ENODEV; | ||
| 403 | while (!(rd_regl(port, ureg->sirfsoc_rx_fifo_status) & | ||
| 404 | ufifo_st->ff_empty(port))) { | ||
| 405 | ch = rd_regl(port, ureg->sirfsoc_rx_fifo_data) | | ||
| 406 | SIRFUART_DUMMY_READ; | ||
| 407 | if (unlikely(uart_handle_sysrq_char(port, ch))) | ||
| 408 | continue; | ||
| 409 | uart_insert_char(port, 0, 0, ch, TTY_NORMAL); | ||
| 410 | rx_count++; | ||
| 411 | if (rx_count >= max_rx_count) | ||
| 412 | break; | ||
| 413 | } | ||
| 414 | |||
| 415 | port->icount.rx += rx_count; | ||
| 416 | |||
| 417 | return rx_count; | ||
| 418 | } | ||
| 419 | |||
| 420 | static unsigned int | ||
| 421 | sirfsoc_uart_pio_tx_chars(struct sirfsoc_uart_port *sirfport, int count) | ||
| 422 | { | ||
| 423 | struct uart_port *port = &sirfport->port; | ||
| 424 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | ||
| 425 | struct sirfsoc_fifo_status *ufifo_st = &sirfport->uart_reg->fifo_status; | ||
| 426 | struct circ_buf *xmit = &port->state->xmit; | ||
| 427 | unsigned int num_tx = 0; | ||
| 428 | while (!uart_circ_empty(xmit) && | ||
| 429 | !(rd_regl(port, ureg->sirfsoc_tx_fifo_status) & | ||
| 430 | ufifo_st->ff_full(port)) && | ||
| 431 | count--) { | ||
| 432 | wr_regl(port, ureg->sirfsoc_tx_fifo_data, | ||
| 433 | xmit->buf[xmit->tail]); | ||
| 434 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
| 435 | port->icount.tx++; | ||
| 436 | num_tx++; | ||
| 437 | } | ||
| 438 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
| 439 | uart_write_wakeup(port); | ||
| 440 | return num_tx; | ||
| 441 | } | ||
| 442 | |||
| 443 | static void sirfsoc_uart_tx_dma_complete_callback(void *param) | ||
| 444 | { | ||
| 445 | struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)param; | ||
| 446 | struct uart_port *port = &sirfport->port; | ||
| 447 | struct circ_buf *xmit = &port->state->xmit; | ||
| 448 | unsigned long flags; | ||
| 449 | |||
| 450 | spin_lock_irqsave(&port->lock, flags); | ||
| 451 | xmit->tail = (xmit->tail + sirfport->transfer_size) & | ||
| 452 | (UART_XMIT_SIZE - 1); | ||
| 453 | port->icount.tx += sirfport->transfer_size; | ||
| 454 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
| 455 | uart_write_wakeup(port); | ||
| 456 | if (sirfport->tx_dma_addr) | ||
| 457 | dma_unmap_single(port->dev, sirfport->tx_dma_addr, | ||
| 458 | sirfport->transfer_size, DMA_TO_DEVICE); | ||
| 459 | sirfport->tx_dma_state = TX_DMA_IDLE; | ||
| 460 | sirfsoc_uart_tx_with_dma(sirfport); | ||
| 461 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 462 | } | ||
| 463 | |||
| 464 | static irqreturn_t sirfsoc_uart_isr(int irq, void *dev_id) | ||
| 465 | { | ||
| 466 | unsigned long intr_status; | ||
| 467 | unsigned long cts_status; | ||
| 468 | unsigned long flag = TTY_NORMAL; | ||
| 469 | struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)dev_id; | ||
| 470 | struct uart_port *port = &sirfport->port; | ||
| 471 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | ||
| 472 | struct sirfsoc_fifo_status *ufifo_st = &sirfport->uart_reg->fifo_status; | ||
| 473 | struct sirfsoc_int_status *uint_st = &sirfport->uart_reg->uart_int_st; | ||
| 474 | struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; | ||
| 475 | struct uart_state *state = port->state; | ||
| 476 | struct circ_buf *xmit = &port->state->xmit; | ||
| 477 | spin_lock(&port->lock); | ||
| 478 | intr_status = rd_regl(port, ureg->sirfsoc_int_st_reg); | ||
| 479 | wr_regl(port, ureg->sirfsoc_int_st_reg, intr_status); | ||
| 480 | intr_status &= rd_regl(port, ureg->sirfsoc_int_en_reg); | ||
| 481 | if (unlikely(intr_status & (SIRFUART_ERR_INT_STAT(uint_st, | ||
| 482 | sirfport->uart_reg->uart_type)))) { | ||
| 483 | if (intr_status & uint_st->sirfsoc_rxd_brk) { | ||
| 484 | port->icount.brk++; | ||
| 485 | if (uart_handle_break(port)) | ||
| 486 | goto recv_char; | ||
| 487 | } | ||
| 488 | if (intr_status & uint_st->sirfsoc_rx_oflow) { | ||
| 489 | port->icount.overrun++; | ||
| 490 | flag = TTY_OVERRUN; | ||
| 491 | } | ||
| 492 | if (intr_status & uint_st->sirfsoc_frm_err) { | ||
| 493 | port->icount.frame++; | ||
| 494 | flag = TTY_FRAME; | ||
| 495 | } | ||
| 496 | if (intr_status & uint_st->sirfsoc_parity_err) { | ||
| 497 | port->icount.parity++; | ||
| 498 | flag = TTY_PARITY; | ||
| 499 | } | ||
| 500 | wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET); | ||
| 501 | wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0); | ||
| 502 | wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START); | ||
| 503 | intr_status &= port->read_status_mask; | ||
| 504 | uart_insert_char(port, intr_status, | ||
| 505 | uint_en->sirfsoc_rx_oflow_en, 0, flag); | ||
| 506 | } | ||
| 507 | recv_char: | ||
| 508 | if ((sirfport->uart_reg->uart_type == SIRF_REAL_UART) && | ||
| 509 | (intr_status & SIRFUART_CTS_INT_ST(uint_st)) && | ||
| 510 | !sirfport->tx_dma_state) { | ||
| 511 | cts_status = rd_regl(port, ureg->sirfsoc_afc_ctrl) & | ||
| 512 | SIRFUART_AFC_CTS_STATUS; | ||
| 513 | if (cts_status != 0) | ||
| 514 | cts_status = 0; | ||
| 515 | else | ||
| 516 | cts_status = 1; | ||
| 517 | uart_handle_cts_change(port, cts_status); | ||
| 518 | wake_up_interruptible(&state->port.delta_msr_wait); | ||
| 519 | } | ||
| 520 | if (!sirfport->rx_dma_chan && | ||
| 521 | (intr_status & SIRFUART_RX_IO_INT_ST(uint_st))) { | ||
| 522 | /* | ||
| 523 | * chip will trigger continuous RX_TIMEOUT interrupt | ||
| 524 | * in RXFIFO empty and not trigger if RXFIFO recevice | ||
| 525 | * data in limit time, original method use RX_TIMEOUT | ||
| 526 | * will trigger lots of useless interrupt in RXFIFO | ||
| 527 | * empty.RXFIFO received one byte will trigger RX_DONE | ||
| 528 | * interrupt.use RX_DONE to wait for data received | ||
| 529 | * into RXFIFO, use RX_THD/RX_FULL for lots data receive | ||
| 530 | * and use RX_TIMEOUT for the last left data. | ||
| 531 | */ | ||
| 532 | if (intr_status & uint_st->sirfsoc_rx_done) { | ||
| 533 | if (!sirfport->is_atlas7) { | ||
| 534 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 535 | rd_regl(port, ureg->sirfsoc_int_en_reg) | ||
| 536 | & ~(uint_en->sirfsoc_rx_done_en)); | ||
| 537 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 538 | rd_regl(port, ureg->sirfsoc_int_en_reg) | ||
| 539 | | (uint_en->sirfsoc_rx_timeout_en)); | ||
| 540 | } else { | ||
| 541 | wr_regl(port, ureg->sirfsoc_int_en_clr_reg, | ||
| 542 | uint_en->sirfsoc_rx_done_en); | ||
| 543 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 544 | uint_en->sirfsoc_rx_timeout_en); | ||
| 545 | } | ||
| 546 | } else { | ||
| 547 | if (intr_status & uint_st->sirfsoc_rx_timeout) { | ||
| 548 | if (!sirfport->is_atlas7) { | ||
| 549 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 550 | rd_regl(port, ureg->sirfsoc_int_en_reg) | ||
| 551 | & ~(uint_en->sirfsoc_rx_timeout_en)); | ||
| 552 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 553 | rd_regl(port, ureg->sirfsoc_int_en_reg) | ||
| 554 | | (uint_en->sirfsoc_rx_done_en)); | ||
| 555 | } else { | ||
| 556 | wr_regl(port, | ||
| 557 | ureg->sirfsoc_int_en_clr_reg, | ||
| 558 | uint_en->sirfsoc_rx_timeout_en); | ||
| 559 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 560 | uint_en->sirfsoc_rx_done_en); | ||
| 561 | } | ||
| 562 | } | ||
| 563 | sirfsoc_uart_pio_rx_chars(port, port->fifosize); | ||
| 564 | } | ||
| 565 | } | ||
| 566 | spin_unlock(&port->lock); | ||
| 567 | tty_flip_buffer_push(&state->port); | ||
| 568 | spin_lock(&port->lock); | ||
| 569 | if (intr_status & uint_st->sirfsoc_txfifo_empty) { | ||
| 570 | if (sirfport->tx_dma_chan) | ||
| 571 | sirfsoc_uart_tx_with_dma(sirfport); | ||
| 572 | else { | ||
| 573 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | ||
| 574 | spin_unlock(&port->lock); | ||
| 575 | return IRQ_HANDLED; | ||
| 576 | } else { | ||
| 577 | sirfsoc_uart_pio_tx_chars(sirfport, | ||
| 578 | port->fifosize); | ||
| 579 | if ((uart_circ_empty(xmit)) && | ||
| 580 | (rd_regl(port, ureg->sirfsoc_tx_fifo_status) & | ||
| 581 | ufifo_st->ff_empty(port))) | ||
| 582 | sirfsoc_uart_stop_tx(port); | ||
| 583 | } | ||
| 584 | } | ||
| 585 | } | ||
| 586 | spin_unlock(&port->lock); | ||
| 587 | |||
| 588 | return IRQ_HANDLED; | ||
| 589 | } | ||
| 590 | |||
| 591 | static void sirfsoc_uart_rx_dma_complete_callback(void *param) | ||
| 592 | { | ||
| 593 | } | ||
| 594 | |||
| 595 | /* submit rx dma task into dmaengine */ | ||
| 596 | static void sirfsoc_uart_start_next_rx_dma(struct uart_port *port) | ||
| 597 | { | ||
| 598 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
| 599 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | ||
| 600 | struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; | ||
| 601 | wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, | ||
| 602 | rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) & | ||
| 603 | ~SIRFUART_IO_MODE); | ||
| 604 | sirfport->rx_dma_items.xmit.tail = | ||
| 605 | sirfport->rx_dma_items.xmit.head = 0; | ||
| 606 | sirfport->rx_dma_items.desc = | ||
| 607 | dmaengine_prep_dma_cyclic(sirfport->rx_dma_chan, | ||
| 608 | sirfport->rx_dma_items.dma_addr, SIRFSOC_RX_DMA_BUF_SIZE, | ||
| 609 | SIRFSOC_RX_DMA_BUF_SIZE / 2, | ||
| 610 | DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); | ||
| 611 | if (IS_ERR_OR_NULL(sirfport->rx_dma_items.desc)) { | ||
| 612 | dev_err(port->dev, "DMA slave single fail\n"); | ||
| 613 | return; | ||
| 614 | } | ||
| 615 | sirfport->rx_dma_items.desc->callback = | ||
| 616 | sirfsoc_uart_rx_dma_complete_callback; | ||
| 617 | sirfport->rx_dma_items.desc->callback_param = sirfport; | ||
| 618 | sirfport->rx_dma_items.cookie = | ||
| 619 | dmaengine_submit(sirfport->rx_dma_items.desc); | ||
| 620 | dma_async_issue_pending(sirfport->rx_dma_chan); | ||
| 621 | if (!sirfport->is_atlas7) | ||
| 622 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 623 | rd_regl(port, ureg->sirfsoc_int_en_reg) | | ||
| 624 | SIRFUART_RX_DMA_INT_EN(uint_en, | ||
| 625 | sirfport->uart_reg->uart_type)); | ||
| 626 | else | ||
| 627 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 628 | SIRFUART_RX_DMA_INT_EN(uint_en, | ||
| 629 | sirfport->uart_reg->uart_type)); | ||
| 630 | } | ||
| 631 | |||
| 632 | static unsigned int | ||
| 633 | sirfsoc_usp_calc_sample_div(unsigned long set_rate, | ||
| 634 | unsigned long ioclk_rate, unsigned long *sample_reg) | ||
| 635 | { | ||
| 636 | unsigned long min_delta = ~0UL; | ||
| 637 | unsigned short sample_div; | ||
| 638 | unsigned long ioclk_div = 0; | ||
| 639 | unsigned long temp_delta; | ||
| 640 | |||
| 641 | for (sample_div = SIRF_USP_MIN_SAMPLE_DIV; | ||
| 642 | sample_div <= SIRF_MAX_SAMPLE_DIV; sample_div++) { | ||
| 643 | temp_delta = ioclk_rate - | ||
| 644 | (ioclk_rate + (set_rate * sample_div) / 2) | ||
| 645 | / (set_rate * sample_div) * set_rate * sample_div; | ||
| 646 | |||
| 647 | temp_delta = (temp_delta > 0) ? temp_delta : -temp_delta; | ||
| 648 | if (temp_delta < min_delta) { | ||
| 649 | ioclk_div = (2 * ioclk_rate / | ||
| 650 | (set_rate * sample_div) + 1) / 2 - 1; | ||
| 651 | if (ioclk_div > SIRF_IOCLK_DIV_MAX) | ||
| 652 | continue; | ||
| 653 | min_delta = temp_delta; | ||
| 654 | *sample_reg = sample_div; | ||
| 655 | if (!temp_delta) | ||
| 656 | break; | ||
| 657 | } | ||
| 658 | } | ||
| 659 | return ioclk_div; | ||
| 660 | } | ||
| 661 | |||
| 662 | static unsigned int | ||
| 663 | sirfsoc_uart_calc_sample_div(unsigned long baud_rate, | ||
| 664 | unsigned long ioclk_rate, unsigned long *set_baud) | ||
| 665 | { | ||
| 666 | unsigned long min_delta = ~0UL; | ||
| 667 | unsigned short sample_div; | ||
| 668 | unsigned int regv = 0; | ||
| 669 | unsigned long ioclk_div; | ||
| 670 | unsigned long baud_tmp; | ||
| 671 | int temp_delta; | ||
| 672 | |||
| 673 | for (sample_div = SIRF_MIN_SAMPLE_DIV; | ||
| 674 | sample_div <= SIRF_MAX_SAMPLE_DIV; sample_div++) { | ||
| 675 | ioclk_div = (ioclk_rate / (baud_rate * (sample_div + 1))) - 1; | ||
| 676 | if (ioclk_div > SIRF_IOCLK_DIV_MAX) | ||
| 677 | continue; | ||
| 678 | baud_tmp = ioclk_rate / ((ioclk_div + 1) * (sample_div + 1)); | ||
| 679 | temp_delta = baud_tmp - baud_rate; | ||
| 680 | temp_delta = (temp_delta > 0) ? temp_delta : -temp_delta; | ||
| 681 | if (temp_delta < min_delta) { | ||
| 682 | regv = regv & (~SIRF_IOCLK_DIV_MASK); | ||
| 683 | regv = regv | ioclk_div; | ||
| 684 | regv = regv & (~SIRF_SAMPLE_DIV_MASK); | ||
| 685 | regv = regv | (sample_div << SIRF_SAMPLE_DIV_SHIFT); | ||
| 686 | min_delta = temp_delta; | ||
| 687 | *set_baud = baud_tmp; | ||
| 688 | } | ||
| 689 | } | ||
| 690 | return regv; | ||
| 691 | } | ||
| 692 | |||
| 693 | static void sirfsoc_uart_set_termios(struct uart_port *port, | ||
| 694 | struct ktermios *termios, | ||
| 695 | struct ktermios *old) | ||
| 696 | { | ||
| 697 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
| 698 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | ||
| 699 | struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; | ||
| 700 | unsigned long config_reg = 0; | ||
| 701 | unsigned long baud_rate; | ||
| 702 | unsigned long set_baud; | ||
| 703 | unsigned long flags; | ||
| 704 | unsigned long ic; | ||
| 705 | unsigned int clk_div_reg = 0; | ||
| 706 | unsigned long txfifo_op_reg, ioclk_rate; | ||
| 707 | unsigned long rx_time_out; | ||
| 708 | int threshold_div; | ||
| 709 | u32 data_bit_len, stop_bit_len, len_val; | ||
| 710 | unsigned long sample_div_reg = 0xf; | ||
| 711 | ioclk_rate = port->uartclk; | ||
| 712 | |||
| 713 | switch (termios->c_cflag & CSIZE) { | ||
| 714 | default: | ||
| 715 | case CS8: | ||
| 716 | data_bit_len = 8; | ||
| 717 | config_reg |= SIRFUART_DATA_BIT_LEN_8; | ||
| 718 | break; | ||
| 719 | case CS7: | ||
| 720 | data_bit_len = 7; | ||
| 721 | config_reg |= SIRFUART_DATA_BIT_LEN_7; | ||
| 722 | break; | ||
| 723 | case CS6: | ||
| 724 | data_bit_len = 6; | ||
| 725 | config_reg |= SIRFUART_DATA_BIT_LEN_6; | ||
| 726 | break; | ||
| 727 | case CS5: | ||
| 728 | data_bit_len = 5; | ||
| 729 | config_reg |= SIRFUART_DATA_BIT_LEN_5; | ||
| 730 | break; | ||
| 731 | } | ||
| 732 | if (termios->c_cflag & CSTOPB) { | ||
| 733 | config_reg |= SIRFUART_STOP_BIT_LEN_2; | ||
| 734 | stop_bit_len = 2; | ||
| 735 | } else | ||
| 736 | stop_bit_len = 1; | ||
| 737 | |||
| 738 | spin_lock_irqsave(&port->lock, flags); | ||
| 739 | port->read_status_mask = uint_en->sirfsoc_rx_oflow_en; | ||
| 740 | port->ignore_status_mask = 0; | ||
| 741 | if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { | ||
| 742 | if (termios->c_iflag & INPCK) | ||
| 743 | port->read_status_mask |= uint_en->sirfsoc_frm_err_en | | ||
| 744 | uint_en->sirfsoc_parity_err_en; | ||
| 745 | } else { | ||
| 746 | if (termios->c_iflag & INPCK) | ||
| 747 | port->read_status_mask |= uint_en->sirfsoc_frm_err_en; | ||
| 748 | } | ||
| 749 | if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) | ||
| 750 | port->read_status_mask |= uint_en->sirfsoc_rxd_brk_en; | ||
| 751 | if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { | ||
| 752 | if (termios->c_iflag & IGNPAR) | ||
| 753 | port->ignore_status_mask |= | ||
| 754 | uint_en->sirfsoc_frm_err_en | | ||
| 755 | uint_en->sirfsoc_parity_err_en; | ||
| 756 | if (termios->c_cflag & PARENB) { | ||
| 757 | if (termios->c_cflag & CMSPAR) { | ||
| 758 | if (termios->c_cflag & PARODD) | ||
| 759 | config_reg |= SIRFUART_STICK_BIT_MARK; | ||
| 760 | else | ||
| 761 | config_reg |= SIRFUART_STICK_BIT_SPACE; | ||
| 762 | } else { | ||
| 763 | if (termios->c_cflag & PARODD) | ||
| 764 | config_reg |= SIRFUART_STICK_BIT_ODD; | ||
| 765 | else | ||
| 766 | config_reg |= SIRFUART_STICK_BIT_EVEN; | ||
| 767 | } | ||
| 768 | } | ||
| 769 | } else { | ||
| 770 | if (termios->c_iflag & IGNPAR) | ||
| 771 | port->ignore_status_mask |= | ||
| 772 | uint_en->sirfsoc_frm_err_en; | ||
| 773 | if (termios->c_cflag & PARENB) | ||
| 774 | dev_warn(port->dev, | ||
| 775 | "USP-UART not support parity err\n"); | ||
| 776 | } | ||
| 777 | if (termios->c_iflag & IGNBRK) { | ||
| 778 | port->ignore_status_mask |= | ||
| 779 | uint_en->sirfsoc_rxd_brk_en; | ||
| 780 | if (termios->c_iflag & IGNPAR) | ||
| 781 | port->ignore_status_mask |= | ||
| 782 | uint_en->sirfsoc_rx_oflow_en; | ||
| 783 | } | ||
| 784 | if ((termios->c_cflag & CREAD) == 0) | ||
| 785 | port->ignore_status_mask |= SIRFUART_DUMMY_READ; | ||
| 786 | /* Hardware Flow Control Settings */ | ||
| 787 | if (UART_ENABLE_MS(port, termios->c_cflag)) { | ||
| 788 | if (!sirfport->ms_enabled) | ||
| 789 | sirfsoc_uart_enable_ms(port); | ||
| 790 | } else { | ||
| 791 | if (sirfport->ms_enabled) | ||
| 792 | sirfsoc_uart_disable_ms(port); | ||
| 793 | } | ||
| 794 | baud_rate = uart_get_baud_rate(port, termios, old, 0, 4000000); | ||
| 795 | if (ioclk_rate == 150000000) { | ||
| 796 | for (ic = 0; ic < SIRF_BAUD_RATE_SUPPORT_NR; ic++) | ||
| 797 | if (baud_rate == baudrate_to_regv[ic].baud_rate) | ||
| 798 | clk_div_reg = baudrate_to_regv[ic].reg_val; | ||
| 799 | } | ||
| 800 | set_baud = baud_rate; | ||
| 801 | if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { | ||
| 802 | if (unlikely(clk_div_reg == 0)) | ||
| 803 | clk_div_reg = sirfsoc_uart_calc_sample_div(baud_rate, | ||
| 804 | ioclk_rate, &set_baud); | ||
| 805 | wr_regl(port, ureg->sirfsoc_divisor, clk_div_reg); | ||
| 806 | } else { | ||
| 807 | clk_div_reg = sirfsoc_usp_calc_sample_div(baud_rate, | ||
| 808 | ioclk_rate, &sample_div_reg); | ||
| 809 | sample_div_reg--; | ||
| 810 | set_baud = ((ioclk_rate / (clk_div_reg+1) - 1) / | ||
| 811 | (sample_div_reg + 1)); | ||
| 812 | /* setting usp mode 2 */ | ||
| 813 | len_val = ((1 << SIRFSOC_USP_MODE2_RXD_DELAY_OFFSET) | | ||
| 814 | (1 << SIRFSOC_USP_MODE2_TXD_DELAY_OFFSET)); | ||
| 815 | len_val |= ((clk_div_reg & SIRFSOC_USP_MODE2_CLK_DIVISOR_MASK) | ||
| 816 | << SIRFSOC_USP_MODE2_CLK_DIVISOR_OFFSET); | ||
| 817 | wr_regl(port, ureg->sirfsoc_mode2, len_val); | ||
| 818 | } | ||
| 819 | if (tty_termios_baud_rate(termios)) | ||
| 820 | tty_termios_encode_baud_rate(termios, set_baud, set_baud); | ||
| 821 | /* set receive timeout && data bits len */ | ||
| 822 | rx_time_out = SIRFSOC_UART_RX_TIMEOUT(set_baud, 20000); | ||
| 823 | rx_time_out = SIRFUART_RECV_TIMEOUT_VALUE(rx_time_out); | ||
| 824 | txfifo_op_reg = rd_regl(port, ureg->sirfsoc_tx_fifo_op); | ||
| 825 | wr_regl(port, ureg->sirfsoc_tx_fifo_op, | ||
| 826 | (txfifo_op_reg & ~SIRFUART_FIFO_START)); | ||
| 827 | if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { | ||
| 828 | config_reg |= SIRFUART_UART_RECV_TIMEOUT(rx_time_out); | ||
| 829 | wr_regl(port, ureg->sirfsoc_line_ctrl, config_reg); | ||
| 830 | } else { | ||
| 831 | /*tx frame ctrl*/ | ||
| 832 | len_val = (data_bit_len - 1) << SIRFSOC_USP_TX_DATA_LEN_OFFSET; | ||
| 833 | len_val |= (data_bit_len + 1 + stop_bit_len - 1) << | ||
| 834 | SIRFSOC_USP_TX_FRAME_LEN_OFFSET; | ||
| 835 | len_val |= ((data_bit_len - 1) << | ||
| 836 | SIRFSOC_USP_TX_SHIFTER_LEN_OFFSET); | ||
| 837 | len_val |= (((clk_div_reg & 0xc00) >> 10) << | ||
| 838 | SIRFSOC_USP_TX_CLK_DIVISOR_OFFSET); | ||
| 839 | wr_regl(port, ureg->sirfsoc_tx_frame_ctrl, len_val); | ||
| 840 | /*rx frame ctrl*/ | ||
| 841 | len_val = (data_bit_len - 1) << SIRFSOC_USP_RX_DATA_LEN_OFFSET; | ||
| 842 | len_val |= (data_bit_len + 1 + stop_bit_len - 1) << | ||
| 843 | SIRFSOC_USP_RX_FRAME_LEN_OFFSET; | ||
| 844 | len_val |= (data_bit_len - 1) << | ||
| 845 | SIRFSOC_USP_RX_SHIFTER_LEN_OFFSET; | ||
| 846 | len_val |= (((clk_div_reg & 0xf000) >> 12) << | ||
| 847 | SIRFSOC_USP_RX_CLK_DIVISOR_OFFSET); | ||
| 848 | wr_regl(port, ureg->sirfsoc_rx_frame_ctrl, len_val); | ||
| 849 | /*async param*/ | ||
| 850 | wr_regl(port, ureg->sirfsoc_async_param_reg, | ||
| 851 | (SIRFUART_USP_RECV_TIMEOUT(rx_time_out)) | | ||
| 852 | (sample_div_reg & SIRFSOC_USP_ASYNC_DIV2_MASK) << | ||
| 853 | SIRFSOC_USP_ASYNC_DIV2_OFFSET); | ||
| 854 | } | ||
| 855 | if (sirfport->tx_dma_chan) | ||
| 856 | wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_DMA_MODE); | ||
| 857 | else | ||
| 858 | wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_IO_MODE); | ||
| 859 | if (sirfport->rx_dma_chan) | ||
| 860 | wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, | ||
| 861 | rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) & | ||
| 862 | ~SIRFUART_IO_MODE); | ||
| 863 | else | ||
| 864 | wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, | ||
| 865 | rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) | | ||
| 866 | SIRFUART_IO_MODE); | ||
| 867 | sirfport->rx_period_time = 20000000; | ||
| 868 | /* Reset Rx/Tx FIFO Threshold level for proper baudrate */ | ||
| 869 | if (set_baud < 1000000) | ||
| 870 | threshold_div = 1; | ||
| 871 | else | ||
| 872 | threshold_div = 2; | ||
| 873 | wr_regl(port, ureg->sirfsoc_tx_fifo_ctrl, | ||
| 874 | SIRFUART_FIFO_THD(port) / threshold_div); | ||
| 875 | wr_regl(port, ureg->sirfsoc_rx_fifo_ctrl, | ||
| 876 | SIRFUART_FIFO_THD(port) / threshold_div); | ||
| 877 | txfifo_op_reg |= SIRFUART_FIFO_START; | ||
| 878 | wr_regl(port, ureg->sirfsoc_tx_fifo_op, txfifo_op_reg); | ||
| 879 | uart_update_timeout(port, termios->c_cflag, set_baud); | ||
| 880 | wr_regl(port, ureg->sirfsoc_tx_rx_en, SIRFUART_TX_EN | SIRFUART_RX_EN); | ||
| 881 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 882 | } | ||
| 883 | |||
| 884 | static void sirfsoc_uart_pm(struct uart_port *port, unsigned int state, | ||
| 885 | unsigned int oldstate) | ||
| 886 | { | ||
| 887 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
| 888 | if (!state) | ||
| 889 | clk_prepare_enable(sirfport->clk); | ||
| 890 | else | ||
| 891 | clk_disable_unprepare(sirfport->clk); | ||
| 892 | } | ||
| 893 | |||
| 894 | static int sirfsoc_uart_startup(struct uart_port *port) | ||
| 895 | { | ||
| 896 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
| 897 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | ||
| 898 | struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; | ||
| 899 | unsigned int index = port->line; | ||
| 900 | int ret; | ||
| 901 | irq_modify_status(port->irq, IRQ_NOREQUEST, IRQ_NOAUTOEN); | ||
| 902 | ret = request_irq(port->irq, | ||
| 903 | sirfsoc_uart_isr, | ||
| 904 | 0, | ||
| 905 | SIRFUART_PORT_NAME, | ||
| 906 | sirfport); | ||
| 907 | if (ret != 0) { | ||
| 908 | dev_err(port->dev, "UART%d request IRQ line (%d) failed.\n", | ||
| 909 | index, port->irq); | ||
| 910 | goto irq_err; | ||
| 911 | } | ||
| 912 | /* initial hardware settings */ | ||
| 913 | wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, | ||
| 914 | rd_regl(port, ureg->sirfsoc_tx_dma_io_ctrl) | | ||
| 915 | SIRFUART_IO_MODE); | ||
| 916 | wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, | ||
| 917 | rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) | | ||
| 918 | SIRFUART_IO_MODE); | ||
| 919 | wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, | ||
| 920 | rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) & | ||
| 921 | ~SIRFUART_RX_DMA_FLUSH); | ||
| 922 | wr_regl(port, ureg->sirfsoc_tx_dma_io_len, 0); | ||
| 923 | wr_regl(port, ureg->sirfsoc_rx_dma_io_len, 0); | ||
| 924 | wr_regl(port, ureg->sirfsoc_tx_rx_en, SIRFUART_RX_EN | SIRFUART_TX_EN); | ||
| 925 | if (sirfport->uart_reg->uart_type == SIRF_USP_UART) | ||
| 926 | wr_regl(port, ureg->sirfsoc_mode1, | ||
| 927 | SIRFSOC_USP_ENDIAN_CTRL_LSBF | | ||
| 928 | SIRFSOC_USP_EN); | ||
| 929 | wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_RESET); | ||
| 930 | wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET); | ||
| 931 | wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0); | ||
| 932 | wr_regl(port, ureg->sirfsoc_tx_fifo_ctrl, SIRFUART_FIFO_THD(port)); | ||
| 933 | wr_regl(port, ureg->sirfsoc_rx_fifo_ctrl, SIRFUART_FIFO_THD(port)); | ||
| 934 | if (sirfport->rx_dma_chan) | ||
| 935 | wr_regl(port, ureg->sirfsoc_rx_fifo_level_chk, | ||
| 936 | SIRFUART_RX_FIFO_CHK_SC(port->line, 0x1) | | ||
| 937 | SIRFUART_RX_FIFO_CHK_LC(port->line, 0x2) | | ||
| 938 | SIRFUART_RX_FIFO_CHK_HC(port->line, 0x4)); | ||
| 939 | if (sirfport->tx_dma_chan) { | ||
| 940 | sirfport->tx_dma_state = TX_DMA_IDLE; | ||
| 941 | wr_regl(port, ureg->sirfsoc_tx_fifo_level_chk, | ||
| 942 | SIRFUART_TX_FIFO_CHK_SC(port->line, 0x1b) | | ||
| 943 | SIRFUART_TX_FIFO_CHK_LC(port->line, 0xe) | | ||
| 944 | SIRFUART_TX_FIFO_CHK_HC(port->line, 0x4)); | ||
| 945 | } | ||
| 946 | sirfport->ms_enabled = false; | ||
| 947 | if (sirfport->uart_reg->uart_type == SIRF_USP_UART && | ||
| 948 | sirfport->hw_flow_ctrl) { | ||
| 949 | irq_modify_status(gpio_to_irq(sirfport->cts_gpio), | ||
| 950 | IRQ_NOREQUEST, IRQ_NOAUTOEN); | ||
| 951 | ret = request_irq(gpio_to_irq(sirfport->cts_gpio), | ||
| 952 | sirfsoc_uart_usp_cts_handler, IRQF_TRIGGER_FALLING | | ||
| 953 | IRQF_TRIGGER_RISING, "usp_cts_irq", sirfport); | ||
| 954 | if (ret != 0) { | ||
| 955 | dev_err(port->dev, "UART-USP:request gpio irq fail\n"); | ||
| 956 | goto init_rx_err; | ||
| 957 | } | ||
| 958 | } | ||
| 959 | if (sirfport->uart_reg->uart_type == SIRF_REAL_UART && | ||
| 960 | sirfport->rx_dma_chan) | ||
| 961 | wr_regl(port, ureg->sirfsoc_swh_dma_io, | ||
| 962 | SIRFUART_CLEAR_RX_ADDR_EN); | ||
| 963 | if (sirfport->uart_reg->uart_type == SIRF_USP_UART && | ||
| 964 | sirfport->rx_dma_chan) | ||
| 965 | wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, | ||
| 966 | rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) | | ||
| 967 | SIRFSOC_USP_FRADDR_CLR_EN); | ||
| 968 | if (sirfport->rx_dma_chan && !sirfport->is_hrt_enabled) { | ||
| 969 | sirfport->is_hrt_enabled = true; | ||
| 970 | sirfport->rx_period_time = 20000000; | ||
| 971 | sirfport->rx_last_pos = -1; | ||
| 972 | sirfport->pio_fetch_cnt = 0; | ||
| 973 | sirfport->rx_dma_items.xmit.tail = | ||
| 974 | sirfport->rx_dma_items.xmit.head = 0; | ||
| 975 | hrtimer_start(&sirfport->hrt, | ||
| 976 | ns_to_ktime(sirfport->rx_period_time), | ||
| 977 | HRTIMER_MODE_REL); | ||
| 978 | } | ||
| 979 | wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START); | ||
| 980 | if (sirfport->rx_dma_chan) | ||
| 981 | sirfsoc_uart_start_next_rx_dma(port); | ||
| 982 | else { | ||
| 983 | if (!sirfport->is_atlas7) | ||
| 984 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 985 | rd_regl(port, ureg->sirfsoc_int_en_reg) | | ||
| 986 | SIRFUART_RX_IO_INT_EN(uint_en, | ||
| 987 | sirfport->uart_reg->uart_type)); | ||
| 988 | else | ||
| 989 | wr_regl(port, ureg->sirfsoc_int_en_reg, | ||
| 990 | SIRFUART_RX_IO_INT_EN(uint_en, | ||
| 991 | sirfport->uart_reg->uart_type)); | ||
| 992 | } | ||
| 993 | enable_irq(port->irq); | ||
| 994 | |||
| 995 | return 0; | ||
| 996 | init_rx_err: | ||
| 997 | free_irq(port->irq, sirfport); | ||
| 998 | irq_err: | ||
| 999 | return ret; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | static void sirfsoc_uart_shutdown(struct uart_port *port) | ||
| 1003 | { | ||
| 1004 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
| 1005 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | ||
| 1006 | struct circ_buf *xmit; | ||
| 1007 | |||
| 1008 | xmit = &sirfport->rx_dma_items.xmit; | ||
| 1009 | if (!sirfport->is_atlas7) | ||
| 1010 | wr_regl(port, ureg->sirfsoc_int_en_reg, 0); | ||
| 1011 | else | ||
| 1012 | wr_regl(port, ureg->sirfsoc_int_en_clr_reg, ~0UL); | ||
| 1013 | |||
| 1014 | free_irq(port->irq, sirfport); | ||
| 1015 | if (sirfport->ms_enabled) | ||
| 1016 | sirfsoc_uart_disable_ms(port); | ||
| 1017 | if (sirfport->uart_reg->uart_type == SIRF_USP_UART && | ||
| 1018 | sirfport->hw_flow_ctrl) { | ||
| 1019 | gpio_set_value(sirfport->rts_gpio, 1); | ||
| 1020 | free_irq(gpio_to_irq(sirfport->cts_gpio), sirfport); | ||
| 1021 | } | ||
| 1022 | if (sirfport->tx_dma_chan) | ||
| 1023 | sirfport->tx_dma_state = TX_DMA_IDLE; | ||
| 1024 | if (sirfport->rx_dma_chan && sirfport->is_hrt_enabled) { | ||
| 1025 | while (((rd_regl(port, ureg->sirfsoc_rx_fifo_status) & | ||
| 1026 | SIRFUART_RX_FIFO_MASK) > sirfport->pio_fetch_cnt) && | ||
| 1027 | !CIRC_CNT(xmit->head, xmit->tail, | ||
| 1028 | SIRFSOC_RX_DMA_BUF_SIZE)) | ||
| 1029 | ; | ||
| 1030 | sirfport->is_hrt_enabled = false; | ||
| 1031 | hrtimer_cancel(&sirfport->hrt); | ||
| 1032 | } | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | static const char *sirfsoc_uart_type(struct uart_port *port) | ||
| 1036 | { | ||
| 1037 | return port->type == SIRFSOC_PORT_TYPE ? SIRFUART_PORT_NAME : NULL; | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | static int sirfsoc_uart_request_port(struct uart_port *port) | ||
| 1041 | { | ||
| 1042 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
| 1043 | struct sirfsoc_uart_param *uart_param = &sirfport->uart_reg->uart_param; | ||
| 1044 | void *ret; | ||
| 1045 | ret = request_mem_region(port->mapbase, | ||
| 1046 | SIRFUART_MAP_SIZE, uart_param->port_name); | ||
| 1047 | return ret ? 0 : -EBUSY; | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | static void sirfsoc_uart_release_port(struct uart_port *port) | ||
| 1051 | { | ||
| 1052 | release_mem_region(port->mapbase, SIRFUART_MAP_SIZE); | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | static void sirfsoc_uart_config_port(struct uart_port *port, int flags) | ||
| 1056 | { | ||
| 1057 | if (flags & UART_CONFIG_TYPE) { | ||
| 1058 | port->type = SIRFSOC_PORT_TYPE; | ||
| 1059 | sirfsoc_uart_request_port(port); | ||
| 1060 | } | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | static const struct uart_ops sirfsoc_uart_ops = { | ||
| 1064 | .tx_empty = sirfsoc_uart_tx_empty, | ||
| 1065 | .get_mctrl = sirfsoc_uart_get_mctrl, | ||
| 1066 | .set_mctrl = sirfsoc_uart_set_mctrl, | ||
| 1067 | .stop_tx = sirfsoc_uart_stop_tx, | ||
| 1068 | .start_tx = sirfsoc_uart_start_tx, | ||
| 1069 | .stop_rx = sirfsoc_uart_stop_rx, | ||
| 1070 | .enable_ms = sirfsoc_uart_enable_ms, | ||
| 1071 | .break_ctl = sirfsoc_uart_break_ctl, | ||
| 1072 | .startup = sirfsoc_uart_startup, | ||
| 1073 | .shutdown = sirfsoc_uart_shutdown, | ||
| 1074 | .set_termios = sirfsoc_uart_set_termios, | ||
| 1075 | .pm = sirfsoc_uart_pm, | ||
| 1076 | .type = sirfsoc_uart_type, | ||
| 1077 | .release_port = sirfsoc_uart_release_port, | ||
| 1078 | .request_port = sirfsoc_uart_request_port, | ||
| 1079 | .config_port = sirfsoc_uart_config_port, | ||
| 1080 | }; | ||
| 1081 | |||
| 1082 | #ifdef CONFIG_SERIAL_SIRFSOC_CONSOLE | ||
| 1083 | static int __init | ||
| 1084 | sirfsoc_uart_console_setup(struct console *co, char *options) | ||
| 1085 | { | ||
| 1086 | unsigned int baud = 115200; | ||
| 1087 | unsigned int bits = 8; | ||
| 1088 | unsigned int parity = 'n'; | ||
| 1089 | unsigned int flow = 'n'; | ||
| 1090 | struct sirfsoc_uart_port *sirfport; | ||
| 1091 | struct sirfsoc_register *ureg; | ||
| 1092 | if (co->index < 0 || co->index >= SIRFSOC_UART_NR) | ||
| 1093 | co->index = 1; | ||
| 1094 | sirfport = sirf_ports[co->index]; | ||
| 1095 | if (!sirfport) | ||
| 1096 | return -ENODEV; | ||
| 1097 | ureg = &sirfport->uart_reg->uart_reg; | ||
| 1098 | if (!sirfport->port.mapbase) | ||
| 1099 | return -ENODEV; | ||
| 1100 | |||
| 1101 | /* enable usp in mode1 register */ | ||
| 1102 | if (sirfport->uart_reg->uart_type == SIRF_USP_UART) | ||
| 1103 | wr_regl(&sirfport->port, ureg->sirfsoc_mode1, SIRFSOC_USP_EN | | ||
| 1104 | SIRFSOC_USP_ENDIAN_CTRL_LSBF); | ||
| 1105 | if (options) | ||
| 1106 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
| 1107 | sirfport->port.cons = co; | ||
| 1108 | |||
| 1109 | /* default console tx/rx transfer using io mode */ | ||
| 1110 | sirfport->rx_dma_chan = NULL; | ||
| 1111 | sirfport->tx_dma_chan = NULL; | ||
| 1112 | return uart_set_options(&sirfport->port, co, baud, parity, bits, flow); | ||
| 1113 | } | ||
| 1114 | |||
| 1115 | static void sirfsoc_uart_console_putchar(struct uart_port *port, int ch) | ||
| 1116 | { | ||
| 1117 | struct sirfsoc_uart_port *sirfport = to_sirfport(port); | ||
| 1118 | struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; | ||
| 1119 | struct sirfsoc_fifo_status *ufifo_st = &sirfport->uart_reg->fifo_status; | ||
| 1120 | while (rd_regl(port, ureg->sirfsoc_tx_fifo_status) & | ||
| 1121 | ufifo_st->ff_full(port)) | ||
| 1122 | cpu_relax(); | ||
| 1123 | wr_regl(port, ureg->sirfsoc_tx_fifo_data, ch); | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | static void sirfsoc_uart_console_write(struct console *co, const char *s, | ||
| 1127 | unsigned int count) | ||
| 1128 | { | ||
| 1129 | struct sirfsoc_uart_port *sirfport = sirf_ports[co->index]; | ||
| 1130 | |||
| 1131 | uart_console_write(&sirfport->port, s, count, | ||
| 1132 | sirfsoc_uart_console_putchar); | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | static struct console sirfsoc_uart_console = { | ||
| 1136 | .name = SIRFSOC_UART_NAME, | ||
| 1137 | .device = uart_console_device, | ||
| 1138 | .flags = CON_PRINTBUFFER, | ||
| 1139 | .index = -1, | ||
| 1140 | .write = sirfsoc_uart_console_write, | ||
| 1141 | .setup = sirfsoc_uart_console_setup, | ||
| 1142 | .data = &sirfsoc_uart_drv, | ||
| 1143 | }; | ||
| 1144 | |||
| 1145 | static int __init sirfsoc_uart_console_init(void) | ||
| 1146 | { | ||
| 1147 | register_console(&sirfsoc_uart_console); | ||
| 1148 | return 0; | ||
| 1149 | } | ||
| 1150 | console_initcall(sirfsoc_uart_console_init); | ||
| 1151 | #endif | ||
| 1152 | |||
| 1153 | static struct uart_driver sirfsoc_uart_drv = { | ||
| 1154 | .owner = THIS_MODULE, | ||
| 1155 | .driver_name = SIRFUART_PORT_NAME, | ||
| 1156 | .nr = SIRFSOC_UART_NR, | ||
| 1157 | .dev_name = SIRFSOC_UART_NAME, | ||
| 1158 | .major = SIRFSOC_UART_MAJOR, | ||
| 1159 | .minor = SIRFSOC_UART_MINOR, | ||
| 1160 | #ifdef CONFIG_SERIAL_SIRFSOC_CONSOLE | ||
| 1161 | .cons = &sirfsoc_uart_console, | ||
| 1162 | #else | ||
| 1163 | .cons = NULL, | ||
| 1164 | #endif | ||
| 1165 | }; | ||
| 1166 | |||
| 1167 | static enum hrtimer_restart | ||
| 1168 | sirfsoc_uart_rx_dma_hrtimer_callback(struct hrtimer *hrt) | ||
| 1169 | { | ||
| 1170 | struct sirfsoc_uart_port *sirfport; | ||
| 1171 | struct uart_port *port; | ||
| 1172 | int count, inserted; | ||
| 1173 | struct dma_tx_state tx_state; | ||
| 1174 | struct tty_struct *tty; | ||
| 1175 | struct sirfsoc_register *ureg; | ||
| 1176 | struct circ_buf *xmit; | ||
| 1177 | struct sirfsoc_fifo_status *ufifo_st; | ||
| 1178 | int max_pio_cnt; | ||
| 1179 | |||
| 1180 | sirfport = container_of(hrt, struct sirfsoc_uart_port, hrt); | ||
| 1181 | port = &sirfport->port; | ||
| 1182 | inserted = 0; | ||
| 1183 | tty = port->state->port.tty; | ||
| 1184 | ureg = &sirfport->uart_reg->uart_reg; | ||
| 1185 | xmit = &sirfport->rx_dma_items.xmit; | ||
| 1186 | ufifo_st = &sirfport->uart_reg->fifo_status; | ||
| 1187 | |||
| 1188 | dmaengine_tx_status(sirfport->rx_dma_chan, | ||
| 1189 | sirfport->rx_dma_items.cookie, &tx_state); | ||
| 1190 | if (SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue != | ||
| 1191 | sirfport->rx_last_pos) { | ||
| 1192 | xmit->head = SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue; | ||
| 1193 | sirfport->rx_last_pos = xmit->head; | ||
| 1194 | sirfport->pio_fetch_cnt = 0; | ||
| 1195 | } | ||
| 1196 | count = CIRC_CNT_TO_END(xmit->head, xmit->tail, | ||
| 1197 | SIRFSOC_RX_DMA_BUF_SIZE); | ||
| 1198 | while (count > 0) { | ||
| 1199 | inserted = tty_insert_flip_string(tty->port, | ||
| 1200 | (const unsigned char *)&xmit->buf[xmit->tail], count); | ||
| 1201 | if (!inserted) | ||
| 1202 | goto next_hrt; | ||
| 1203 | port->icount.rx += inserted; | ||
| 1204 | xmit->tail = (xmit->tail + inserted) & | ||
| 1205 | (SIRFSOC_RX_DMA_BUF_SIZE - 1); | ||
| 1206 | count = CIRC_CNT_TO_END(xmit->head, xmit->tail, | ||
| 1207 | SIRFSOC_RX_DMA_BUF_SIZE); | ||
| 1208 | tty_flip_buffer_push(tty->port); | ||
| 1209 | } | ||
| 1210 | /* | ||
| 1211 | * if RX DMA buffer data have all push into tty buffer, and there is | ||
| 1212 | * only little data(less than a dma transfer unit) left in rxfifo, | ||
| 1213 | * fetch it out in pio mode and switch back to dma immediately | ||
| 1214 | */ | ||
| 1215 | if (!inserted && !count && | ||
| 1216 | ((rd_regl(port, ureg->sirfsoc_rx_fifo_status) & | ||
| 1217 | SIRFUART_RX_FIFO_MASK) > sirfport->pio_fetch_cnt)) { | ||
| 1218 | dmaengine_pause(sirfport->rx_dma_chan); | ||
| 1219 | /* switch to pio mode */ | ||
| 1220 | wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, | ||
| 1221 | rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) | | ||
| 1222 | SIRFUART_IO_MODE); | ||
| 1223 | /* | ||
| 1224 | * UART controller SWH_DMA_IO register have CLEAR_RX_ADDR_EN | ||
| 1225 | * When found changing I/O to DMA mode, it clears | ||
| 1226 | * two low bits of read point; | ||
| 1227 | * USP have similar FRADDR_CLR_EN bit in USP_RX_DMA_IO_CTRL. | ||
| 1228 | * Fetch data out from rxfifo into DMA buffer in PIO mode, | ||
| 1229 | * while switch back to DMA mode, the data fetched will override | ||
| 1230 | * by DMA, as hardware have a strange behaviour: | ||
| 1231 | * after switch back to DMA mode, check rxfifo status it will | ||
| 1232 | * be the number PIO fetched, so record the fetched data count | ||
| 1233 | * to avoid the repeated fetch | ||
| 1234 | */ | ||
| 1235 | max_pio_cnt = 3; | ||
| 1236 | while (!(rd_regl(port, ureg->sirfsoc_rx_fifo_status) & | ||
| 1237 | ufifo_st->ff_empty(port)) && max_pio_cnt--) { | ||
| 1238 | xmit->buf[xmit->head] = | ||
| 1239 | rd_regl(port, ureg->sirfsoc_rx_fifo_data); | ||
| 1240 | xmit->head = (xmit->head + 1) & | ||
| 1241 | (SIRFSOC_RX_DMA_BUF_SIZE - 1); | ||
| 1242 | sirfport->pio_fetch_cnt++; | ||
| 1243 | } | ||
| 1244 | /* switch back to dma mode */ | ||
| 1245 | wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, | ||
| 1246 | rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) & | ||
| 1247 | ~SIRFUART_IO_MODE); | ||
| 1248 | dmaengine_resume(sirfport->rx_dma_chan); | ||
| 1249 | } | ||
| 1250 | next_hrt: | ||
| 1251 | hrtimer_forward_now(hrt, ns_to_ktime(sirfport->rx_period_time)); | ||
| 1252 | return HRTIMER_RESTART; | ||
| 1253 | } | ||
| 1254 | |||
| 1255 | static const struct of_device_id sirfsoc_uart_ids[] = { | ||
| 1256 | { .compatible = "sirf,prima2-uart", .data = &sirfsoc_uart,}, | ||
| 1257 | { .compatible = "sirf,atlas7-uart", .data = &sirfsoc_uart}, | ||
| 1258 | { .compatible = "sirf,prima2-usp-uart", .data = &sirfsoc_usp}, | ||
| 1259 | { .compatible = "sirf,atlas7-usp-uart", .data = &sirfsoc_usp}, | ||
| 1260 | {} | ||
| 1261 | }; | ||
| 1262 | MODULE_DEVICE_TABLE(of, sirfsoc_uart_ids); | ||
| 1263 | |||
| 1264 | static int sirfsoc_uart_probe(struct platform_device *pdev) | ||
| 1265 | { | ||
| 1266 | struct device_node *np = pdev->dev.of_node; | ||
| 1267 | struct sirfsoc_uart_port *sirfport; | ||
| 1268 | struct uart_port *port; | ||
| 1269 | struct resource *res; | ||
| 1270 | int ret; | ||
| 1271 | struct dma_slave_config slv_cfg = { | ||
| 1272 | .src_maxburst = 1, | ||
| 1273 | }; | ||
| 1274 | struct dma_slave_config tx_slv_cfg = { | ||
| 1275 | .dst_maxburst = 2, | ||
| 1276 | }; | ||
| 1277 | const struct of_device_id *match; | ||
| 1278 | |||
| 1279 | match = of_match_node(sirfsoc_uart_ids, np); | ||
| 1280 | sirfport = devm_kzalloc(&pdev->dev, sizeof(*sirfport), GFP_KERNEL); | ||
| 1281 | if (!sirfport) { | ||
| 1282 | ret = -ENOMEM; | ||
| 1283 | goto err; | ||
| 1284 | } | ||
| 1285 | sirfport->port.line = of_alias_get_id(np, "serial"); | ||
| 1286 | if (sirfport->port.line >= ARRAY_SIZE(sirf_ports)) { | ||
| 1287 | dev_err(&pdev->dev, "serial%d out of range\n", | ||
| 1288 | sirfport->port.line); | ||
| 1289 | return -EINVAL; | ||
| 1290 | } | ||
| 1291 | sirf_ports[sirfport->port.line] = sirfport; | ||
| 1292 | sirfport->port.iotype = UPIO_MEM; | ||
| 1293 | sirfport->port.flags = UPF_BOOT_AUTOCONF; | ||
| 1294 | port = &sirfport->port; | ||
| 1295 | port->dev = &pdev->dev; | ||
| 1296 | port->private_data = sirfport; | ||
| 1297 | sirfport->uart_reg = (struct sirfsoc_uart_register *)match->data; | ||
| 1298 | |||
| 1299 | sirfport->hw_flow_ctrl = | ||
| 1300 | of_property_read_bool(np, "uart-has-rtscts") || | ||
| 1301 | of_property_read_bool(np, "sirf,uart-has-rtscts") /* deprecated */; | ||
| 1302 | if (of_device_is_compatible(np, "sirf,prima2-uart") || | ||
| 1303 | of_device_is_compatible(np, "sirf,atlas7-uart")) | ||
| 1304 | sirfport->uart_reg->uart_type = SIRF_REAL_UART; | ||
| 1305 | if (of_device_is_compatible(np, "sirf,prima2-usp-uart") || | ||
| 1306 | of_device_is_compatible(np, "sirf,atlas7-usp-uart")) { | ||
| 1307 | sirfport->uart_reg->uart_type = SIRF_USP_UART; | ||
| 1308 | if (!sirfport->hw_flow_ctrl) | ||
| 1309 | goto usp_no_flow_control; | ||
| 1310 | if (of_find_property(np, "cts-gpios", NULL)) | ||
| 1311 | sirfport->cts_gpio = | ||
| 1312 | of_get_named_gpio(np, "cts-gpios", 0); | ||
| 1313 | else | ||
| 1314 | sirfport->cts_gpio = -1; | ||
| 1315 | if (of_find_property(np, "rts-gpios", NULL)) | ||
| 1316 | sirfport->rts_gpio = | ||
| 1317 | of_get_named_gpio(np, "rts-gpios", 0); | ||
| 1318 | else | ||
| 1319 | sirfport->rts_gpio = -1; | ||
| 1320 | |||
| 1321 | if ((!gpio_is_valid(sirfport->cts_gpio) || | ||
| 1322 | !gpio_is_valid(sirfport->rts_gpio))) { | ||
| 1323 | ret = -EINVAL; | ||
| 1324 | dev_err(&pdev->dev, | ||
| 1325 | "Usp flow control must have cts and rts gpio"); | ||
| 1326 | goto err; | ||
| 1327 | } | ||
| 1328 | ret = devm_gpio_request(&pdev->dev, sirfport->cts_gpio, | ||
| 1329 | "usp-cts-gpio"); | ||
| 1330 | if (ret) { | ||
| 1331 | dev_err(&pdev->dev, "Unable request cts gpio"); | ||
| 1332 | goto err; | ||
| 1333 | } | ||
| 1334 | gpio_direction_input(sirfport->cts_gpio); | ||
| 1335 | ret = devm_gpio_request(&pdev->dev, sirfport->rts_gpio, | ||
| 1336 | "usp-rts-gpio"); | ||
| 1337 | if (ret) { | ||
| 1338 | dev_err(&pdev->dev, "Unable request rts gpio"); | ||
| 1339 | goto err; | ||
| 1340 | } | ||
| 1341 | gpio_direction_output(sirfport->rts_gpio, 1); | ||
| 1342 | } | ||
| 1343 | usp_no_flow_control: | ||
| 1344 | if (of_device_is_compatible(np, "sirf,atlas7-uart") || | ||
| 1345 | of_device_is_compatible(np, "sirf,atlas7-usp-uart")) | ||
| 1346 | sirfport->is_atlas7 = true; | ||
| 1347 | |||
| 1348 | if (of_property_read_u32(np, "fifosize", &port->fifosize)) { | ||
| 1349 | dev_err(&pdev->dev, | ||
| 1350 | "Unable to find fifosize in uart node.\n"); | ||
| 1351 | ret = -EFAULT; | ||
| 1352 | goto err; | ||
| 1353 | } | ||
| 1354 | |||
| 1355 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 1356 | if (res == NULL) { | ||
| 1357 | dev_err(&pdev->dev, "Insufficient resources.\n"); | ||
| 1358 | ret = -EFAULT; | ||
| 1359 | goto err; | ||
| 1360 | } | ||
| 1361 | port->mapbase = res->start; | ||
| 1362 | port->membase = devm_ioremap(&pdev->dev, | ||
| 1363 | res->start, resource_size(res)); | ||
| 1364 | if (!port->membase) { | ||
| 1365 | dev_err(&pdev->dev, "Cannot remap resource.\n"); | ||
| 1366 | ret = -ENOMEM; | ||
| 1367 | goto err; | ||
| 1368 | } | ||
| 1369 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
| 1370 | if (res == NULL) { | ||
| 1371 | dev_err(&pdev->dev, "Insufficient resources.\n"); | ||
| 1372 | ret = -EFAULT; | ||
| 1373 | goto err; | ||
| 1374 | } | ||
| 1375 | port->irq = res->start; | ||
| 1376 | |||
| 1377 | sirfport->clk = devm_clk_get(&pdev->dev, NULL); | ||
| 1378 | if (IS_ERR(sirfport->clk)) { | ||
| 1379 | ret = PTR_ERR(sirfport->clk); | ||
| 1380 | goto err; | ||
| 1381 | } | ||
| 1382 | port->uartclk = clk_get_rate(sirfport->clk); | ||
| 1383 | |||
| 1384 | port->ops = &sirfsoc_uart_ops; | ||
| 1385 | spin_lock_init(&port->lock); | ||
| 1386 | |||
| 1387 | platform_set_drvdata(pdev, sirfport); | ||
| 1388 | ret = uart_add_one_port(&sirfsoc_uart_drv, port); | ||
| 1389 | if (ret != 0) { | ||
| 1390 | dev_err(&pdev->dev, "Cannot add UART port(%d).\n", pdev->id); | ||
| 1391 | goto err; | ||
| 1392 | } | ||
| 1393 | |||
| 1394 | sirfport->rx_dma_chan = dma_request_slave_channel(port->dev, "rx"); | ||
| 1395 | sirfport->rx_dma_items.xmit.buf = | ||
| 1396 | dma_alloc_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE, | ||
| 1397 | &sirfport->rx_dma_items.dma_addr, GFP_KERNEL); | ||
| 1398 | if (!sirfport->rx_dma_items.xmit.buf) { | ||
| 1399 | dev_err(port->dev, "Uart alloc bufa failed\n"); | ||
| 1400 | ret = -ENOMEM; | ||
| 1401 | goto alloc_coherent_err; | ||
| 1402 | } | ||
| 1403 | sirfport->rx_dma_items.xmit.head = | ||
| 1404 | sirfport->rx_dma_items.xmit.tail = 0; | ||
| 1405 | if (sirfport->rx_dma_chan) | ||
| 1406 | dmaengine_slave_config(sirfport->rx_dma_chan, &slv_cfg); | ||
| 1407 | sirfport->tx_dma_chan = dma_request_slave_channel(port->dev, "tx"); | ||
| 1408 | if (sirfport->tx_dma_chan) | ||
| 1409 | dmaengine_slave_config(sirfport->tx_dma_chan, &tx_slv_cfg); | ||
| 1410 | if (sirfport->rx_dma_chan) { | ||
| 1411 | hrtimer_init(&sirfport->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | ||
| 1412 | sirfport->hrt.function = sirfsoc_uart_rx_dma_hrtimer_callback; | ||
| 1413 | sirfport->is_hrt_enabled = false; | ||
| 1414 | } | ||
| 1415 | |||
| 1416 | return 0; | ||
| 1417 | alloc_coherent_err: | ||
| 1418 | dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE, | ||
| 1419 | sirfport->rx_dma_items.xmit.buf, | ||
| 1420 | sirfport->rx_dma_items.dma_addr); | ||
| 1421 | dma_release_channel(sirfport->rx_dma_chan); | ||
| 1422 | err: | ||
| 1423 | return ret; | ||
| 1424 | } | ||
| 1425 | |||
| 1426 | static int sirfsoc_uart_remove(struct platform_device *pdev) | ||
| 1427 | { | ||
| 1428 | struct sirfsoc_uart_port *sirfport = platform_get_drvdata(pdev); | ||
| 1429 | struct uart_port *port = &sirfport->port; | ||
| 1430 | uart_remove_one_port(&sirfsoc_uart_drv, port); | ||
| 1431 | if (sirfport->rx_dma_chan) { | ||
| 1432 | dmaengine_terminate_all(sirfport->rx_dma_chan); | ||
| 1433 | dma_release_channel(sirfport->rx_dma_chan); | ||
| 1434 | dma_free_coherent(port->dev, SIRFSOC_RX_DMA_BUF_SIZE, | ||
| 1435 | sirfport->rx_dma_items.xmit.buf, | ||
| 1436 | sirfport->rx_dma_items.dma_addr); | ||
| 1437 | } | ||
| 1438 | if (sirfport->tx_dma_chan) { | ||
| 1439 | dmaengine_terminate_all(sirfport->tx_dma_chan); | ||
| 1440 | dma_release_channel(sirfport->tx_dma_chan); | ||
| 1441 | } | ||
| 1442 | return 0; | ||
| 1443 | } | ||
| 1444 | |||
| 1445 | #ifdef CONFIG_PM_SLEEP | ||
| 1446 | static int | ||
| 1447 | sirfsoc_uart_suspend(struct device *pdev) | ||
| 1448 | { | ||
| 1449 | struct sirfsoc_uart_port *sirfport = dev_get_drvdata(pdev); | ||
| 1450 | struct uart_port *port = &sirfport->port; | ||
| 1451 | uart_suspend_port(&sirfsoc_uart_drv, port); | ||
| 1452 | return 0; | ||
| 1453 | } | ||
| 1454 | |||
| 1455 | static int sirfsoc_uart_resume(struct device *pdev) | ||
| 1456 | { | ||
| 1457 | struct sirfsoc_uart_port *sirfport = dev_get_drvdata(pdev); | ||
| 1458 | struct uart_port *port = &sirfport->port; | ||
| 1459 | uart_resume_port(&sirfsoc_uart_drv, port); | ||
| 1460 | return 0; | ||
| 1461 | } | ||
| 1462 | #endif | ||
| 1463 | |||
| 1464 | static const struct dev_pm_ops sirfsoc_uart_pm_ops = { | ||
| 1465 | SET_SYSTEM_SLEEP_PM_OPS(sirfsoc_uart_suspend, sirfsoc_uart_resume) | ||
| 1466 | }; | ||
| 1467 | |||
| 1468 | static struct platform_driver sirfsoc_uart_driver = { | ||
| 1469 | .probe = sirfsoc_uart_probe, | ||
| 1470 | .remove = sirfsoc_uart_remove, | ||
| 1471 | .driver = { | ||
| 1472 | .name = SIRFUART_PORT_NAME, | ||
| 1473 | .of_match_table = sirfsoc_uart_ids, | ||
| 1474 | .pm = &sirfsoc_uart_pm_ops, | ||
| 1475 | }, | ||
| 1476 | }; | ||
| 1477 | |||
| 1478 | static int __init sirfsoc_uart_init(void) | ||
| 1479 | { | ||
| 1480 | int ret = 0; | ||
| 1481 | |||
| 1482 | ret = uart_register_driver(&sirfsoc_uart_drv); | ||
| 1483 | if (ret) | ||
| 1484 | goto out; | ||
| 1485 | |||
| 1486 | ret = platform_driver_register(&sirfsoc_uart_driver); | ||
| 1487 | if (ret) | ||
| 1488 | uart_unregister_driver(&sirfsoc_uart_drv); | ||
| 1489 | out: | ||
| 1490 | return ret; | ||
| 1491 | } | ||
| 1492 | module_init(sirfsoc_uart_init); | ||
| 1493 | |||
| 1494 | static void __exit sirfsoc_uart_exit(void) | ||
| 1495 | { | ||
| 1496 | platform_driver_unregister(&sirfsoc_uart_driver); | ||
| 1497 | uart_unregister_driver(&sirfsoc_uart_drv); | ||
| 1498 | } | ||
| 1499 | module_exit(sirfsoc_uart_exit); | ||
| 1500 | |||
| 1501 | MODULE_LICENSE("GPL v2"); | ||
| 1502 | MODULE_AUTHOR("Bin Shi <Bin.Shi@csr.com>, Rong Wang<Rong.Wang@csr.com>"); | ||
| 1503 | MODULE_DESCRIPTION("CSR SiRFprimaII Uart Driver"); | ||
| @@ -1,447 +0,0 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0+ */ | ||
| 2 | /* | ||
| 3 | * Drivers for CSR SiRFprimaII onboard UARTs. | ||
| 4 | * | ||
| 5 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | ||
| 6 | */ | ||
| 7 | #include <linux/bitops.h> | ||
| 8 | #include <linux/log2.h> | ||
| 9 | #include <linux/hrtimer.h> | ||
| 10 | struct sirfsoc_uart_param { | ||
| 11 | const char *uart_name; | ||
| 12 | const char *port_name; | ||
| 13 | }; | ||
| 14 | |||
| 15 | struct sirfsoc_register { | ||
| 16 | /* hardware uart specific */ | ||
| 17 | u32 sirfsoc_line_ctrl; | ||
| 18 | u32 sirfsoc_divisor; | ||
| 19 | /* uart - usp common */ | ||
| 20 | u32 sirfsoc_tx_rx_en; | ||
| 21 | u32 sirfsoc_int_en_reg; | ||
| 22 | u32 sirfsoc_int_st_reg; | ||
| 23 | u32 sirfsoc_int_en_clr_reg; | ||
| 24 | u32 sirfsoc_tx_dma_io_ctrl; | ||
| 25 | u32 sirfsoc_tx_dma_io_len; | ||
| 26 | u32 sirfsoc_tx_fifo_ctrl; | ||
| 27 | u32 sirfsoc_tx_fifo_level_chk; | ||
| 28 | u32 sirfsoc_tx_fifo_op; | ||
| 29 | u32 sirfsoc_tx_fifo_status; | ||
| 30 | u32 sirfsoc_tx_fifo_data; | ||
| 31 | u32 sirfsoc_rx_dma_io_ctrl; | ||
| 32 | u32 sirfsoc_rx_dma_io_len; | ||
| 33 | u32 sirfsoc_rx_fifo_ctrl; | ||
| 34 | u32 sirfsoc_rx_fifo_level_chk; | ||
| 35 | u32 sirfsoc_rx_fifo_op; | ||
| 36 | u32 sirfsoc_rx_fifo_status; | ||
| 37 | u32 sirfsoc_rx_fifo_data; | ||
| 38 | u32 sirfsoc_afc_ctrl; | ||
| 39 | u32 sirfsoc_swh_dma_io; | ||
| 40 | /* hardware usp specific */ | ||
| 41 | u32 sirfsoc_mode1; | ||
| 42 | u32 sirfsoc_mode2; | ||
| 43 | u32 sirfsoc_tx_frame_ctrl; | ||
| 44 | u32 sirfsoc_rx_frame_ctrl; | ||
| 45 | u32 sirfsoc_async_param_reg; | ||
| 46 | }; | ||
| 47 | |||
| 48 | typedef u32 (*fifo_full_mask)(struct uart_port *port); | ||
| 49 | typedef u32 (*fifo_empty_mask)(struct uart_port *port); | ||
| 50 | |||
| 51 | struct sirfsoc_fifo_status { | ||
| 52 | fifo_full_mask ff_full; | ||
| 53 | fifo_empty_mask ff_empty; | ||
| 54 | }; | ||
| 55 | |||
| 56 | struct sirfsoc_int_en { | ||
| 57 | u32 sirfsoc_rx_done_en; | ||
| 58 | u32 sirfsoc_tx_done_en; | ||
| 59 | u32 sirfsoc_rx_oflow_en; | ||
| 60 | u32 sirfsoc_tx_allout_en; | ||
| 61 | u32 sirfsoc_rx_io_dma_en; | ||
| 62 | u32 sirfsoc_tx_io_dma_en; | ||
| 63 | u32 sirfsoc_rxfifo_full_en; | ||
| 64 | u32 sirfsoc_txfifo_empty_en; | ||
| 65 | u32 sirfsoc_rxfifo_thd_en; | ||
| 66 | u32 sirfsoc_txfifo_thd_en; | ||
| 67 | u32 sirfsoc_frm_err_en; | ||
| 68 | u32 sirfsoc_rxd_brk_en; | ||
| 69 | u32 sirfsoc_rx_timeout_en; | ||
| 70 | u32 sirfsoc_parity_err_en; | ||
| 71 | u32 sirfsoc_cts_en; | ||
| 72 | u32 sirfsoc_rts_en; | ||
| 73 | }; | ||
| 74 | |||
| 75 | struct sirfsoc_int_status { | ||
| 76 | u32 sirfsoc_rx_done; | ||
| 77 | u32 sirfsoc_tx_done; | ||
| 78 | u32 sirfsoc_rx_oflow; | ||
| 79 | u32 sirfsoc_tx_allout; | ||
| 80 | u32 sirfsoc_rx_io_dma; | ||
| 81 | u32 sirfsoc_tx_io_dma; | ||
| 82 | u32 sirfsoc_rxfifo_full; | ||
| 83 | u32 sirfsoc_txfifo_empty; | ||
| 84 | u32 sirfsoc_rxfifo_thd; | ||
| 85 | u32 sirfsoc_txfifo_thd; | ||
| 86 | u32 sirfsoc_frm_err; | ||
| 87 | u32 sirfsoc_rxd_brk; | ||
| 88 | u32 sirfsoc_rx_timeout; | ||
| 89 | u32 sirfsoc_parity_err; | ||
| 90 | u32 sirfsoc_cts; | ||
| 91 | u32 sirfsoc_rts; | ||
| 92 | }; | ||
| 93 | |||
| 94 | enum sirfsoc_uart_type { | ||
| 95 | SIRF_REAL_UART, | ||
| 96 | SIRF_USP_UART, | ||
| 97 | }; | ||
| 98 | |||
| 99 | struct sirfsoc_uart_register { | ||
| 100 | struct sirfsoc_register uart_reg; | ||
| 101 | struct sirfsoc_int_en uart_int_en; | ||
| 102 | struct sirfsoc_int_status uart_int_st; | ||
| 103 | struct sirfsoc_fifo_status fifo_status; | ||
| 104 | struct sirfsoc_uart_param uart_param; | ||
| 105 | enum sirfsoc_uart_type uart_type; | ||
| 106 | }; | ||
| 107 | |||
| 108 | static u32 uart_usp_ff_full_mask(struct uart_port *port) | ||
| 109 | { | ||
| 110 | u32 full_bit; | ||
| 111 | |||
| 112 | full_bit = ilog2(port->fifosize); | ||
| 113 | return (1 << full_bit); | ||
| 114 | } | ||
| 115 | |||
| 116 | static u32 uart_usp_ff_empty_mask(struct uart_port *port) | ||
| 117 | { | ||
| 118 | u32 empty_bit; | ||
| 119 | |||
| 120 | empty_bit = ilog2(port->fifosize) + 1; | ||
| 121 | return (1 << empty_bit); | ||
| 122 | } | ||
| 123 | |||
| 124 | static struct sirfsoc_uart_register sirfsoc_usp = { | ||
| 125 | .uart_reg = { | ||
| 126 | .sirfsoc_mode1 = 0x0000, | ||
| 127 | .sirfsoc_mode2 = 0x0004, | ||
| 128 | .sirfsoc_tx_frame_ctrl = 0x0008, | ||
| 129 | .sirfsoc_rx_frame_ctrl = 0x000c, | ||
| 130 | .sirfsoc_tx_rx_en = 0x0010, | ||
| 131 | .sirfsoc_int_en_reg = 0x0014, | ||
| 132 | .sirfsoc_int_st_reg = 0x0018, | ||
| 133 | .sirfsoc_async_param_reg = 0x0024, | ||
| 134 | .sirfsoc_tx_dma_io_ctrl = 0x0100, | ||
| 135 | .sirfsoc_tx_dma_io_len = 0x0104, | ||
| 136 | .sirfsoc_tx_fifo_ctrl = 0x0108, | ||
| 137 | .sirfsoc_tx_fifo_level_chk = 0x010c, | ||
| 138 | .sirfsoc_tx_fifo_op = 0x0110, | ||
| 139 | .sirfsoc_tx_fifo_status = 0x0114, | ||
| 140 | .sirfsoc_tx_fifo_data = 0x0118, | ||
| 141 | .sirfsoc_rx_dma_io_ctrl = 0x0120, | ||
| 142 | .sirfsoc_rx_dma_io_len = 0x0124, | ||
| 143 | .sirfsoc_rx_fifo_ctrl = 0x0128, | ||
| 144 | .sirfsoc_rx_fifo_level_chk = 0x012c, | ||
| 145 | .sirfsoc_rx_fifo_op = 0x0130, | ||
| 146 | .sirfsoc_rx_fifo_status = 0x0134, | ||
| 147 | .sirfsoc_rx_fifo_data = 0x0138, | ||
| 148 | .sirfsoc_int_en_clr_reg = 0x140, | ||
| 149 | }, | ||
| 150 | .uart_int_en = { | ||
| 151 | .sirfsoc_rx_done_en = BIT(0), | ||
| 152 | .sirfsoc_tx_done_en = BIT(1), | ||
| 153 | .sirfsoc_rx_oflow_en = BIT(2), | ||
| 154 | .sirfsoc_tx_allout_en = BIT(3), | ||
| 155 | .sirfsoc_rx_io_dma_en = BIT(4), | ||
| 156 | .sirfsoc_tx_io_dma_en = BIT(5), | ||
| 157 | .sirfsoc_rxfifo_full_en = BIT(6), | ||
| 158 | .sirfsoc_txfifo_empty_en = BIT(7), | ||
| 159 | .sirfsoc_rxfifo_thd_en = BIT(8), | ||
| 160 | .sirfsoc_txfifo_thd_en = BIT(9), | ||
| 161 | .sirfsoc_frm_err_en = BIT(10), | ||
| 162 | .sirfsoc_rx_timeout_en = BIT(11), | ||
| 163 | .sirfsoc_rxd_brk_en = BIT(15), | ||
| 164 | }, | ||
| 165 | .uart_int_st = { | ||
| 166 | .sirfsoc_rx_done = BIT(0), | ||
| 167 | .sirfsoc_tx_done = BIT(1), | ||
| 168 | .sirfsoc_rx_oflow = BIT(2), | ||
| 169 | .sirfsoc_tx_allout = BIT(3), | ||
| 170 | .sirfsoc_rx_io_dma = BIT(4), | ||
| 171 | .sirfsoc_tx_io_dma = BIT(5), | ||
| 172 | .sirfsoc_rxfifo_full = BIT(6), | ||
| 173 | .sirfsoc_txfifo_empty = BIT(7), | ||
| 174 | .sirfsoc_rxfifo_thd = BIT(8), | ||
| 175 | .sirfsoc_txfifo_thd = BIT(9), | ||
| 176 | .sirfsoc_frm_err = BIT(10), | ||
| 177 | .sirfsoc_rx_timeout = BIT(11), | ||
| 178 | .sirfsoc_rxd_brk = BIT(15), | ||
| 179 | }, | ||
| 180 | .fifo_status = { | ||
| 181 | .ff_full = uart_usp_ff_full_mask, | ||
| 182 | .ff_empty = uart_usp_ff_empty_mask, | ||
| 183 | }, | ||
| 184 | .uart_param = { | ||
| 185 | .uart_name = "ttySiRF", | ||
| 186 | .port_name = "sirfsoc-uart", | ||
| 187 | }, | ||
| 188 | }; | ||
| 189 | |||
| 190 | static struct sirfsoc_uart_register sirfsoc_uart = { | ||
| 191 | .uart_reg = { | ||
| 192 | .sirfsoc_line_ctrl = 0x0040, | ||
| 193 | .sirfsoc_tx_rx_en = 0x004c, | ||
| 194 | .sirfsoc_divisor = 0x0050, | ||
| 195 | .sirfsoc_int_en_reg = 0x0054, | ||
| 196 | .sirfsoc_int_st_reg = 0x0058, | ||
| 197 | .sirfsoc_int_en_clr_reg = 0x0060, | ||
| 198 | .sirfsoc_tx_dma_io_ctrl = 0x0100, | ||
| 199 | .sirfsoc_tx_dma_io_len = 0x0104, | ||
| 200 | .sirfsoc_tx_fifo_ctrl = 0x0108, | ||
| 201 | .sirfsoc_tx_fifo_level_chk = 0x010c, | ||
| 202 | .sirfsoc_tx_fifo_op = 0x0110, | ||
| 203 | .sirfsoc_tx_fifo_status = 0x0114, | ||
| 204 | .sirfsoc_tx_fifo_data = 0x0118, | ||
| 205 | .sirfsoc_rx_dma_io_ctrl = 0x0120, | ||
| 206 | .sirfsoc_rx_dma_io_len = 0x0124, | ||
| 207 | .sirfsoc_rx_fifo_ctrl = 0x0128, | ||
| 208 | .sirfsoc_rx_fifo_level_chk = 0x012c, | ||
| 209 | .sirfsoc_rx_fifo_op = 0x0130, | ||
| 210 | .sirfsoc_rx_fifo_status = 0x0134, | ||
| 211 | .sirfsoc_rx_fifo_data = 0x0138, | ||
| 212 | .sirfsoc_afc_ctrl = 0x0140, | ||
| 213 | .sirfsoc_swh_dma_io = 0x0148, | ||
| 214 | }, | ||
| 215 | .uart_int_en = { | ||
| 216 | .sirfsoc_rx_done_en = BIT(0), | ||
| 217 | .sirfsoc_tx_done_en = BIT(1), | ||
| 218 | .sirfsoc_rx_oflow_en = BIT(2), | ||
| 219 | .sirfsoc_tx_allout_en = BIT(3), | ||
| 220 | .sirfsoc_rx_io_dma_en = BIT(4), | ||
| 221 | .sirfsoc_tx_io_dma_en = BIT(5), | ||
| 222 | .sirfsoc_rxfifo_full_en = BIT(6), | ||
| 223 | .sirfsoc_txfifo_empty_en = BIT(7), | ||
| 224 | .sirfsoc_rxfifo_thd_en = BIT(8), | ||
| 225 | .sirfsoc_txfifo_thd_en = BIT(9), | ||
| 226 | .sirfsoc_frm_err_en = BIT(10), | ||
| 227 | .sirfsoc_rxd_brk_en = BIT(11), | ||
| 228 | .sirfsoc_rx_timeout_en = BIT(12), | ||
| 229 | .sirfsoc_parity_err_en = BIT(13), | ||
| 230 | .sirfsoc_cts_en = BIT(14), | ||
| 231 | .sirfsoc_rts_en = BIT(15), | ||
| 232 | }, | ||
| 233 | .uart_int_st = { | ||
| 234 | .sirfsoc_rx_done = BIT(0), | ||
| 235 | .sirfsoc_tx_done = BIT(1), | ||
| 236 | .sirfsoc_rx_oflow = BIT(2), | ||
| 237 | .sirfsoc_tx_allout = BIT(3), | ||
| 238 | .sirfsoc_rx_io_dma = BIT(4), | ||
| 239 | .sirfsoc_tx_io_dma = BIT(5), | ||
| 240 | .sirfsoc_rxfifo_full = BIT(6), | ||
| 241 | .sirfsoc_txfifo_empty = BIT(7), | ||
| 242 | .sirfsoc_rxfifo_thd = BIT(8), | ||
| 243 | .sirfsoc_txfifo_thd = BIT(9), | ||
| 244 | .sirfsoc_frm_err = BIT(10), | ||
| 245 | .sirfsoc_rxd_brk = BIT(11), | ||
| 246 | .sirfsoc_rx_timeout = BIT(12), | ||
| 247 | .sirfsoc_parity_err = BIT(13), | ||
| 248 | .sirfsoc_cts = BIT(14), | ||
| 249 | .sirfsoc_rts = BIT(15), | ||
| 250 | }, | ||
| 251 | .fifo_status = { | ||
| 252 | .ff_full = uart_usp_ff_full_mask, | ||
| 253 | .ff_empty = uart_usp_ff_empty_mask, | ||
| 254 | }, | ||
| 255 | .uart_param = { | ||
| 256 | .uart_name = "ttySiRF", | ||
| 257 | .port_name = "sirfsoc_uart", | ||
| 258 | }, | ||
| 259 | }; | ||
| 260 | /* uart io ctrl */ | ||
| 261 | #define SIRFUART_DATA_BIT_LEN_MASK 0x3 | ||
| 262 | #define SIRFUART_DATA_BIT_LEN_5 BIT(0) | ||
| 263 | #define SIRFUART_DATA_BIT_LEN_6 1 | ||
| 264 | #define SIRFUART_DATA_BIT_LEN_7 2 | ||
| 265 | #define SIRFUART_DATA_BIT_LEN_8 3 | ||
| 266 | #define SIRFUART_STOP_BIT_LEN_1 0 | ||
| 267 | #define SIRFUART_STOP_BIT_LEN_2 BIT(2) | ||
| 268 | #define SIRFUART_PARITY_EN BIT(3) | ||
| 269 | #define SIRFUART_EVEN_BIT BIT(4) | ||
| 270 | #define SIRFUART_STICK_BIT_MASK (7 << 3) | ||
| 271 | #define SIRFUART_STICK_BIT_NONE (0 << 3) | ||
| 272 | #define SIRFUART_STICK_BIT_EVEN BIT(3) | ||
| 273 | #define SIRFUART_STICK_BIT_ODD (3 << 3) | ||
| 274 | #define SIRFUART_STICK_BIT_MARK (5 << 3) | ||
| 275 | #define SIRFUART_STICK_BIT_SPACE (7 << 3) | ||
| 276 | #define SIRFUART_SET_BREAK BIT(6) | ||
| 277 | #define SIRFUART_LOOP_BACK BIT(7) | ||
| 278 | #define SIRFUART_PARITY_MASK (7 << 3) | ||
| 279 | #define SIRFUART_DUMMY_READ BIT(16) | ||
| 280 | #define SIRFUART_AFC_CTRL_RX_THD 0x70 | ||
| 281 | #define SIRFUART_AFC_RX_EN BIT(8) | ||
| 282 | #define SIRFUART_AFC_TX_EN BIT(9) | ||
| 283 | #define SIRFUART_AFC_CTS_CTRL BIT(10) | ||
| 284 | #define SIRFUART_AFC_RTS_CTRL BIT(11) | ||
| 285 | #define SIRFUART_AFC_CTS_STATUS BIT(12) | ||
| 286 | #define SIRFUART_AFC_RTS_STATUS BIT(13) | ||
| 287 | /* UART FIFO Register */ | ||
| 288 | #define SIRFUART_FIFO_STOP 0x0 | ||
| 289 | #define SIRFUART_FIFO_RESET BIT(0) | ||
| 290 | #define SIRFUART_FIFO_START BIT(1) | ||
| 291 | |||
| 292 | #define SIRFUART_RX_EN BIT(0) | ||
| 293 | #define SIRFUART_TX_EN BIT(1) | ||
| 294 | |||
| 295 | #define SIRFUART_IO_MODE BIT(0) | ||
| 296 | #define SIRFUART_DMA_MODE 0x0 | ||
| 297 | #define SIRFUART_RX_DMA_FLUSH 0x4 | ||
| 298 | |||
| 299 | #define SIRFUART_CLEAR_RX_ADDR_EN 0x2 | ||
| 300 | /* Baud Rate Calculation */ | ||
| 301 | #define SIRF_USP_MIN_SAMPLE_DIV 0x1 | ||
| 302 | #define SIRF_MIN_SAMPLE_DIV 0xf | ||
| 303 | #define SIRF_MAX_SAMPLE_DIV 0x3f | ||
| 304 | #define SIRF_IOCLK_DIV_MAX 0xffff | ||
| 305 | #define SIRF_SAMPLE_DIV_SHIFT 16 | ||
| 306 | #define SIRF_IOCLK_DIV_MASK 0xffff | ||
| 307 | #define SIRF_SAMPLE_DIV_MASK 0x3f0000 | ||
| 308 | #define SIRF_BAUD_RATE_SUPPORT_NR 18 | ||
| 309 | |||
| 310 | /* USP SPEC */ | ||
| 311 | #define SIRFSOC_USP_ENDIAN_CTRL_LSBF BIT(4) | ||
| 312 | #define SIRFSOC_USP_EN BIT(5) | ||
| 313 | #define SIRFSOC_USP_MODE2_RXD_DELAY_OFFSET 0 | ||
| 314 | #define SIRFSOC_USP_MODE2_TXD_DELAY_OFFSET 8 | ||
| 315 | #define SIRFSOC_USP_MODE2_CLK_DIVISOR_MASK 0x3ff | ||
| 316 | #define SIRFSOC_USP_MODE2_CLK_DIVISOR_OFFSET 21 | ||
| 317 | #define SIRFSOC_USP_TX_DATA_LEN_OFFSET 0 | ||
| 318 | #define SIRFSOC_USP_TX_SYNC_LEN_OFFSET 8 | ||
| 319 | #define SIRFSOC_USP_TX_FRAME_LEN_OFFSET 16 | ||
| 320 | #define SIRFSOC_USP_TX_SHIFTER_LEN_OFFSET 24 | ||
| 321 | #define SIRFSOC_USP_TX_CLK_DIVISOR_OFFSET 30 | ||
| 322 | #define SIRFSOC_USP_RX_DATA_LEN_OFFSET 0 | ||
| 323 | #define SIRFSOC_USP_RX_FRAME_LEN_OFFSET 8 | ||
| 324 | #define SIRFSOC_USP_RX_SHIFTER_LEN_OFFSET 16 | ||
| 325 | #define SIRFSOC_USP_RX_CLK_DIVISOR_OFFSET 24 | ||
| 326 | #define SIRFSOC_USP_ASYNC_DIV2_MASK 0x3f | ||
| 327 | #define SIRFSOC_USP_ASYNC_DIV2_OFFSET 16 | ||
| 328 | #define SIRFSOC_USP_LOOP_BACK_CTRL BIT(2) | ||
| 329 | #define SIRFSOC_USP_FRADDR_CLR_EN BIT(1) | ||
| 330 | /* USP-UART Common */ | ||
| 331 | #define SIRFSOC_UART_RX_TIMEOUT(br, to) (((br) * (((to) + 999) / 1000)) / 1000) | ||
| 332 | #define SIRFUART_RECV_TIMEOUT_VALUE(x) \ | ||
| 333 | (((x) > 0xFFFF) ? 0xFFFF : ((x) & 0xFFFF)) | ||
| 334 | #define SIRFUART_USP_RECV_TIMEOUT(x) (x & 0xFFFF) | ||
| 335 | #define SIRFUART_UART_RECV_TIMEOUT(x) ((x & 0xFFFF) << 16) | ||
| 336 | |||
| 337 | #define SIRFUART_FIFO_THD(port) (port->fifosize >> 1) | ||
| 338 | #define SIRFUART_ERR_INT_STAT(unit_st, uart_type) \ | ||
| 339 | (uint_st->sirfsoc_rx_oflow | \ | ||
| 340 | uint_st->sirfsoc_frm_err | \ | ||
| 341 | uint_st->sirfsoc_rxd_brk | \ | ||
| 342 | ((uart_type != SIRF_REAL_UART) ? \ | ||
| 343 | 0 : uint_st->sirfsoc_parity_err)) | ||
| 344 | #define SIRFUART_RX_IO_INT_EN(uint_en, uart_type) \ | ||
| 345 | (uint_en->sirfsoc_rx_done_en |\ | ||
| 346 | uint_en->sirfsoc_rxfifo_thd_en |\ | ||
| 347 | uint_en->sirfsoc_rxfifo_full_en |\ | ||
| 348 | uint_en->sirfsoc_frm_err_en |\ | ||
| 349 | uint_en->sirfsoc_rx_oflow_en |\ | ||
| 350 | uint_en->sirfsoc_rxd_brk_en |\ | ||
| 351 | ((uart_type != SIRF_REAL_UART) ? \ | ||
| 352 | 0 : uint_en->sirfsoc_parity_err_en)) | ||
| 353 | #define SIRFUART_RX_IO_INT_ST(uint_st) \ | ||
| 354 | (uint_st->sirfsoc_rxfifo_thd |\ | ||
| 355 | uint_st->sirfsoc_rxfifo_full|\ | ||
| 356 | uint_st->sirfsoc_rx_done |\ | ||
| 357 | uint_st->sirfsoc_rx_timeout) | ||
| 358 | #define SIRFUART_CTS_INT_ST(uint_st) (uint_st->sirfsoc_cts) | ||
| 359 | #define SIRFUART_RX_DMA_INT_EN(uint_en, uart_type) \ | ||
| 360 | (uint_en->sirfsoc_frm_err_en |\ | ||
| 361 | uint_en->sirfsoc_rx_oflow_en |\ | ||
| 362 | uint_en->sirfsoc_rxd_brk_en |\ | ||
| 363 | ((uart_type != SIRF_REAL_UART) ? \ | ||
| 364 | 0 : uint_en->sirfsoc_parity_err_en)) | ||
| 365 | /* Generic Definitions */ | ||
| 366 | #define SIRFSOC_UART_NAME "ttySiRF" | ||
| 367 | #define SIRFSOC_UART_MAJOR 0 | ||
| 368 | #define SIRFSOC_UART_MINOR 0 | ||
| 369 | #define SIRFUART_PORT_NAME "sirfsoc-uart" | ||
| 370 | #define SIRFUART_MAP_SIZE 0x200 | ||
| 371 | #define SIRFSOC_UART_NR 11 | ||
| 372 | #define SIRFSOC_PORT_TYPE 0xa5 | ||
| 373 | |||
| 374 | /* Uart Common Use Macro*/ | ||
| 375 | #define SIRFSOC_RX_DMA_BUF_SIZE (1024 * 32) | ||
| 376 | #define BYTES_TO_ALIGN(dma_addr) ((unsigned long)(dma_addr) & 0x3) | ||
| 377 | /* Uart Fifo Level Chk */ | ||
| 378 | #define SIRFUART_TX_FIFO_SC_OFFSET 0 | ||
| 379 | #define SIRFUART_TX_FIFO_LC_OFFSET 10 | ||
| 380 | #define SIRFUART_TX_FIFO_HC_OFFSET 20 | ||
| 381 | #define SIRFUART_TX_FIFO_CHK_SC(line, value) ((((line) == 1) ? (value & 0x3) :\ | ||
| 382 | (value & 0x1f)) << SIRFUART_TX_FIFO_SC_OFFSET) | ||
| 383 | #define SIRFUART_TX_FIFO_CHK_LC(line, value) ((((line) == 1) ? (value & 0x3) :\ | ||
| 384 | (value & 0x1f)) << SIRFUART_TX_FIFO_LC_OFFSET) | ||
| 385 | #define SIRFUART_TX_FIFO_CHK_HC(line, value) ((((line) == 1) ? (value & 0x3) :\ | ||
| 386 | (value & 0x1f)) << SIRFUART_TX_FIFO_HC_OFFSET) | ||
| 387 | |||
| 388 | #define SIRFUART_RX_FIFO_CHK_SC SIRFUART_TX_FIFO_CHK_SC | ||
| 389 | #define SIRFUART_RX_FIFO_CHK_LC SIRFUART_TX_FIFO_CHK_LC | ||
| 390 | #define SIRFUART_RX_FIFO_CHK_HC SIRFUART_TX_FIFO_CHK_HC | ||
| 391 | #define SIRFUART_RX_FIFO_MASK 0x7f | ||
| 392 | /* Indicate how many buffers used */ | ||
| 393 | |||
| 394 | /* For Fast Baud Rate Calculation */ | ||
| 395 | struct sirfsoc_baudrate_to_regv { | ||
| 396 | unsigned int baud_rate; | ||
| 397 | unsigned int reg_val; | ||
| 398 | }; | ||
| 399 | |||
| 400 | enum sirfsoc_tx_state { | ||
| 401 | TX_DMA_IDLE, | ||
| 402 | TX_DMA_RUNNING, | ||
| 403 | TX_DMA_PAUSE, | ||
| 404 | }; | ||
| 405 | |||
| 406 | struct sirfsoc_rx_buffer { | ||
| 407 | struct circ_buf xmit; | ||
| 408 | dma_cookie_t cookie; | ||
| 409 | struct dma_async_tx_descriptor *desc; | ||
| 410 | dma_addr_t dma_addr; | ||
| 411 | }; | ||
| 412 | |||
| 413 | struct sirfsoc_uart_port { | ||
| 414 | bool hw_flow_ctrl; | ||
| 415 | bool ms_enabled; | ||
| 416 | |||
| 417 | struct uart_port port; | ||
| 418 | struct clk *clk; | ||
| 419 | /* for SiRFatlas7, there are SET/CLR for UART_INT_EN */ | ||
| 420 | bool is_atlas7; | ||
| 421 | struct sirfsoc_uart_register *uart_reg; | ||
| 422 | struct dma_chan *rx_dma_chan; | ||
| 423 | struct dma_chan *tx_dma_chan; | ||
| 424 | dma_addr_t tx_dma_addr; | ||
| 425 | struct dma_async_tx_descriptor *tx_dma_desc; | ||
| 426 | unsigned long transfer_size; | ||
| 427 | enum sirfsoc_tx_state tx_dma_state; | ||
| 428 | unsigned int cts_gpio; | ||
| 429 | unsigned int rts_gpio; | ||
| 430 | |||
| 431 | struct sirfsoc_rx_buffer rx_dma_items; | ||
| 432 | struct hrtimer hrt; | ||
| 433 | bool is_hrt_enabled; | ||
| 434 | unsigned long rx_period_time; | ||
| 435 | unsigned long rx_last_pos; | ||
| 436 | unsigned long pio_fetch_cnt; | ||
| 437 | }; | ||
| 438 | |||
| 439 | /* Register Access Control */ | ||
| 440 | #define portaddr(port, reg) ((port)->membase + (reg)) | ||
| 441 | #define rd_regl(port, reg) (__raw_readl(portaddr(port, reg))) | ||
| 442 | #define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg)) | ||
| 443 | |||
| 444 | /* UART Port Mask */ | ||
| 445 | #define SIRFUART_FIFOLEVEL_MASK(port) ((port->fifosize - 1) & 0xFFF) | ||
| 446 | #define SIRFUART_FIFOFULL_MASK(port) (port->fifosize & 0xFFF) | ||
| 447 | #define SIRFUART_FIFOEMPTY_MASK(port) ((port->fifosize & 0xFFF) << 1) | ||
| @@ -3,7 +3,8 @@ · 2 unmodified lines | |||
| 3 | * Copyright (C) Maxime Coquelin 2015 | 3 | * Copyright (C) Maxime Coquelin 2015 |
| 4 | * Copyright (C) STMicroelectronics SA 2017 | 4 | * Copyright (C) STMicroelectronics SA 2017 |
| 5 | * Authors: Maxime Coquelin <mcoquelin.stm32@gmail.com> | 5 | * Authors: Maxime Coquelin <mcoquelin.stm32@gmail.com> |
| 6 | * Gerald Baeza <gerald.baeza@st.com> | 6 | * Gerald Baeza <gerald.baeza@foss.st.com> |
| 7 | * Erwan Le Ray <erwan.leray@foss.st.com> | ||
| 7 | * | 8 | * |
| 8 | * Inspired by st-asc.c from STMicroelectronics (c) | 9 | * Inspired by st-asc.c from STMicroelectronics (c) |
| 9 | */ | 10 | */ |
| @@ -34,15 +35,15 @@ · 24 unmodified lines | |||
| 34 | #include "serial_mctrl_gpio.h" | 35 | #include "serial_mctrl_gpio.h" |
| 35 | #include "stm32-usart.h" | 36 | #include "stm32-usart.h" |
| 36 | 37 | ||
| 37 | static void stm32_stop_tx(struct uart_port *port); | 38 | static void stm32_usart_stop_tx(struct uart_port *port); |
| 38 | static void stm32_transmit_chars(struct uart_port *port); | 39 | static void stm32_usart_transmit_chars(struct uart_port *port); |
| 39 | 40 | ||
| 40 | static inline struct stm32_port *to_stm32_port(struct uart_port *port) | 41 | static inline struct stm32_port *to_stm32_port(struct uart_port *port) |
| 41 | { | 42 | { |
| 42 | return container_of(port, struct stm32_port, port); | 43 | return container_of(port, struct stm32_port, port); |
| 43 | } | 44 | } |
| 44 | 45 | ||
| 45 | static void stm32_set_bits(struct uart_port *port, u32 reg, u32 bits) | 46 | static void stm32_usart_set_bits(struct uart_port *port, u32 reg, u32 bits) |
| 46 | { | 47 | { |
| 47 | u32 val; | 48 | u32 val; |
| 48 | 49 | ||
| @@ -51,7 +52,7 @@ static void stm32_set_bits(struct uart_port *port, u32 reg, u32 bits) · 2 unmodified lines | |||
| 51 | writel_relaxed(val, port->membase + reg); | 52 | writel_relaxed(val, port->membase + reg); |
| 52 | } | 53 | } |
| 53 | 54 | ||
| 54 | static void stm32_clr_bits(struct uart_port *port, u32 reg, u32 bits) | 55 | static void stm32_usart_clr_bits(struct uart_port *port, u32 reg, u32 bits) |
| 55 | { | 56 | { |
| 56 | u32 val; | 57 | u32 val; |
| 57 | 58 | ||
| @@ -60,8 +61,8 @@ static void stm32_clr_bits(struct uart_port *port, u32 reg, u32 bits) · 2 unmodified lines | |||
| 60 | writel_relaxed(val, port->membase + reg); | 61 | writel_relaxed(val, port->membase + reg); |
| 61 | } | 62 | } |
| 62 | 63 | ||
| 63 | static void stm32_config_reg_rs485(u32 *cr1, u32 *cr3, u32 delay_ADE, | 64 | static void stm32_usart_config_reg_rs485(u32 *cr1, u32 *cr3, u32 delay_ADE, |
| 64 | u32 delay_DDE, u32 baud) | 65 | u32 delay_DDE, u32 baud) |
| 65 | { | 66 | { |
| 66 | u32 rs485_deat_dedt; | 67 | u32 rs485_deat_dedt; |
| 67 | u32 rs485_deat_dedt_max = (USART_CR1_DEAT_MASK >> USART_CR1_DEAT_SHIFT); | 68 | u32 rs485_deat_dedt_max = (USART_CR1_DEAT_MASK >> USART_CR1_DEAT_SHIFT); |
| @@ -95,8 +96,8 @@ static void stm32_config_reg_rs485(u32 *cr1, u32 *cr3, u32 delay_ADE, · 27 unmodified lines | |||
| 95 | *cr1 |= rs485_deat_dedt; | 96 | *cr1 |= rs485_deat_dedt; |
| 96 | } | 97 | } |
| 97 | 98 | ||
| 98 | static int stm32_config_rs485(struct uart_port *port, | 99 | static int stm32_usart_config_rs485(struct uart_port *port, |
| 99 | struct serial_rs485 *rs485conf) | 100 | struct serial_rs485 *rs485conf) |
| 100 | { | 101 | { |
| 101 | struct stm32_port *stm32_port = to_stm32_port(port); | 102 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 102 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; | 103 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| @@ -104,7 +105,7 @@ static int stm32_config_rs485(struct uart_port *port, · 1 unmodified line | |||
| 104 | u32 usartdiv, baud, cr1, cr3; | 105 | u32 usartdiv, baud, cr1, cr3; |
| 105 | bool over8; | 106 | bool over8; |
| 106 | 107 | ||
| 107 | stm32_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit)); | 108 | stm32_usart_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit)); |
| 108 | 109 | ||
| 109 | port->rs485 = *rs485conf; | 110 | port->rs485 = *rs485conf; |
| 110 | 111 | ||
| @@ -122,9 +123,10 @@ static int stm32_config_rs485(struct uart_port *port, · 11 unmodified lines | |||
| 122 | << USART_BRR_04_R_SHIFT; | 123 | << USART_BRR_04_R_SHIFT; |
| 123 | 124 | ||
| 124 | baud = DIV_ROUND_CLOSEST(port->uartclk, usartdiv); | 125 | baud = DIV_ROUND_CLOSEST(port->uartclk, usartdiv); |
| 125 | stm32_config_reg_rs485(&cr1, &cr3, | 126 | stm32_usart_config_reg_rs485(&cr1, &cr3, |
| 126 | rs485conf->delay_rts_before_send, | 127 | rs485conf->delay_rts_before_send, |
| 127 | rs485conf->delay_rts_after_send, baud); | 128 | rs485conf->delay_rts_after_send, |
| 129 | baud); | ||
| 128 | 130 | ||
| 129 | if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { | 131 | if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { |
| 130 | cr3 &= ~USART_CR3_DEP; | 132 | cr3 &= ~USART_CR3_DEP; |
| @@ -137,18 +139,19 @@ static int stm32_config_rs485(struct uart_port *port, · 6 unmodified lines | |||
| 137 | writel_relaxed(cr3, port->membase + ofs->cr3); | 139 | writel_relaxed(cr3, port->membase + ofs->cr3); |
| 138 | writel_relaxed(cr1, port->membase + ofs->cr1); | 140 | writel_relaxed(cr1, port->membase + ofs->cr1); |
| 139 | } else { | 141 | } else { |
| 140 | stm32_clr_bits(port, ofs->cr3, USART_CR3_DEM | USART_CR3_DEP); | 142 | stm32_usart_clr_bits(port, ofs->cr3, |
| 141 | stm32_clr_bits(port, ofs->cr1, | 143 | USART_CR3_DEM | USART_CR3_DEP); |
| 142 | USART_CR1_DEDT_MASK | USART_CR1_DEAT_MASK); | 144 | stm32_usart_clr_bits(port, ofs->cr1, |
| 145 | USART_CR1_DEDT_MASK | USART_CR1_DEAT_MASK); | ||
| 143 | } | 146 | } |
| 144 | 147 | ||
| 145 | stm32_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit)); | 148 | stm32_usart_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit)); |
| 146 | 149 | ||
| 147 | return 0; | 150 | return 0; |
| 148 | } | 151 | } |
| 149 | 152 | ||
| 150 | static int stm32_init_rs485(struct uart_port *port, | 153 | static int stm32_usart_init_rs485(struct uart_port *port, |
| 151 | struct platform_device *pdev) | 154 | struct platform_device *pdev) |
| 152 | { | 155 | { |
| 153 | struct serial_rs485 *rs485conf = &port->rs485; | 156 | struct serial_rs485 *rs485conf = &port->rs485; |
| 154 | 157 | ||
| @@ -162,8 +165,8 @@ static int stm32_init_rs485(struct uart_port *port, · 7 unmodified lines | |||
| 162 | return uart_get_rs485_mode(port); | 165 | return uart_get_rs485_mode(port); |
| 163 | } | 166 | } |
| 164 | 167 | ||
| 165 | static int stm32_pending_rx(struct uart_port *port, u32 *sr, int *last_res, | 168 | static int stm32_usart_pending_rx(struct uart_port *port, u32 *sr, |
| 166 | bool threaded) | 169 | int *last_res, bool threaded) |
| 167 | { | 170 | { |
| 168 | struct stm32_port *stm32_port = to_stm32_port(port); | 171 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 169 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; | 172 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| @@ -176,8 +179,7 @@ static int stm32_pending_rx(struct uart_port *port, u32 *sr, int *last_res, · 6 unmodified lines | |||
| 176 | status = dmaengine_tx_status(stm32_port->rx_ch, | 179 | status = dmaengine_tx_status(stm32_port->rx_ch, |
| 177 | stm32_port->rx_ch->cookie, | 180 | stm32_port->rx_ch->cookie, |
| 178 | &state); | 181 | &state); |
| 179 | if ((status == DMA_IN_PROGRESS) && | 182 | if (status == DMA_IN_PROGRESS && (*last_res != state.residue)) |
| 180 | (*last_res != state.residue)) | ||
| 181 | return 1; | 183 | return 1; |
| 182 | else | 184 | else |
| 183 | return 0; | 185 | return 0; |
| @@ -187,8 +189,8 @@ static int stm32_pending_rx(struct uart_port *port, u32 *sr, int *last_res, · 3 unmodified lines | |||
| 187 | return 0; | 189 | return 0; |
| 188 | } | 190 | } |
| 189 | 191 | ||
| 190 | static unsigned long stm32_get_char(struct uart_port *port, u32 *sr, | 192 | static unsigned long stm32_usart_get_char(struct uart_port *port, u32 *sr, |
| 191 | int *last_res) | 193 | int *last_res) |
| 192 | { | 194 | { |
| 193 | struct stm32_port *stm32_port = to_stm32_port(port); | 195 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 194 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; | 196 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| @@ -207,7 +209,7 @@ static unsigned long stm32_get_char(struct uart_port *port, u32 *sr, · 12 unmodified lines | |||
| 207 | return c; | 209 | return c; |
| 208 | } | 210 | } |
| 209 | 211 | ||
| 210 | static void stm32_receive_chars(struct uart_port *port, bool threaded) | 212 | static void stm32_usart_receive_chars(struct uart_port *port, bool threaded) |
| 211 | { | 213 | { |
| 212 | struct tty_port *tport = &port->state->port; | 214 | struct tty_port *tport = &port->state->port; |
| 213 | struct stm32_port *stm32_port = to_stm32_port(port); | 215 | struct stm32_port *stm32_port = to_stm32_port(port); |
| @@ -219,7 +221,8 @@ static void stm32_receive_chars(struct uart_port *port, bool threaded) · 5 unmodified lines | |||
| 219 | if (irqd_is_wakeup_set(irq_get_irq_data(port->irq))) | 221 | if (irqd_is_wakeup_set(irq_get_irq_data(port->irq))) |
| 220 | pm_wakeup_event(tport->tty->dev, 0); | 222 | pm_wakeup_event(tport->tty->dev, 0); |
| 221 | 223 | ||
| 222 | while (stm32_pending_rx(port, &sr, &stm32_port->last_res, threaded)) { | 224 | while (stm32_usart_pending_rx(port, &sr, &stm32_port->last_res, |
| 225 | threaded)) { | ||
| 223 | sr |= USART_SR_DUMMY_RX; | 226 | sr |= USART_SR_DUMMY_RX; |
| 224 | flag = TTY_NORMAL; | 227 | flag = TTY_NORMAL; |
| 225 | 228 | ||
| @@ -238,7 +241,7 @@ static void stm32_receive_chars(struct uart_port *port, bool threaded) · 12 unmodified lines | |||
| 238 | writel_relaxed(sr & USART_SR_ERR_MASK, | 241 | writel_relaxed(sr & USART_SR_ERR_MASK, |
| 239 | port->membase + ofs->icr); | 242 | port->membase + ofs->icr); |
| 240 | 243 | ||
| 241 | c = stm32_get_char(port, &sr, &stm32_port->last_res); | 244 | c = stm32_usart_get_char(port, &sr, &stm32_port->last_res); |
| 242 | port->icount.rx++; | 245 | port->icount.rx++; |
| 243 | if (sr & USART_SR_ERR_MASK) { | 246 | if (sr & USART_SR_ERR_MASK) { |
| 244 | if (sr & USART_SR_ORE) { | 247 | if (sr & USART_SR_ORE) { |
| @@ -278,20 +281,20 @@ static void stm32_receive_chars(struct uart_port *port, bool threaded) · 33 unmodified lines | |||
| 278 | spin_lock(&port->lock); | 281 | spin_lock(&port->lock); |
| 279 | } | 282 | } |
| 280 | 283 | ||
| 281 | static void stm32_tx_dma_complete(void *arg) | 284 | static void stm32_usart_tx_dma_complete(void *arg) |
| 282 | { | 285 | { |
| 283 | struct uart_port *port = arg; | 286 | struct uart_port *port = arg; |
| 284 | struct stm32_port *stm32port = to_stm32_port(port); | 287 | struct stm32_port *stm32port = to_stm32_port(port); |
| 285 | struct stm32_usart_offsets *ofs = &stm32port->info->ofs; | 288 | struct stm32_usart_offsets *ofs = &stm32port->info->ofs; |
| 286 | 289 | ||
| 287 | stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAT); | 290 | stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); |
| 288 | stm32port->tx_dma_busy = false; | 291 | stm32port->tx_dma_busy = false; |
| 289 | 292 | ||
| 290 | /* Let's see if we have pending data to send */ | 293 | /* Let's see if we have pending data to send */ |
| 291 | stm32_transmit_chars(port); | 294 | stm32_usart_transmit_chars(port); |
| 292 | } | 295 | } |
| 293 | 296 | ||
| 294 | static void stm32_tx_interrupt_enable(struct uart_port *port) | 297 | static void stm32_usart_tx_interrupt_enable(struct uart_port *port) |
| 295 | { | 298 | { |
| 296 | struct stm32_port *stm32_port = to_stm32_port(port); | 299 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 297 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; | 300 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| @@ -301,30 +304,30 @@ static void stm32_tx_interrupt_enable(struct uart_port *port) · 3 unmodified lines | |||
| 301 | * or TX empty irq when FIFO is disabled | 304 | * or TX empty irq when FIFO is disabled |
| 302 | */ | 305 | */ |
| 303 | if (stm32_port->fifoen) | 306 | if (stm32_port->fifoen) |
| 304 | stm32_set_bits(port, ofs->cr3, USART_CR3_TXFTIE); | 307 | stm32_usart_set_bits(port, ofs->cr3, USART_CR3_TXFTIE); |
| 305 | else | 308 | else |
| 306 | stm32_set_bits(port, ofs->cr1, USART_CR1_TXEIE); | 309 | stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TXEIE); |
| 307 | } | 310 | } |
| 308 | 311 | ||
| 309 | static void stm32_tx_interrupt_disable(struct uart_port *port) | 312 | static void stm32_usart_tx_interrupt_disable(struct uart_port *port) |
| 310 | { | 313 | { |
| 311 | struct stm32_port *stm32_port = to_stm32_port(port); | 314 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 312 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; | 315 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| 313 | 316 | ||
| 314 | if (stm32_port->fifoen) | 317 | if (stm32_port->fifoen) |
| 315 | stm32_clr_bits(port, ofs->cr3, USART_CR3_TXFTIE); | 318 | stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_TXFTIE); |
| 316 | else | 319 | else |
| 317 | stm32_clr_bits(port, ofs->cr1, USART_CR1_TXEIE); | 320 | stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TXEIE); |
| 318 | } | 321 | } |
| 319 | 322 | ||
| 320 | static void stm32_transmit_chars_pio(struct uart_port *port) | 323 | static void stm32_usart_transmit_chars_pio(struct uart_port *port) |
| 321 | { | 324 | { |
| 322 | struct stm32_port *stm32_port = to_stm32_port(port); | 325 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 323 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; | 326 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| 324 | struct circ_buf *xmit = &port->state->xmit; | 327 | struct circ_buf *xmit = &port->state->xmit; |
| 325 | 328 | ||
| 326 | if (stm32_port->tx_dma_busy) { | 329 | if (stm32_port->tx_dma_busy) { |
| 327 | stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAT); | 330 | stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); |
| 328 | stm32_port->tx_dma_busy = false; | 331 | stm32_port->tx_dma_busy = false; |
| 329 | } | 332 | } |
| 330 | 333 | ||
| @@ -339,12 +342,12 @@ static void stm32_transmit_chars_pio(struct uart_port *port) · 8 unmodified lines | |||
| 339 | 342 | ||
| 340 | /* rely on TXE irq (mask or unmask) for sending remaining data */ | 343 | /* rely on TXE irq (mask or unmask) for sending remaining data */ |
| 341 | if (uart_circ_empty(xmit)) | 344 | if (uart_circ_empty(xmit)) |
| 342 | stm32_tx_interrupt_disable(port); | 345 | stm32_usart_tx_interrupt_disable(port); |
| 343 | else | 346 | else |
| 344 | stm32_tx_interrupt_enable(port); | 347 | stm32_usart_tx_interrupt_enable(port); |
| 345 | } | 348 | } |
| 346 | 349 | ||
| 347 | static void stm32_transmit_chars_dma(struct uart_port *port) | 350 | static void stm32_usart_transmit_chars_dma(struct uart_port *port) |
| 348 | { | 351 | { |
| 349 | struct stm32_port *stm32port = to_stm32_port(port); | 352 | struct stm32_port *stm32port = to_stm32_port(port); |
| 350 | struct stm32_usart_offsets *ofs = &stm32port->info->ofs; | 353 | struct stm32_usart_offsets *ofs = &stm32port->info->ofs; |
| @@ -383,28 +386,34 @@ static void stm32_transmit_chars_dma(struct uart_port *port) · 32 unmodified lines | |||
| 383 | DMA_MEM_TO_DEV, | 386 | DMA_MEM_TO_DEV, |
| 384 | DMA_PREP_INTERRUPT); | 387 | DMA_PREP_INTERRUPT); |
| 385 | 388 | ||
| 386 | if (!desc) { | 389 | if (!desc) |
| 387 | for (i = count; i > 0; i--) | 390 | goto fallback_err; |
| 388 | stm32_transmit_chars_pio(port); | ||
| 389 | return; | ||
| 390 | } | ||
| 391 | 391 | ||
| 392 | desc->callback = stm32_tx_dma_complete; | 392 | desc->callback = stm32_usart_tx_dma_complete; |
| 393 | desc->callback_param = port; | 393 | desc->callback_param = port; |
| 394 | 394 | ||
| 395 | /* Push current DMA TX transaction in the pending queue */ | 395 | /* Push current DMA TX transaction in the pending queue */ |
| 396 | dmaengine_submit(desc); | 396 | if (dma_submit_error(dmaengine_submit(desc))) { |
| 397 | /* dma no yet started, safe to free resources */ | ||
| 398 | dmaengine_terminate_async(stm32port->tx_ch); | ||
| 399 | goto fallback_err; | ||
| 400 | } | ||
| 397 | 401 | ||
| 398 | /* Issue pending DMA TX requests */ | 402 | /* Issue pending DMA TX requests */ |
| 399 | dma_async_issue_pending(stm32port->tx_ch); | 403 | dma_async_issue_pending(stm32port->tx_ch); |
| 400 | 404 | ||
| 401 | stm32_set_bits(port, ofs->cr3, USART_CR3_DMAT); | 405 | stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAT); |
| 402 | 406 | ||
| 403 | xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1); | 407 | xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1); |
| 404 | port->icount.tx += count; | 408 | port->icount.tx += count; |
| 409 | return; | ||
| 410 | |||
| 411 | fallback_err: | ||
| 412 | for (i = count; i > 0; i--) | ||
| 413 | stm32_usart_transmit_chars_pio(port); | ||
| 405 | } | 414 | } |
| 406 | 415 | ||
| 407 | static void stm32_transmit_chars(struct uart_port *port) | 416 | static void stm32_usart_transmit_chars(struct uart_port *port) |
| 408 | { | 417 | { |
| 409 | struct stm32_port *stm32_port = to_stm32_port(port); | 418 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 410 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; | 419 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| @@ -412,38 +421,38 @@ static void stm32_transmit_chars(struct uart_port *port) · 1 unmodified line | |||
| 412 | 421 | ||
| 413 | if (port->x_char) { | 422 | if (port->x_char) { |
| 414 | if (stm32_port->tx_dma_busy) | 423 | if (stm32_port->tx_dma_busy) |
| 415 | stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAT); | 424 | stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); |
| 416 | writel_relaxed(port->x_char, port->membase + ofs->tdr); | 425 | writel_relaxed(port->x_char, port->membase + ofs->tdr); |
| 417 | port->x_char = 0; | 426 | port->x_char = 0; |
| 418 | port->icount.tx++; | 427 | port->icount.tx++; |
| 419 | if (stm32_port->tx_dma_busy) | 428 | if (stm32_port->tx_dma_busy) |
| 420 | stm32_set_bits(port, ofs->cr3, USART_CR3_DMAT); | 429 | stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAT); |
| 421 | return; | 430 | return; |
| 422 | } | 431 | } |
| 423 | 432 | ||
| 424 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | 433 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { |
| 425 | stm32_tx_interrupt_disable(port); | 434 | stm32_usart_tx_interrupt_disable(port); |
| 426 | return; | 435 | return; |
| 427 | } | 436 | } |
| 428 | 437 | ||
| 429 | if (ofs->icr == UNDEF_REG) | 438 | if (ofs->icr == UNDEF_REG) |
| 430 | stm32_clr_bits(port, ofs->isr, USART_SR_TC); | 439 | stm32_usart_clr_bits(port, ofs->isr, USART_SR_TC); |
| 431 | else | 440 | else |
| 432 | writel_relaxed(USART_ICR_TCCF, port->membase + ofs->icr); | 441 | writel_relaxed(USART_ICR_TCCF, port->membase + ofs->icr); |
| 433 | 442 | ||
| 434 | if (stm32_port->tx_ch) | 443 | if (stm32_port->tx_ch) |
| 435 | stm32_transmit_chars_dma(port); | 444 | stm32_usart_transmit_chars_dma(port); |
| 436 | else | 445 | else |
| 437 | stm32_transmit_chars_pio(port); | 446 | stm32_usart_transmit_chars_pio(port); |
| 438 | 447 | ||
| 439 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 448 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
| 440 | uart_write_wakeup(port); | 449 | uart_write_wakeup(port); |
| 441 | 450 | ||
| 442 | if (uart_circ_empty(xmit)) | 451 | if (uart_circ_empty(xmit)) |
| 443 | stm32_tx_interrupt_disable(port); | 452 | stm32_usart_tx_interrupt_disable(port); |
| 444 | } | 453 | } |
| 445 | 454 | ||
| 446 | static irqreturn_t stm32_interrupt(int irq, void *ptr) | 455 | static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) |
| 447 | { | 456 | { |
| 448 | struct uart_port *port = ptr; | 457 | struct uart_port *port = ptr; |
| 449 | struct stm32_port *stm32_port = to_stm32_port(port); | 458 | struct stm32_port *stm32_port = to_stm32_port(port); |
| @@ -458,15 +467,15 @@ static irqreturn_t stm32_interrupt(int irq, void *ptr) · 8 unmodified lines | |||
| 458 | writel_relaxed(USART_ICR_RTOCF, | 467 | writel_relaxed(USART_ICR_RTOCF, |
| 459 | port->membase + ofs->icr); | 468 | port->membase + ofs->icr); |
| 460 | 469 | ||
| 461 | if ((sr & USART_SR_WUF) && (ofs->icr != UNDEF_REG)) | 470 | if ((sr & USART_SR_WUF) && ofs->icr != UNDEF_REG) |
| 462 | writel_relaxed(USART_ICR_WUCF, | 471 | writel_relaxed(USART_ICR_WUCF, |
| 463 | port->membase + ofs->icr); | 472 | port->membase + ofs->icr); |
| 464 | 473 | ||
| 465 | if ((sr & USART_SR_RXNE) && !(stm32_port->rx_ch)) | 474 | if ((sr & USART_SR_RXNE) && !(stm32_port->rx_ch)) |
| 466 | stm32_receive_chars(port, false); | 475 | stm32_usart_receive_chars(port, false); |
| 467 | 476 | ||
| 468 | if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch)) | 477 | if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch)) |
| 469 | stm32_transmit_chars(port); | 478 | stm32_usart_transmit_chars(port); |
| 470 | 479 | ||
| 471 | spin_unlock(&port->lock); | 480 | spin_unlock(&port->lock); |
| 472 | 481 | ||
| @@ -476,7 +485,7 @@ static irqreturn_t stm32_interrupt(int irq, void *ptr) · 3 unmodified lines | |||
| 476 | return IRQ_HANDLED; | 485 | return IRQ_HANDLED; |
| 477 | } | 486 | } |
| 478 | 487 | ||
| 479 | static irqreturn_t stm32_threaded_interrupt(int irq, void *ptr) | 488 | static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr) |
| 480 | { | 489 | { |
| 481 | struct uart_port *port = ptr; | 490 | struct uart_port *port = ptr; |
| 482 | struct stm32_port *stm32_port = to_stm32_port(port); | 491 | struct stm32_port *stm32_port = to_stm32_port(port); |
| @@ -484,14 +493,14 @@ static irqreturn_t stm32_threaded_interrupt(int irq, void *ptr) · 1 unmodified line | |||
| 484 | spin_lock(&port->lock); | 493 | spin_lock(&port->lock); |
| 485 | 494 | ||
| 486 | if (stm32_port->rx_ch) | 495 | if (stm32_port->rx_ch) |
| 487 | stm32_receive_chars(port, true); | 496 | stm32_usart_receive_chars(port, true); |
| 488 | 497 | ||
| 489 | spin_unlock(&port->lock); | 498 | spin_unlock(&port->lock); |
| 490 | 499 | ||
| 491 | return IRQ_HANDLED; | 500 | return IRQ_HANDLED; |
| 492 | } | 501 | } |
| 493 | 502 | ||
| 494 | static unsigned int stm32_tx_empty(struct uart_port *port) | 503 | static unsigned int stm32_usart_tx_empty(struct uart_port *port) |
| 495 | { | 504 | { |
| 496 | struct stm32_port *stm32_port = to_stm32_port(port); | 505 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 497 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; | 506 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| @@ -499,20 +508,20 @@ static unsigned int stm32_tx_empty(struct uart_port *port) · 1 unmodified line | |||
| 499 | return readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE; | 508 | return readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE; |
| 500 | } | 509 | } |
| 501 | 510 | ||
| 502 | static void stm32_set_mctrl(struct uart_port *port, unsigned int mctrl) | 511 | static void stm32_usart_set_mctrl(struct uart_port *port, unsigned int mctrl) |
| 503 | { | 512 | { |
| 504 | struct stm32_port *stm32_port = to_stm32_port(port); | 513 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 505 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; | 514 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| 506 | 515 | ||
| 507 | if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS)) | 516 | if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS)) |
| 508 | stm32_set_bits(port, ofs->cr3, USART_CR3_RTSE); | 517 | stm32_usart_set_bits(port, ofs->cr3, USART_CR3_RTSE); |
| 509 | else | 518 | else |
| 510 | stm32_clr_bits(port, ofs->cr3, USART_CR3_RTSE); | 519 | stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_RTSE); |
| 511 | 520 | ||
| 512 | mctrl_gpio_set(stm32_port->gpios, mctrl); | 521 | mctrl_gpio_set(stm32_port->gpios, mctrl); |
| 513 | } | 522 | } |
| 514 | 523 | ||
| 515 | static unsigned int stm32_get_mctrl(struct uart_port *port) | 524 | static unsigned int stm32_usart_get_mctrl(struct uart_port *port) |
| 516 | { | 525 | { |
| 517 | struct stm32_port *stm32_port = to_stm32_port(port); | 526 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 518 | unsigned int ret; | 527 | unsigned int ret; |
| @@ -523,23 +532,23 @@ static unsigned int stm32_get_mctrl(struct uart_port *port) · 4 unmodified lines | |||
| 523 | return mctrl_gpio_get(stm32_port->gpios, &ret); | 532 | return mctrl_gpio_get(stm32_port->gpios, &ret); |
| 524 | } | 533 | } |
| 525 | 534 | ||
| 526 | static void stm32_enable_ms(struct uart_port *port) | 535 | static void stm32_usart_enable_ms(struct uart_port *port) |
| 527 | { | 536 | { |
| 528 | mctrl_gpio_enable_ms(to_stm32_port(port)->gpios); | 537 | mctrl_gpio_enable_ms(to_stm32_port(port)->gpios); |
| 529 | } | 538 | } |
| 530 | 539 | ||
| 531 | static void stm32_disable_ms(struct uart_port *port) | 540 | static void stm32_usart_disable_ms(struct uart_port *port) |
| 532 | { | 541 | { |
| 533 | mctrl_gpio_disable_ms(to_stm32_port(port)->gpios); | 542 | mctrl_gpio_disable_ms(to_stm32_port(port)->gpios); |
| 534 | } | 543 | } |
| 535 | 544 | ||
| 536 | /* Transmit stop */ | 545 | /* Transmit stop */ |
| 537 | static void stm32_stop_tx(struct uart_port *port) | 546 | static void stm32_usart_stop_tx(struct uart_port *port) |
| 538 | { | 547 | { |
| 539 | struct stm32_port *stm32_port = to_stm32_port(port); | 548 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 540 | struct serial_rs485 *rs485conf = &port->rs485; | 549 | struct serial_rs485 *rs485conf = &port->rs485; |
| 541 | 550 | ||
| 542 | stm32_tx_interrupt_disable(port); | 551 | stm32_usart_tx_interrupt_disable(port); |
| 543 | 552 | ||
| 544 | if (rs485conf->flags & SER_RS485_ENABLED) { | 553 | if (rs485conf->flags & SER_RS485_ENABLED) { |
| 545 | if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { | 554 | if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { |
| @@ -553,7 +562,7 @@ static void stm32_stop_tx(struct uart_port *port) · 7 unmodified lines | |||
| 553 | } | 562 | } |
| 554 | 563 | ||
| 555 | /* There are probably characters waiting to be transmitted. */ | 564 | /* There are probably characters waiting to be transmitted. */ |
| 556 | static void stm32_start_tx(struct uart_port *port) | 565 | static void stm32_usart_start_tx(struct uart_port *port) |
| 557 | { | 566 | { |
| 558 | struct stm32_port *stm32_port = to_stm32_port(port); | 567 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 559 | struct serial_rs485 *rs485conf = &port->rs485; | 568 | struct serial_rs485 *rs485conf = &port->rs485; |
| @@ -572,57 +581,56 @@ static void stm32_start_tx(struct uart_port *port) · 12 unmodified lines | |||
| 572 | } | 581 | } |
| 573 | } | 582 | } |
| 574 | 583 | ||
| 575 | stm32_transmit_chars(port); | 584 | stm32_usart_transmit_chars(port); |
| 576 | } | 585 | } |
| 577 | 586 | ||
| 578 | /* Throttle the remote when input buffer is about to overflow. */ | 587 | /* Throttle the remote when input buffer is about to overflow. */ |
| 579 | static void stm32_throttle(struct uart_port *port) | 588 | static void stm32_usart_throttle(struct uart_port *port) |
| 580 | { | 589 | { |
| 581 | struct stm32_port *stm32_port = to_stm32_port(port); | 590 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 582 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; | 591 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| 583 | unsigned long flags; | 592 | unsigned long flags; |
| 584 | 593 | ||
| 585 | spin_lock_irqsave(&port->lock, flags); | 594 | spin_lock_irqsave(&port->lock, flags); |
| 586 | stm32_clr_bits(port, ofs->cr1, stm32_port->cr1_irq); | 595 | stm32_usart_clr_bits(port, ofs->cr1, stm32_port->cr1_irq); |
| 587 | if (stm32_port->cr3_irq) | 596 | if (stm32_port->cr3_irq) |
| 588 | stm32_clr_bits(port, ofs->cr3, stm32_port->cr3_irq); | 597 | stm32_usart_clr_bits(port, ofs->cr3, stm32_port->cr3_irq); |
| 589 | 598 | ||
| 590 | spin_unlock_irqrestore(&port->lock, flags); | 599 | spin_unlock_irqrestore(&port->lock, flags); |
| 591 | } | 600 | } |
| 592 | 601 | ||
| 593 | /* Unthrottle the remote, the input buffer can now accept data. */ | 602 | /* Unthrottle the remote, the input buffer can now accept data. */ |
| 594 | static void stm32_unthrottle(struct uart_port *port) | 603 | static void stm32_usart_unthrottle(struct uart_port *port) |
| 595 | { | 604 | { |
| 596 | struct stm32_port *stm32_port = to_stm32_port(port); | 605 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 597 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; | 606 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| 598 | unsigned long flags; | 607 | unsigned long flags; |
| 599 | 608 | ||
| 600 | spin_lock_irqsave(&port->lock, flags); | 609 | spin_lock_irqsave(&port->lock, flags); |
| 601 | stm32_set_bits(port, ofs->cr1, stm32_port->cr1_irq); | 610 | stm32_usart_set_bits(port, ofs->cr1, stm32_port->cr1_irq); |
| 602 | if (stm32_port->cr3_irq) | 611 | if (stm32_port->cr3_irq) |
| 603 | stm32_set_bits(port, ofs->cr3, stm32_port->cr3_irq); | 612 | stm32_usart_set_bits(port, ofs->cr3, stm32_port->cr3_irq); |
| 604 | 613 | ||
| 605 | spin_unlock_irqrestore(&port->lock, flags); | 614 | spin_unlock_irqrestore(&port->lock, flags); |
| 606 | } | 615 | } |
| 607 | 616 | ||
| 608 | /* Receive stop */ | 617 | /* Receive stop */ |
| 609 | static void stm32_stop_rx(struct uart_port *port) | 618 | static void stm32_usart_stop_rx(struct uart_port *port) |
| 610 | { | 619 | { |
| 611 | struct stm32_port *stm32_port = to_stm32_port(port); | 620 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 612 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; | 621 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| 613 | 622 | ||
| 614 | stm32_clr_bits(port, ofs->cr1, stm32_port->cr1_irq); | 623 | stm32_usart_clr_bits(port, ofs->cr1, stm32_port->cr1_irq); |
| 615 | if (stm32_port->cr3_irq) | 624 | if (stm32_port->cr3_irq) |
| 616 | stm32_clr_bits(port, ofs->cr3, stm32_port->cr3_irq); | 625 | stm32_usart_clr_bits(port, ofs->cr3, stm32_port->cr3_irq); |
| 617 | |||
| 618 | } | 626 | } |
| 619 | 627 | ||
| 620 | /* Handle breaks - ignored by us */ | 628 | /* Handle breaks - ignored by us */ |
| 621 | static void stm32_break_ctl(struct uart_port *port, int break_state) | 629 | static void stm32_usart_break_ctl(struct uart_port *port, int break_state) |
| 622 | { | 630 | { |
| 623 | } | 631 | } |
| 624 | 632 | ||
| 625 | static int stm32_startup(struct uart_port *port) | 633 | static int stm32_usart_startup(struct uart_port *port) |
| 626 | { | 634 | { |
| 627 | struct stm32_port *stm32_port = to_stm32_port(port); | 635 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 628 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; | 636 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| @@ -630,15 +638,15 @@ static int stm32_startup(struct uart_port *port) · 1 unmodified line | |||
| 630 | u32 val; | 638 | u32 val; |
| 631 | int ret; | 639 | int ret; |
| 632 | 640 | ||
| 633 | ret = request_threaded_irq(port->irq, stm32_interrupt, | 641 | ret = request_threaded_irq(port->irq, stm32_usart_interrupt, |
| 634 | stm32_threaded_interrupt, | 642 | stm32_usart_threaded_interrupt, |
| 635 | IRQF_NO_SUSPEND, name, port); | 643 | IRQF_NO_SUSPEND, name, port); |
| 636 | if (ret) | 644 | if (ret) |
| 637 | return ret; | 645 | return ret; |
| 638 | 646 | ||
| 639 | /* RX FIFO Flush */ | 647 | /* RX FIFO Flush */ |
| 640 | if (ofs->rqr != UNDEF_REG) | 648 | if (ofs->rqr != UNDEF_REG) |
| 641 | stm32_set_bits(port, ofs->rqr, USART_RQR_RXFRQ); | 649 | stm32_usart_set_bits(port, ofs->rqr, USART_RQR_RXFRQ); |
| 642 | 650 | ||
| 643 | /* Tx and RX FIFO configuration */ | 651 | /* Tx and RX FIFO configuration */ |
| 644 | if (stm32_port->fifoen) { | 652 | if (stm32_port->fifoen) { |
| @@ -653,12 +661,12 @@ static int stm32_startup(struct uart_port *port) · 8 unmodified lines | |||
| 653 | val = stm32_port->cr1_irq | USART_CR1_RE; | 661 | val = stm32_port->cr1_irq | USART_CR1_RE; |
| 654 | if (stm32_port->fifoen) | 662 | if (stm32_port->fifoen) |
| 655 | val |= USART_CR1_FIFOEN; | 663 | val |= USART_CR1_FIFOEN; |
| 656 | stm32_set_bits(port, ofs->cr1, val); | 664 | stm32_usart_set_bits(port, ofs->cr1, val); |
| 657 | 665 | ||
| 658 | return 0; | 666 | return 0; |
| 659 | } | 667 | } |
| 660 | 668 | ||
| 661 | static void stm32_shutdown(struct uart_port *port) | 669 | static void stm32_usart_shutdown(struct uart_port *port) |
| 662 | { | 670 | { |
| 663 | struct stm32_port *stm32_port = to_stm32_port(port); | 671 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 664 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; | 672 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| @@ -667,7 +675,7 @@ static void stm32_shutdown(struct uart_port *port) · 2 unmodified lines | |||
| 667 | int ret; | 675 | int ret; |
| 668 | 676 | ||
| 669 | /* Disable modem control interrupts */ | 677 | /* Disable modem control interrupts */ |
| 670 | stm32_disable_ms(port); | 678 | stm32_usart_disable_ms(port); |
| 671 | 679 | ||
| 672 | val = USART_CR1_TXEIE | USART_CR1_TE; | 680 | val = USART_CR1_TXEIE | USART_CR1_TE; |
| 673 | val |= stm32_port->cr1_irq | USART_CR1_RE; | 681 | val |= stm32_port->cr1_irq | USART_CR1_RE; |
| @@ -679,15 +687,16 @@ static void stm32_shutdown(struct uart_port *port) · 5 unmodified lines | |||
| 679 | isr, (isr & USART_SR_TC), | 687 | isr, (isr & USART_SR_TC), |
| 680 | 10, 100000); | 688 | 10, 100000); |
| 681 | 689 | ||
| 690 | /* Send the TC error message only when ISR_TC is not set */ | ||
| 682 | if (ret) | 691 | if (ret) |
| 683 | dev_err(port->dev, "transmission complete not set\n"); | 692 | dev_err(port->dev, "Transmission is not complete\n"); |
| 684 | 693 | ||
| 685 | stm32_clr_bits(port, ofs->cr1, val); | 694 | stm32_usart_clr_bits(port, ofs->cr1, val); |
| 686 | 695 | ||
| 687 | free_irq(port->irq, port); | 696 | free_irq(port->irq, port); |
| 688 | } | 697 | } |
| 689 | 698 | ||
| 690 | static unsigned int stm32_get_databits(struct ktermios *termios) | 699 | static unsigned int stm32_usart_get_databits(struct ktermios *termios) |
| 691 | { | 700 | { |
| 692 | unsigned int bits; | 701 | unsigned int bits; |
| 693 | 702 | ||
| @@ -717,8 +726,9 @@ static unsigned int stm32_get_databits(struct ktermios *termios) · 23 unmodified lines | |||
| 717 | return bits; | 726 | return bits; |
| 718 | } | 727 | } |
| 719 | 728 | ||
| 720 | static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, | 729 | static void stm32_usart_set_termios(struct uart_port *port, |
| 721 | struct ktermios *old) | 730 | struct ktermios *termios, |
| 731 | struct ktermios *old) | ||
| 722 | { | 732 | { |
| 723 | struct stm32_port *stm32_port = to_stm32_port(port); | 733 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 724 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; | 734 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| @@ -742,8 +752,8 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, · 17 unmodified lines | |||
| 742 | 752 | ||
| 743 | /* flush RX & TX FIFO */ | 753 | /* flush RX & TX FIFO */ |
| 744 | if (ofs->rqr != UNDEF_REG) | 754 | if (ofs->rqr != UNDEF_REG) |
| 745 | stm32_set_bits(port, ofs->rqr, | 755 | stm32_usart_set_bits(port, ofs->rqr, |
| 746 | USART_RQR_TXFRQ | USART_RQR_RXFRQ); | 756 | USART_RQR_TXFRQ | USART_RQR_RXFRQ); |
| 747 | 757 | ||
| 748 | cr1 = USART_CR1_TE | USART_CR1_RE; | 758 | cr1 = USART_CR1_TE | USART_CR1_RE; |
| 749 | if (stm32_port->fifoen) | 759 | if (stm32_port->fifoen) |
| @@ -756,7 +766,7 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, · 6 unmodified lines | |||
| 756 | if (cflag & CSTOPB) | 766 | if (cflag & CSTOPB) |
| 757 | cr2 |= USART_CR2_STOP_2B; | 767 | cr2 |= USART_CR2_STOP_2B; |
| 758 | 768 | ||
| 759 | bits = stm32_get_databits(termios); | 769 | bits = stm32_usart_get_databits(termios); |
| 760 | stm32_port->rdr_mask = (BIT(bits) - 1); | 770 | stm32_port->rdr_mask = (BIT(bits) - 1); |
| 761 | 771 | ||
| 762 | if (cflag & PARENB) { | 772 | if (cflag & PARENB) { |
| @@ -809,9 +819,9 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, · 46 unmodified lines | |||
| 809 | 819 | ||
| 810 | /* Handle modem control interrupts */ | 820 | /* Handle modem control interrupts */ |
| 811 | if (UART_ENABLE_MS(port, termios->c_cflag)) | 821 | if (UART_ENABLE_MS(port, termios->c_cflag)) |
| 812 | stm32_enable_ms(port); | 822 | stm32_usart_enable_ms(port); |
| 813 | else | 823 | else |
| 814 | stm32_disable_ms(port); | 824 | stm32_usart_disable_ms(port); |
| 815 | 825 | ||
| 816 | usartdiv = DIV_ROUND_CLOSEST(port->uartclk, baud); | 826 | usartdiv = DIV_ROUND_CLOSEST(port->uartclk, baud); |
| 817 | 827 | ||
| @@ -824,11 +834,11 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, · 6 unmodified lines | |||
| 824 | if (usartdiv < 16) { | 834 | if (usartdiv < 16) { |
| 825 | oversampling = 8; | 835 | oversampling = 8; |
| 826 | cr1 |= USART_CR1_OVER8; | 836 | cr1 |= USART_CR1_OVER8; |
| 827 | stm32_set_bits(port, ofs->cr1, USART_CR1_OVER8); | 837 | stm32_usart_set_bits(port, ofs->cr1, USART_CR1_OVER8); |
| 828 | } else { | 838 | } else { |
| 829 | oversampling = 16; | 839 | oversampling = 16; |
| 830 | cr1 &= ~USART_CR1_OVER8; | 840 | cr1 &= ~USART_CR1_OVER8; |
| 831 | stm32_clr_bits(port, ofs->cr1, USART_CR1_OVER8); | 841 | stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_OVER8); |
| 832 | } | 842 | } |
| 833 | 843 | ||
| 834 | mantissa = (usartdiv / oversampling) << USART_BRR_DIV_M_SHIFT; | 844 | mantissa = (usartdiv / oversampling) << USART_BRR_DIV_M_SHIFT; |
| @@ -865,9 +875,10 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, · 30 unmodified lines | |||
| 865 | cr3 |= USART_CR3_DMAR; | 875 | cr3 |= USART_CR3_DMAR; |
| 866 | 876 | ||
| 867 | if (rs485conf->flags & SER_RS485_ENABLED) { | 877 | if (rs485conf->flags & SER_RS485_ENABLED) { |
| 868 | stm32_config_reg_rs485(&cr1, &cr3, | 878 | stm32_usart_config_reg_rs485(&cr1, &cr3, |
| 869 | rs485conf->delay_rts_before_send, | 879 | rs485conf->delay_rts_before_send, |
| 870 | rs485conf->delay_rts_after_send, baud); | 880 | rs485conf->delay_rts_after_send, |
| 881 | baud); | ||
| 871 | if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { | 882 | if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { |
| 872 | cr3 &= ~USART_CR3_DEP; | 883 | cr3 &= ~USART_CR3_DEP; |
| 873 | rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND; | 884 | rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND; |
| @@ -885,39 +896,39 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, · 11 unmodified lines | |||
| 885 | writel_relaxed(cr2, port->membase + ofs->cr2); | 896 | writel_relaxed(cr2, port->membase + ofs->cr2); |
| 886 | writel_relaxed(cr1, port->membase + ofs->cr1); | 897 | writel_relaxed(cr1, port->membase + ofs->cr1); |
| 887 | 898 | ||
| 888 | stm32_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit)); | 899 | stm32_usart_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit)); |
| 889 | spin_unlock_irqrestore(&port->lock, flags); | 900 | spin_unlock_irqrestore(&port->lock, flags); |
| 890 | } | 901 | } |
| 891 | 902 | ||
| 892 | static const char *stm32_type(struct uart_port *port) | 903 | static const char *stm32_usart_type(struct uart_port *port) |
| 893 | { | 904 | { |
| 894 | return (port->type == PORT_STM32) ? DRIVER_NAME : NULL; | 905 | return (port->type == PORT_STM32) ? DRIVER_NAME : NULL; |
| 895 | } | 906 | } |
| 896 | 907 | ||
| 897 | static void stm32_release_port(struct uart_port *port) | 908 | static void stm32_usart_release_port(struct uart_port *port) |
| 898 | { | 909 | { |
| 899 | } | 910 | } |
| 900 | 911 | ||
| 901 | static int stm32_request_port(struct uart_port *port) | 912 | static int stm32_usart_request_port(struct uart_port *port) |
| 902 | { | 913 | { |
| 903 | return 0; | 914 | return 0; |
| 904 | } | 915 | } |
| 905 | 916 | ||
| 906 | static void stm32_config_port(struct uart_port *port, int flags) | 917 | static void stm32_usart_config_port(struct uart_port *port, int flags) |
| 907 | { | 918 | { |
| 908 | if (flags & UART_CONFIG_TYPE) | 919 | if (flags & UART_CONFIG_TYPE) |
| 909 | port->type = PORT_STM32; | 920 | port->type = PORT_STM32; |
| 910 | } | 921 | } |
| 911 | 922 | ||
| 912 | static int | 923 | static int |
| 913 | stm32_verify_port(struct uart_port *port, struct serial_struct *ser) | 924 | stm32_usart_verify_port(struct uart_port *port, struct serial_struct *ser) |
| 914 | { | 925 | { |
| 915 | /* No user changeable parameters */ | 926 | /* No user changeable parameters */ |
| 916 | return -EINVAL; | 927 | return -EINVAL; |
| 917 | } | 928 | } |
| 918 | 929 | ||
| 919 | static void stm32_pm(struct uart_port *port, unsigned int state, | 930 | static void stm32_usart_pm(struct uart_port *port, unsigned int state, |
| 920 | unsigned int oldstate) | 931 | unsigned int oldstate) |
| 921 | { | 932 | { |
| 922 | struct stm32_port *stm32port = container_of(port, | 933 | struct stm32_port *stm32port = container_of(port, |
| 923 | struct stm32_port, port); | 934 | struct stm32_port, port); |
| @@ -931,7 +942,7 @@ static void stm32_pm(struct uart_port *port, unsigned int state, · 7 unmodified lines | |||
| 931 | break; | 942 | break; |
| 932 | case UART_PM_STATE_OFF: | 943 | case UART_PM_STATE_OFF: |
| 933 | spin_lock_irqsave(&port->lock, flags); | 944 | spin_lock_irqsave(&port->lock, flags); |
| 934 | stm32_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit)); | 945 | stm32_usart_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit)); |
| 935 | spin_unlock_irqrestore(&port->lock, flags); | 946 | spin_unlock_irqrestore(&port->lock, flags); |
| 936 | pm_runtime_put_sync(port->dev); | 947 | pm_runtime_put_sync(port->dev); |
| 937 | break; | 948 | break; |
| @@ -939,33 +950,42 @@ static void stm32_pm(struct uart_port *port, unsigned int state, · 1 unmodified line | |||
| 939 | } | 950 | } |
| 940 | 951 | ||
| 941 | static const struct uart_ops stm32_uart_ops = { | 952 | static const struct uart_ops stm32_uart_ops = { |
| 942 | .tx_empty = stm32_tx_empty, | 953 | .tx_empty = stm32_usart_tx_empty, |
| 943 | .set_mctrl = stm32_set_mctrl, | 954 | .set_mctrl = stm32_usart_set_mctrl, |
| 944 | .get_mctrl = stm32_get_mctrl, | 955 | .get_mctrl = stm32_usart_get_mctrl, |
| 945 | .stop_tx = stm32_stop_tx, | 956 | .stop_tx = stm32_usart_stop_tx, |
| 946 | .start_tx = stm32_start_tx, | 957 | .start_tx = stm32_usart_start_tx, |
| 947 | .throttle = stm32_throttle, | 958 | .throttle = stm32_usart_throttle, |
| 948 | .unthrottle = stm32_unthrottle, | 959 | .unthrottle = stm32_usart_unthrottle, |
| 949 | .stop_rx = stm32_stop_rx, | 960 | .stop_rx = stm32_usart_stop_rx, |
| 950 | .enable_ms = stm32_enable_ms, | 961 | .enable_ms = stm32_usart_enable_ms, |
| 951 | .break_ctl = stm32_break_ctl, | 962 | .break_ctl = stm32_usart_break_ctl, |
| 952 | .startup = stm32_startup, | 963 | .startup = stm32_usart_startup, |
| 953 | .shutdown = stm32_shutdown, | 964 | .shutdown = stm32_usart_shutdown, |
| 954 | .set_termios = stm32_set_termios, | 965 | .set_termios = stm32_usart_set_termios, |
| 955 | .pm = stm32_pm, | 966 | .pm = stm32_usart_pm, |
| 956 | .type = stm32_type, | 967 | .type = stm32_usart_type, |
| 957 | .release_port = stm32_release_port, | 968 | .release_port = stm32_usart_release_port, |
| 958 | .request_port = stm32_request_port, | 969 | .request_port = stm32_usart_request_port, |
| 959 | .config_port = stm32_config_port, | 970 | .config_port = stm32_usart_config_port, |
| 960 | .verify_port = stm32_verify_port, | 971 | .verify_port = stm32_usart_verify_port, |
| 961 | }; | 972 | }; |
| 962 | 973 | ||
| 963 | static int stm32_init_port(struct stm32_port *stm32port, | 974 | static void stm32_usart_deinit_port(struct stm32_port *stm32port) |
| 964 | struct platform_device *pdev) | 975 | { |
| 976 | clk_disable_unprepare(stm32port->clk); | ||
| 977 | } | ||
| 978 | |||
| 979 | static int stm32_usart_init_port(struct stm32_port *stm32port, | ||
| 980 | struct platform_device *pdev) | ||
| 965 | { | 981 | { |
| 966 | struct uart_port *port = &stm32port->port; | 982 | struct uart_port *port = &stm32port->port; |
| 967 | struct resource *res; | 983 | struct resource *res; |
| 968 | int ret; | 984 | int ret, irq; |
| 985 | |||
| 986 | irq = platform_get_irq(pdev, 0); | ||
| 987 | if (irq <= 0) | ||
| 988 | return irq ? : -ENODEV; | ||
| 969 | 989 | ||
| 970 | port->iotype = UPIO_MEM; | 990 | port->iotype = UPIO_MEM; |
| 971 | port->flags = UPF_BOOT_AUTOCONF; | 991 | port->flags = UPF_BOOT_AUTOCONF; |
| @@ -973,15 +993,10 @@ static int stm32_init_port(struct stm32_port *stm32port, · 1 unmodified line | |||
| 973 | port->dev = &pdev->dev; | 993 | port->dev = &pdev->dev; |
| 974 | port->fifosize = stm32port->info->cfg.fifosize; | 994 | port->fifosize = stm32port->info->cfg.fifosize; |
| 975 | port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_STM32_CONSOLE); | 995 | port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_STM32_CONSOLE); |
| 996 | port->irq = irq; | ||
| 997 | port->rs485_config = stm32_usart_config_rs485; | ||
| 976 | 998 | ||
| 977 | ret = platform_get_irq(pdev, 0); | 999 | ret = stm32_usart_init_rs485(port, pdev); |
| 978 | if (ret <= 0) | ||
| 979 | return ret ? : -ENODEV; | ||
| 980 | port->irq = ret; | ||
| 981 | |||
| 982 | port->rs485_config = stm32_config_rs485; | ||
| 983 | |||
| 984 | ret = stm32_init_rs485(port, pdev); | ||
| 985 | if (ret) | 1000 | if (ret) |
| 986 | return ret; | 1001 | return ret; |
| 987 | 1002 | ||
| @@ -1022,7 +1037,10 @@ static int stm32_init_port(struct stm32_port *stm32port, · 34 unmodified lines | |||
| 1022 | goto err_clk; | 1037 | goto err_clk; |
| 1023 | } | 1038 | } |
| 1024 | 1039 | ||
| 1025 | /* Both CTS/RTS gpios and "st,hw-flow-ctrl" should not be specified */ | 1040 | /* |
| 1041 | * Both CTS/RTS gpios and "st,hw-flow-ctrl" (deprecated) or "uart-has-rtscts" | ||
| 1042 | * properties should not be specified. | ||
| 1043 | */ | ||
| 1026 | if (stm32port->hw_flow_control) { | 1044 | if (stm32port->hw_flow_control) { |
| 1027 | if (mctrl_gpio_to_gpiod(stm32port->gpios, UART_GPIO_CTS) || | 1045 | if (mctrl_gpio_to_gpiod(stm32port->gpios, UART_GPIO_CTS) || |
| 1028 | mctrl_gpio_to_gpiod(stm32port->gpios, UART_GPIO_RTS)) { | 1046 | mctrl_gpio_to_gpiod(stm32port->gpios, UART_GPIO_RTS)) { |
| @@ -1040,7 +1058,7 @@ err_clk: · 11 unmodified lines | |||
| 1040 | return ret; | 1058 | return ret; |
| 1041 | } | 1059 | } |
| 1042 | 1060 | ||
| 1043 | static struct stm32_port *stm32_of_get_stm32_port(struct platform_device *pdev) | 1061 | static struct stm32_port *stm32_usart_of_get_port(struct platform_device *pdev) |
| 1044 | { | 1062 | { |
| 1045 | struct device_node *np = pdev->dev.of_node; | 1063 | struct device_node *np = pdev->dev.of_node; |
| 1046 | int id; | 1064 | int id; |
| @@ -1078,8 +1096,8 @@ static const struct of_device_id stm32_match[] = { · 31 unmodified lines | |||
| 1078 | MODULE_DEVICE_TABLE(of, stm32_match); | 1096 | MODULE_DEVICE_TABLE(of, stm32_match); |
| 1079 | #endif | 1097 | #endif |
| 1080 | 1098 | ||
| 1081 | static int stm32_of_dma_rx_probe(struct stm32_port *stm32port, | 1099 | static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port, |
| 1082 | struct platform_device *pdev) | 1100 | struct platform_device *pdev) |
| 1083 | { | 1101 | { |
| 1084 | struct stm32_usart_offsets *ofs = &stm32port->info->ofs; | 1102 | struct stm32_usart_offsets *ofs = &stm32port->info->ofs; |
| 1085 | struct uart_port *port = &stm32port->port; | 1103 | struct uart_port *port = &stm32port->port; |
| @@ -1095,8 +1113,8 @@ static int stm32_of_dma_rx_probe(struct stm32_port *stm32port, · 9 unmodified lines | |||
| 1095 | return -ENODEV; | 1113 | return -ENODEV; |
| 1096 | } | 1114 | } |
| 1097 | stm32port->rx_buf = dma_alloc_coherent(&pdev->dev, RX_BUF_L, | 1115 | stm32port->rx_buf = dma_alloc_coherent(&pdev->dev, RX_BUF_L, |
| 1098 | &stm32port->rx_dma_buf, | 1116 | &stm32port->rx_dma_buf, |
| 1099 | GFP_KERNEL); | 1117 | GFP_KERNEL); |
| 1100 | if (!stm32port->rx_buf) { | 1118 | if (!stm32port->rx_buf) { |
| 1101 | ret = -ENOMEM; | 1119 | ret = -ENOMEM; |
| 1102 | goto alloc_err; | 1120 | goto alloc_err; |
| @@ -1130,7 +1148,11 @@ static int stm32_of_dma_rx_probe(struct stm32_port *stm32port, · 27 unmodified lines | |||
| 1130 | desc->callback_param = NULL; | 1148 | desc->callback_param = NULL; |
| 1131 | 1149 | ||
| 1132 | /* Push current DMA transaction in the pending queue */ | 1150 | /* Push current DMA transaction in the pending queue */ |
| 1133 | dmaengine_submit(desc); | 1151 | ret = dma_submit_error(dmaengine_submit(desc)); |
| 1152 | if (ret) { | ||
| 1153 | dmaengine_terminate_sync(stm32port->rx_ch); | ||
| 1154 | goto config_err; | ||
| 1155 | } | ||
| 1134 | 1156 | ||
| 1135 | /* Issue pending DMA requests */ | 1157 | /* Issue pending DMA requests */ |
| 1136 | dma_async_issue_pending(stm32port->rx_ch); | 1158 | dma_async_issue_pending(stm32port->rx_ch); |
| @@ -1149,8 +1171,8 @@ alloc_err: · 12 unmodified lines | |||
| 1149 | return ret; | 1171 | return ret; |
| 1150 | } | 1172 | } |
| 1151 | 1173 | ||
| 1152 | static int stm32_of_dma_tx_probe(struct stm32_port *stm32port, | 1174 | static int stm32_usart_of_dma_tx_probe(struct stm32_port *stm32port, |
| 1153 | struct platform_device *pdev) | 1175 | struct platform_device *pdev) |
| 1154 | { | 1176 | { |
| 1155 | struct stm32_usart_offsets *ofs = &stm32port->info->ofs; | 1177 | struct stm32_usart_offsets *ofs = &stm32port->info->ofs; |
| 1156 | struct uart_port *port = &stm32port->port; | 1178 | struct uart_port *port = &stm32port->port; |
| @@ -1167,8 +1189,8 @@ static int stm32_of_dma_tx_probe(struct stm32_port *stm32port, · 10 unmodified lines | |||
| 1167 | return -ENODEV; | 1189 | return -ENODEV; |
| 1168 | } | 1190 | } |
| 1169 | stm32port->tx_buf = dma_alloc_coherent(&pdev->dev, TX_BUF_L, | 1191 | stm32port->tx_buf = dma_alloc_coherent(&pdev->dev, TX_BUF_L, |
| 1170 | &stm32port->tx_dma_buf, | 1192 | &stm32port->tx_dma_buf, |
| 1171 | GFP_KERNEL); | 1193 | GFP_KERNEL); |
| 1172 | if (!stm32port->tx_buf) { | 1194 | if (!stm32port->tx_buf) { |
| 1173 | ret = -ENOMEM; | 1195 | ret = -ENOMEM; |
| 1174 | goto alloc_err; | 1196 | goto alloc_err; |
| @@ -1200,13 +1222,13 @@ alloc_err: · 25 unmodified lines | |||
| 1200 | return ret; | 1222 | return ret; |
| 1201 | } | 1223 | } |
| 1202 | 1224 | ||
| 1203 | static int stm32_serial_probe(struct platform_device *pdev) | 1225 | static int stm32_usart_serial_probe(struct platform_device *pdev) |
| 1204 | { | 1226 | { |
| 1205 | const struct of_device_id *match; | 1227 | const struct of_device_id *match; |
| 1206 | struct stm32_port *stm32port; | 1228 | struct stm32_port *stm32port; |
| 1207 | int ret; | 1229 | int ret; |
| 1208 | 1230 | ||
| 1209 | stm32port = stm32_of_get_stm32_port(pdev); | 1231 | stm32port = stm32_usart_of_get_port(pdev); |
| 1210 | if (!stm32port) | 1232 | if (!stm32port) |
| 1211 | return -ENODEV; | 1233 | return -ENODEV; |
| 1212 | 1234 | ||
| @@ -1216,7 +1238,7 @@ static int stm32_serial_probe(struct platform_device *pdev) · 3 unmodified lines | |||
| 1216 | else | 1238 | else |
| 1217 | return -EINVAL; | 1239 | return -EINVAL; |
| 1218 | 1240 | ||
| 1219 | ret = stm32_init_port(stm32port, pdev); | 1241 | ret = stm32_usart_init_port(stm32port, pdev); |
| 1220 | if (ret) | 1242 | if (ret) |
| 1221 | return ret; | 1243 | return ret; |
| 1222 | 1244 | ||
| @@ -1237,11 +1259,11 @@ static int stm32_serial_probe(struct platform_device *pdev) · 14 unmodified lines | |||
| 1237 | if (ret) | 1259 | if (ret) |
| 1238 | goto err_wirq; | 1260 | goto err_wirq; |
| 1239 | 1261 | ||
| 1240 | ret = stm32_of_dma_rx_probe(stm32port, pdev); | 1262 | ret = stm32_usart_of_dma_rx_probe(stm32port, pdev); |
| 1241 | if (ret) | 1263 | if (ret) |
| 1242 | dev_info(&pdev->dev, "interrupt mode used for rx (no dma)\n"); | 1264 | dev_info(&pdev->dev, "interrupt mode used for rx (no dma)\n"); |
| 1243 | 1265 | ||
| 1244 | ret = stm32_of_dma_tx_probe(stm32port, pdev); | 1266 | ret = stm32_usart_of_dma_tx_probe(stm32port, pdev); |
| 1245 | if (ret) | 1267 | if (ret) |
| 1246 | dev_info(&pdev->dev, "interrupt mode used for tx (no dma)\n"); | 1268 | dev_info(&pdev->dev, "interrupt mode used for tx (no dma)\n"); |
| 1247 | 1269 | ||
| @@ -1263,12 +1285,12 @@ err_nowup: · 15 unmodified lines | |||
| 1263 | device_init_wakeup(&pdev->dev, false); | 1285 | device_init_wakeup(&pdev->dev, false); |
| 1264 | 1286 | ||
| 1265 | err_uninit: | 1287 | err_uninit: |
| 1266 | clk_disable_unprepare(stm32port->clk); | 1288 | stm32_usart_deinit_port(stm32port); |
| 1267 | 1289 | ||
| 1268 | return ret; | 1290 | return ret; |
| 1269 | } | 1291 | } |
| 1270 | 1292 | ||
| 1271 | static int stm32_serial_remove(struct platform_device *pdev) | 1293 | static int stm32_usart_serial_remove(struct platform_device *pdev) |
| 1272 | { | 1294 | { |
| 1273 | struct uart_port *port = platform_get_drvdata(pdev); | 1295 | struct uart_port *port = platform_get_drvdata(pdev); |
| 1274 | struct stm32_port *stm32_port = to_stm32_port(port); | 1296 | struct stm32_port *stm32_port = to_stm32_port(port); |
| @@ -1277,7 +1299,7 @@ static int stm32_serial_remove(struct platform_device *pdev) · 2 unmodified lines | |||
| 1277 | 1299 | ||
| 1278 | pm_runtime_get_sync(&pdev->dev); | 1300 | pm_runtime_get_sync(&pdev->dev); |
| 1279 | 1301 | ||
| 1280 | stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAR); | 1302 | stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR); |
| 1281 | 1303 | ||
| 1282 | if (stm32_port->rx_ch) | 1304 | if (stm32_port->rx_ch) |
| 1283 | dma_release_channel(stm32_port->rx_ch); | 1305 | dma_release_channel(stm32_port->rx_ch); |
| @@ -1287,7 +1309,7 @@ static int stm32_serial_remove(struct platform_device *pdev) · 3 unmodified lines | |||
| 1287 | RX_BUF_L, stm32_port->rx_buf, | 1309 | RX_BUF_L, stm32_port->rx_buf, |
| 1288 | stm32_port->rx_dma_buf); | 1310 | stm32_port->rx_dma_buf); |
| 1289 | 1311 | ||
| 1290 | stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAT); | 1312 | stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); |
| 1291 | 1313 | ||
| 1292 | if (stm32_port->tx_ch) | 1314 | if (stm32_port->tx_ch) |
| 1293 | dma_release_channel(stm32_port->tx_ch); | 1315 | dma_release_channel(stm32_port->tx_ch); |
| @@ -1302,7 +1324,7 @@ static int stm32_serial_remove(struct platform_device *pdev) · 8 unmodified lines | |||
| 1302 | device_init_wakeup(&pdev->dev, false); | 1324 | device_init_wakeup(&pdev->dev, false); |
| 1303 | } | 1325 | } |
| 1304 | 1326 | ||
| 1305 | clk_disable_unprepare(stm32_port->clk); | 1327 | stm32_usart_deinit_port(stm32_port); |
| 1306 | 1328 | ||
| 1307 | err = uart_remove_one_port(&stm32_usart_driver, port); | 1329 | err = uart_remove_one_port(&stm32_usart_driver, port); |
| 1308 | 1330 | ||
| @@ -1312,9 +1334,8 @@ static int stm32_serial_remove(struct platform_device *pdev) · 3 unmodified lines | |||
| 1312 | return err; | 1334 | return err; |
| 1313 | } | 1335 | } |
| 1314 | 1336 | ||
| 1315 | |||
| 1316 | #ifdef CONFIG_SERIAL_STM32_CONSOLE | 1337 | #ifdef CONFIG_SERIAL_STM32_CONSOLE |
| 1317 | static void stm32_console_putchar(struct uart_port *port, int ch) | 1338 | static void stm32_usart_console_putchar(struct uart_port *port, int ch) |
| 1318 | { | 1339 | { |
| 1319 | struct stm32_port *stm32_port = to_stm32_port(port); | 1340 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 1320 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; | 1341 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| @@ -1325,7 +1346,8 @@ static void stm32_console_putchar(struct uart_port *port, int ch) · 4 unmodified lines | |||
| 1325 | writel_relaxed(ch, port->membase + ofs->tdr); | 1346 | writel_relaxed(ch, port->membase + ofs->tdr); |
| 1326 | } | 1347 | } |
| 1327 | 1348 | ||
| 1328 | static void stm32_console_write(struct console *co, const char *s, unsigned cnt) | 1349 | static void stm32_usart_console_write(struct console *co, const char *s, |
| 1350 | unsigned int cnt) | ||
| 1329 | { | 1351 | { |
| 1330 | struct uart_port *port = &stm32_ports[co->index].port; | 1352 | struct uart_port *port = &stm32_ports[co->index].port; |
| 1331 | struct stm32_port *stm32_port = to_stm32_port(port); | 1353 | struct stm32_port *stm32_port = to_stm32_port(port); |
| @@ -1349,7 +1371,7 @@ static void stm32_console_write(struct console *co, const char *s, unsigned cnt) · 17 unmodified lines | |||
| 1349 | new_cr1 |= USART_CR1_TE | BIT(cfg->uart_enable_bit); | 1371 | new_cr1 |= USART_CR1_TE | BIT(cfg->uart_enable_bit); |
| 1350 | writel_relaxed(new_cr1, port->membase + ofs->cr1); | 1372 | writel_relaxed(new_cr1, port->membase + ofs->cr1); |
| 1351 | 1373 | ||
| 1352 | uart_console_write(port, s, cnt, stm32_console_putchar); | 1374 | uart_console_write(port, s, cnt, stm32_usart_console_putchar); |
| 1353 | 1375 | ||
| 1354 | /* Restore interrupt state */ | 1376 | /* Restore interrupt state */ |
| 1355 | writel_relaxed(old_cr1, port->membase + ofs->cr1); | 1377 | writel_relaxed(old_cr1, port->membase + ofs->cr1); |
| @@ -1359,7 +1381,7 @@ static void stm32_console_write(struct console *co, const char *s, unsigned cnt) · 3 unmodified lines | |||
| 1359 | local_irq_restore(flags); | 1381 | local_irq_restore(flags); |
| 1360 | } | 1382 | } |
| 1361 | 1383 | ||
| 1362 | static int stm32_console_setup(struct console *co, char *options) | 1384 | static int stm32_usart_console_setup(struct console *co, char *options) |
| 1363 | { | 1385 | { |
| 1364 | struct stm32_port *stm32port; | 1386 | struct stm32_port *stm32port; |
| 1365 | int baud = 9600; | 1387 | int baud = 9600; |
| @@ -1378,7 +1400,7 @@ static int stm32_console_setup(struct console *co, char *options) · 12 unmodified lines | |||
| 1378 | * this to be called during the uart port registration when the | 1400 | * this to be called during the uart port registration when the |
| 1379 | * driver gets probed and the port should be mapped at that point. | 1401 | * driver gets probed and the port should be mapped at that point. |
| 1380 | */ | 1402 | */ |
| 1381 | if (stm32port->port.mapbase == 0 || stm32port->port.membase == NULL) | 1403 | if (stm32port->port.mapbase == 0 || !stm32port->port.membase) |
| 1382 | return -ENXIO; | 1404 | return -ENXIO; |
| 1383 | 1405 | ||
| 1384 | if (options) | 1406 | if (options) |
| @@ -1390,8 +1412,8 @@ static int stm32_console_setup(struct console *co, char *options) · 5 unmodified lines | |||
| 1390 | static struct console stm32_console = { | 1412 | static struct console stm32_console = { |
| 1391 | .name = STM32_SERIAL_NAME, | 1413 | .name = STM32_SERIAL_NAME, |
| 1392 | .device = uart_console_device, | 1414 | .device = uart_console_device, |
| 1393 | .write = stm32_console_write, | 1415 | .write = stm32_usart_console_write, |
| 1394 | .setup = stm32_console_setup, | 1416 | .setup = stm32_usart_console_setup, |
| 1395 | .flags = CON_PRINTBUFFER, | 1417 | .flags = CON_PRINTBUFFER, |
| 1396 | .index = -1, | 1418 | .index = -1, |
| 1397 | .data = &stm32_usart_driver, | 1419 | .data = &stm32_usart_driver, |
| @@ -1412,8 +1434,8 @@ static struct uart_driver stm32_usart_driver = { · 14 unmodified lines | |||
| 1412 | .cons = STM32_SERIAL_CONSOLE, | 1434 | .cons = STM32_SERIAL_CONSOLE, |
| 1413 | }; | 1435 | }; |
| 1414 | 1436 | ||
| 1415 | static void __maybe_unused stm32_serial_enable_wakeup(struct uart_port *port, | 1437 | static void __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port, |
| 1416 | bool enable) | 1438 | bool enable) |
| 1417 | { | 1439 | { |
| 1418 | struct stm32_port *stm32_port = to_stm32_port(port); | 1440 | struct stm32_port *stm32_port = to_stm32_port(port); |
| 1419 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; | 1441 | struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; |
| @@ -1424,29 +1446,29 @@ static void __maybe_unused stm32_serial_enable_wakeup(struct uart_port *port, · 4 unmodified lines | |||
| 1424 | return; | 1446 | return; |
| 1425 | 1447 | ||
| 1426 | if (enable) { | 1448 | if (enable) { |
| 1427 | stm32_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit)); | 1449 | stm32_usart_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit)); |
| 1428 | stm32_set_bits(port, ofs->cr1, USART_CR1_UESM); | 1450 | stm32_usart_set_bits(port, ofs->cr1, USART_CR1_UESM); |
| 1429 | val = readl_relaxed(port->membase + ofs->cr3); | 1451 | val = readl_relaxed(port->membase + ofs->cr3); |
| 1430 | val &= ~USART_CR3_WUS_MASK; | 1452 | val &= ~USART_CR3_WUS_MASK; |
| 1431 | /* Enable Wake up interrupt from low power on start bit */ | 1453 | /* Enable Wake up interrupt from low power on start bit */ |
| 1432 | val |= USART_CR3_WUS_START_BIT | USART_CR3_WUFIE; | 1454 | val |= USART_CR3_WUS_START_BIT | USART_CR3_WUFIE; |
| 1433 | writel_relaxed(val, port->membase + ofs->cr3); | 1455 | writel_relaxed(val, port->membase + ofs->cr3); |
| 1434 | stm32_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit)); | 1456 | stm32_usart_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit)); |
| 1435 | } else { | 1457 | } else { |
| 1436 | stm32_clr_bits(port, ofs->cr1, USART_CR1_UESM); | 1458 | stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_UESM); |
| 1437 | } | 1459 | } |
| 1438 | } | 1460 | } |
| 1439 | 1461 | ||
| 1440 | static int __maybe_unused stm32_serial_suspend(struct device *dev) | 1462 | static int __maybe_unused stm32_usart_serial_suspend(struct device *dev) |
| 1441 | { | 1463 | { |
| 1442 | struct uart_port *port = dev_get_drvdata(dev); | 1464 | struct uart_port *port = dev_get_drvdata(dev); |
| 1443 | 1465 | ||
| 1444 | uart_suspend_port(&stm32_usart_driver, port); | 1466 | uart_suspend_port(&stm32_usart_driver, port); |
| 1445 | 1467 | ||
| 1446 | if (device_may_wakeup(dev)) | 1468 | if (device_may_wakeup(dev)) |
| 1447 | stm32_serial_enable_wakeup(port, true); | 1469 | stm32_usart_serial_en_wakeup(port, true); |
| 1448 | else | 1470 | else |
| 1449 | stm32_serial_enable_wakeup(port, false); | 1471 | stm32_usart_serial_en_wakeup(port, false); |
| 1450 | 1472 | ||
| 1451 | /* | 1473 | /* |
| 1452 | * When "no_console_suspend" is enabled, keep the pinctrl default state | 1474 | * When "no_console_suspend" is enabled, keep the pinctrl default state |
| @@ -1464,19 +1486,19 @@ static int __maybe_unused stm32_serial_suspend(struct device *dev) · 11 unmodified lines | |||
| 1464 | return 0; | 1486 | return 0; |
| 1465 | } | 1487 | } |
| 1466 | 1488 | ||
| 1467 | static int __maybe_unused stm32_serial_resume(struct device *dev) | 1489 | static int __maybe_unused stm32_usart_serial_resume(struct device *dev) |
| 1468 | { | 1490 | { |
| 1469 | struct uart_port *port = dev_get_drvdata(dev); | 1491 | struct uart_port *port = dev_get_drvdata(dev); |
| 1470 | 1492 | ||
| 1471 | pinctrl_pm_select_default_state(dev); | 1493 | pinctrl_pm_select_default_state(dev); |
| 1472 | 1494 | ||
| 1473 | if (device_may_wakeup(dev)) | 1495 | if (device_may_wakeup(dev)) |
| 1474 | stm32_serial_enable_wakeup(port, false); | 1496 | stm32_usart_serial_en_wakeup(port, false); |
| 1475 | 1497 | ||
| 1476 | return uart_resume_port(&stm32_usart_driver, port); | 1498 | return uart_resume_port(&stm32_usart_driver, port); |
| 1477 | } | 1499 | } |
| 1478 | 1500 | ||
| 1479 | static int __maybe_unused stm32_serial_runtime_suspend(struct device *dev) | 1501 | static int __maybe_unused stm32_usart_runtime_suspend(struct device *dev) |
| 1480 | { | 1502 | { |
| 1481 | struct uart_port *port = dev_get_drvdata(dev); | 1503 | struct uart_port *port = dev_get_drvdata(dev); |
| 1482 | struct stm32_port *stm32port = container_of(port, | 1504 | struct stm32_port *stm32port = container_of(port, |
| @@ -1487,7 +1509,7 @@ static int __maybe_unused stm32_serial_runtime_suspend(struct device *dev) · 4 unmodified lines | |||
| 1487 | return 0; | 1509 | return 0; |
| 1488 | } | 1510 | } |
| 1489 | 1511 | ||
| 1490 | static int __maybe_unused stm32_serial_runtime_resume(struct device *dev) | 1512 | static int __maybe_unused stm32_usart_runtime_resume(struct device *dev) |
| 1491 | { | 1513 | { |
| 1492 | struct uart_port *port = dev_get_drvdata(dev); | 1514 | struct uart_port *port = dev_get_drvdata(dev); |
| 1493 | struct stm32_port *stm32port = container_of(port, | 1515 | struct stm32_port *stm32port = container_of(port, |
| @@ -1497,14 +1519,15 @@ static int __maybe_unused stm32_serial_runtime_resume(struct device *dev) · 3 unmodified lines | |||
| 1497 | } | 1519 | } |
| 1498 | 1520 | ||
| 1499 | static const struct dev_pm_ops stm32_serial_pm_ops = { | 1521 | static const struct dev_pm_ops stm32_serial_pm_ops = { |
| 1500 | SET_RUNTIME_PM_OPS(stm32_serial_runtime_suspend, | 1522 | SET_RUNTIME_PM_OPS(stm32_usart_runtime_suspend, |
| 1501 | stm32_serial_runtime_resume, NULL) | 1523 | stm32_usart_runtime_resume, NULL) |
| 1502 | SET_SYSTEM_SLEEP_PM_OPS(stm32_serial_suspend, stm32_serial_resume) | 1524 | SET_SYSTEM_SLEEP_PM_OPS(stm32_usart_serial_suspend, |
| 1525 | stm32_usart_serial_resume) | ||
| 1503 | }; | 1526 | }; |
| 1504 | 1527 | ||
| 1505 | static struct platform_driver stm32_serial_driver = { | 1528 | static struct platform_driver stm32_serial_driver = { |
| 1506 | .probe = stm32_serial_probe, | 1529 | .probe = stm32_usart_serial_probe, |
| 1507 | .remove = stm32_serial_remove, | 1530 | .remove = stm32_usart_serial_remove, |
| 1508 | .driver = { | 1531 | .driver = { |
| 1509 | .name = DRIVER_NAME, | 1532 | .name = DRIVER_NAME, |
| 1510 | .pm = &stm32_serial_pm_ops, | 1533 | .pm = &stm32_serial_pm_ops, |
| @@ -1512,7 +1535,7 @@ static struct platform_driver stm32_serial_driver = { · 1 unmodified line | |||
| 1512 | }, | 1535 | }, |
| 1513 | }; | 1536 | }; |
| 1514 | 1537 | ||
| 1515 | static int __init usart_init(void) | 1538 | static int __init stm32_usart_init(void) |
| 1516 | { | 1539 | { |
| 1517 | static char banner[] __initdata = "STM32 USART driver initialized"; | 1540 | static char banner[] __initdata = "STM32 USART driver initialized"; |
| 1518 | int ret; | 1541 | int ret; |
| @@ -1530,14 +1553,14 @@ static int __init usart_init(void) · 11 unmodified lines | |||
| 1530 | return ret; | 1553 | return ret; |
| 1531 | } | 1554 | } |
| 1532 | 1555 | ||
| 1533 | static void __exit usart_exit(void) | 1556 | static void __exit stm32_usart_exit(void) |
| 1534 | { | 1557 | { |
| 1535 | platform_driver_unregister(&stm32_serial_driver); | 1558 | platform_driver_unregister(&stm32_serial_driver); |
| 1536 | uart_unregister_driver(&stm32_usart_driver); | 1559 | uart_unregister_driver(&stm32_usart_driver); |
| 1537 | } | 1560 | } |
| 1538 | 1561 | ||
| 1539 | module_init(usart_init); | 1562 | module_init(stm32_usart_init); |
| 1540 | module_exit(usart_exit); | 1563 | module_exit(stm32_usart_exit); |
| 1541 | 1564 | ||
| 1542 | MODULE_ALIAS("platform:" DRIVER_NAME); | 1565 | MODULE_ALIAS("platform:" DRIVER_NAME); |
| 1543 | MODULE_DESCRIPTION("STMicroelectronics STM32 serial port driver"); | 1566 | MODULE_DESCRIPTION("STMicroelectronics STM32 serial port driver"); |
| @@ -672,7 +672,6 @@ static int open(struct tty_struct *tty, struct file *filp) · 671 unmodified lines | |||
| 672 | DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count)); | 672 | DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count)); |
| 673 | 673 | ||
| 674 | mutex_lock(&info->port.mutex); | 674 | mutex_lock(&info->port.mutex); |
| 675 | info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; | ||
| 676 | 675 | ||
| 677 | spin_lock_irqsave(&info->netlock, flags); | 676 | spin_lock_irqsave(&info->netlock, flags); |
| 678 | if (info->netcount) { | 677 | if (info->netcount) { |
| @@ -142,7 +142,7 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */ · 141 unmodified lines | |||
| 142 | /* Mutex to protect creating and releasing a tty */ | 142 | /* Mutex to protect creating and releasing a tty */ |
| 143 | DEFINE_MUTEX(tty_mutex); | 143 | DEFINE_MUTEX(tty_mutex); |
| 144 | 144 | ||
| 145 | static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); | 145 | static ssize_t tty_read(struct kiocb *, struct iov_iter *); |
| 146 | static ssize_t tty_write(struct kiocb *, struct iov_iter *); | 146 | static ssize_t tty_write(struct kiocb *, struct iov_iter *); |
| 147 | static __poll_t tty_poll(struct file *, poll_table *); | 147 | static __poll_t tty_poll(struct file *, poll_table *); |
| 148 | static int tty_open(struct inode *, struct file *); | 148 | static int tty_open(struct inode *, struct file *); |
| @@ -429,8 +429,7 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) · 280 unmodified lines | |||
| 429 | EXPORT_SYMBOL_GPL(tty_find_polling_driver); | 429 | EXPORT_SYMBOL_GPL(tty_find_polling_driver); |
| 430 | #endif | 430 | #endif |
| 431 | 431 | ||
| 432 | static ssize_t hung_up_tty_read(struct file *file, char __user *buf, | 432 | static ssize_t hung_up_tty_read(struct kiocb *iocb, struct iov_iter *to) |
| 433 | size_t count, loff_t *ppos) | ||
| 434 | { | 433 | { |
| 435 | return 0; | 434 | return 0; |
| 436 | } | 435 | } |
| @@ -473,8 +472,9 @@ static void tty_show_fdinfo(struct seq_file *m, struct file *file) · 36 unmodified lines | |||
| 473 | 472 | ||
| 474 | static const struct file_operations tty_fops = { | 473 | static const struct file_operations tty_fops = { |
| 475 | .llseek = no_llseek, | 474 | .llseek = no_llseek, |
| 476 | .read = tty_read, | 475 | .read_iter = tty_read, |
| 477 | .write_iter = tty_write, | 476 | .write_iter = tty_write, |
| 477 | .splice_read = generic_file_splice_read, | ||
| 478 | .splice_write = iter_file_splice_write, | 478 | .splice_write = iter_file_splice_write, |
| 479 | .poll = tty_poll, | 479 | .poll = tty_poll, |
| 480 | .unlocked_ioctl = tty_ioctl, | 480 | .unlocked_ioctl = tty_ioctl, |
| @@ -487,8 +487,9 @@ static const struct file_operations tty_fops = { · 6 unmodified lines | |||
| 487 | 487 | ||
| 488 | static const struct file_operations console_fops = { | 488 | static const struct file_operations console_fops = { |
| 489 | .llseek = no_llseek, | 489 | .llseek = no_llseek, |
| 490 | .read = tty_read, | 490 | .read_iter = tty_read, |
| 491 | .write_iter = redirected_tty_write, | 491 | .write_iter = redirected_tty_write, |
| 492 | .splice_read = generic_file_splice_read, | ||
| 492 | .splice_write = iter_file_splice_write, | 493 | .splice_write = iter_file_splice_write, |
| 493 | .poll = tty_poll, | 494 | .poll = tty_poll, |
| 494 | .unlocked_ioctl = tty_ioctl, | 495 | .unlocked_ioctl = tty_ioctl, |
| @@ -500,7 +501,7 @@ static const struct file_operations console_fops = { · 5 unmodified lines | |||
| 500 | 501 | ||
| 501 | static const struct file_operations hung_up_tty_fops = { | 502 | static const struct file_operations hung_up_tty_fops = { |
| 502 | .llseek = no_llseek, | 503 | .llseek = no_llseek, |
| 503 | .read = hung_up_tty_read, | 504 | .read_iter = hung_up_tty_read, |
| 504 | .write_iter = hung_up_tty_write, | 505 | .write_iter = hung_up_tty_write, |
| 505 | .poll = hung_up_tty_poll, | 506 | .poll = hung_up_tty_poll, |
| 506 | .unlocked_ioctl = hung_up_tty_ioctl, | 507 | .unlocked_ioctl = hung_up_tty_ioctl, |
| @@ -538,6 +539,29 @@ void tty_wakeup(struct tty_struct *tty) · 31 unmodified lines | |||
| 538 | 539 | ||
| 539 | EXPORT_SYMBOL_GPL(tty_wakeup); | 540 | EXPORT_SYMBOL_GPL(tty_wakeup); |
| 540 | 541 | ||
| 542 | /** | ||
| 543 | * tty_release_redirect - Release a redirect on a pty if present | ||
| 544 | * @tty: tty device | ||
| 545 | * | ||
| 546 | * This is available to the pty code so if the master closes, if the | ||
| 547 | * slave is a redirect it can release the redirect. It returns the | ||
| 548 | * filp for the redirect, which must be fput when the operations on | ||
| 549 | * the tty are completed. | ||
| 550 | */ | ||
| 551 | struct file *tty_release_redirect(struct tty_struct *tty) | ||
| 552 | { | ||
| 553 | struct file *f = NULL; | ||
| 554 | |||
| 555 | spin_lock(&redirect_lock); | ||
| 556 | if (redirect && file_tty(redirect) == tty) { | ||
| 557 | f = redirect; | ||
| 558 | redirect = NULL; | ||
| 559 | } | ||
| 560 | spin_unlock(&redirect_lock); | ||
| 561 | |||
| 562 | return f; | ||
| 563 | } | ||
| 564 | |||
| 541 | /** | 565 | /** |
| 542 | * __tty_hangup - actual handler for hangup events | 566 | * __tty_hangup - actual handler for hangup events |
| 543 | * @tty: tty device | 567 | * @tty: tty device |
| @@ -564,7 +588,7 @@ EXPORT_SYMBOL_GPL(tty_wakeup); · 20 unmodified lines | |||
| 564 | static void __tty_hangup(struct tty_struct *tty, int exit_session) | 588 | static void __tty_hangup(struct tty_struct *tty, int exit_session) |
| 565 | { | 589 | { |
| 566 | struct file *cons_filp = NULL; | 590 | struct file *cons_filp = NULL; |
| 567 | struct file *filp, *f = NULL; | 591 | struct file *filp, *f; |
| 568 | struct tty_file_private *priv; | 592 | struct tty_file_private *priv; |
| 569 | int closecount = 0, n; | 593 | int closecount = 0, n; |
| 570 | int refs; | 594 | int refs; |
| @@ -572,13 +596,7 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) · 1 unmodified line | |||
| 572 | if (!tty) | 596 | if (!tty) |
| 573 | return; | 597 | return; |
| 574 | 598 | ||
| 575 | 599 | f = tty_release_redirect(tty); | |
| 576 | spin_lock(&redirect_lock); | ||
| 577 | if (redirect && file_tty(redirect) == tty) { | ||
| 578 | f = redirect; | ||
| 579 | redirect = NULL; | ||
| 580 | } | ||
| 581 | spin_unlock(&redirect_lock); | ||
| 582 | 600 | ||
| 583 | tty_lock(tty); | 601 | tty_lock(tty); |
| 584 | 602 | ||
| @@ -829,6 +847,72 @@ static void tty_update_time(struct timespec64 *time) · 244 unmodified lines | |||
| 829 | time->tv_sec = sec; | 847 | time->tv_sec = sec; |
| 830 | } | 848 | } |
| 831 | 849 | ||
| 850 | /* | ||
| 851 | * Iterate on the ldisc ->read() function until we've gotten all | ||
| 852 | * the data the ldisc has for us. | ||
| 853 | * | ||
| 854 | * The "cookie" is something that the ldisc read function can fill | ||
| 855 | * in to let us know that there is more data to be had. | ||
| 856 | * | ||
| 857 | * We promise to continue to call the ldisc until it stops returning | ||
| 858 | * data or clears the cookie. The cookie may be something that the | ||
| 859 | * ldisc maintains state for and needs to free. | ||
| 860 | */ | ||
| 861 | static int iterate_tty_read(struct tty_ldisc *ld, struct tty_struct *tty, | ||
| 862 | struct file *file, struct iov_iter *to) | ||
| 863 | { | ||
| 864 | int retval = 0; | ||
| 865 | void *cookie = NULL; | ||
| 866 | unsigned long offset = 0; | ||
| 867 | char kernel_buf[64]; | ||
| 868 | size_t count = iov_iter_count(to); | ||
| 869 | |||
| 870 | do { | ||
| 871 | int size, copied; | ||
| 872 | |||
| 873 | size = count > sizeof(kernel_buf) ? sizeof(kernel_buf) : count; | ||
| 874 | size = ld->ops->read(tty, file, kernel_buf, size, &cookie, offset); | ||
| 875 | if (!size) | ||
| 876 | break; | ||
| 877 | |||
| 878 | if (size < 0) { | ||
| 879 | /* Did we have an earlier error (ie -EFAULT)? */ | ||
| 880 | if (retval) | ||
| 881 | break; | ||
| 882 | retval = size; | ||
| 883 | |||
| 884 | /* | ||
| 885 | * -EOVERFLOW means we didn't have enough space | ||
| 886 | * for a whole packet, and we shouldn't return | ||
| 887 | * a partial result. | ||
| 888 | */ | ||
| 889 | if (retval == -EOVERFLOW) | ||
| 890 | offset = 0; | ||
| 891 | break; | ||
| 892 | } | ||
| 893 | |||
| 894 | copied = copy_to_iter(kernel_buf, size, to); | ||
| 895 | offset += copied; | ||
| 896 | count -= copied; | ||
| 897 | |||
| 898 | /* | ||
| 899 | * If the user copy failed, we still need to do another ->read() | ||
| 900 | * call if we had a cookie to let the ldisc clear up. | ||
| 901 | * | ||
| 902 | * But make sure size is zeroed. | ||
| 903 | */ | ||
| 904 | if (unlikely(copied != size)) { | ||
| 905 | count = 0; | ||
| 906 | retval = -EFAULT; | ||
| 907 | } | ||
| 908 | } while (cookie); | ||
| 909 | |||
| 910 | /* We always clear tty buffer in case they contained passwords */ | ||
| 911 | memzero_explicit(kernel_buf, sizeof(kernel_buf)); | ||
| 912 | return offset ? offset : retval; | ||
| 913 | } | ||
| 914 | |||
| 915 | |||
| 832 | /** | 916 | /** |
| 833 | * tty_read - read method for tty device files | 917 | * tty_read - read method for tty device files |
| 834 | * @file: pointer to tty file | 918 | * @file: pointer to tty file |
| @@ -844,10 +928,10 @@ static void tty_update_time(struct timespec64 *time) · 9 unmodified lines | |||
| 844 | * read calls may be outstanding in parallel. | 928 | * read calls may be outstanding in parallel. |
| 845 | */ | 929 | */ |
| 846 | 930 | ||
| 847 | static ssize_t tty_read(struct file *file, char __user *buf, size_t count, | 931 | static ssize_t tty_read(struct kiocb *iocb, struct iov_iter *to) |
| 848 | loff_t *ppos) | ||
| 849 | { | 932 | { |
| 850 | int i; | 933 | int i; |
| 934 | struct file *file = iocb->ki_filp; | ||
| 851 | struct inode *inode = file_inode(file); | 935 | struct inode *inode = file_inode(file); |
| 852 | struct tty_struct *tty = file_tty(file); | 936 | struct tty_struct *tty = file_tty(file); |
| 853 | struct tty_ldisc *ld; | 937 | struct tty_ldisc *ld; |
| @@ -861,11 +945,10 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, · 7 unmodified lines | |||
| 861 | situation */ | 945 | situation */ |
| 862 | ld = tty_ldisc_ref_wait(tty); | 946 | ld = tty_ldisc_ref_wait(tty); |
| 863 | if (!ld) | 947 | if (!ld) |
| 864 | return hung_up_tty_read(file, buf, count, ppos); | 948 | return hung_up_tty_read(iocb, to); |
| 949 | i = -EIO; | ||
| 865 | if (ld->ops->read) | 950 | if (ld->ops->read) |
| 866 | i = ld->ops->read(tty, file, buf, count); | 951 | i = iterate_tty_read(ld, tty, file, to); |
| 867 | else | ||
| 868 | i = -EIO; | ||
| 869 | tty_ldisc_deref(ld); | 952 | tty_ldisc_deref(ld); |
| 870 | 953 | ||
| 871 | if (i > 0) | 954 | if (i > 0) |
| @@ -1889,22 +1972,7 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, · 1017 unmodified lines | |||
| 1889 | return driver; | 1972 | return driver; |
| 1890 | } | 1973 | } |
| 1891 | 1974 | ||
| 1892 | /** | 1975 | static struct tty_struct *tty_kopen(dev_t device, int shared) |
| 1893 | * tty_kopen - open a tty device for kernel | ||
| 1894 | * @device: dev_t of device to open | ||
| 1895 | * | ||
| 1896 | * Opens tty exclusively for kernel. Performs the driver lookup, | ||
| 1897 | * makes sure it's not already opened and performs the first-time | ||
| 1898 | * tty initialization. | ||
| 1899 | * | ||
| 1900 | * Returns the locked initialized &tty_struct | ||
| 1901 | * | ||
| 1902 | * Claims the global tty_mutex to serialize: | ||
| 1903 | * - concurrent first-time tty initialization | ||
| 1904 | * - concurrent tty driver removal w/ lookup | ||
| 1905 | * - concurrent tty removal from driver table | ||
| 1906 | */ | ||
| 1907 | struct tty_struct *tty_kopen(dev_t device) | ||
| 1908 | { | 1976 | { |
| 1909 | struct tty_struct *tty; | 1977 | struct tty_struct *tty; |
| 1910 | struct tty_driver *driver; | 1978 | struct tty_driver *driver; |
| @@ -1919,7 +1987,7 @@ struct tty_struct *tty_kopen(dev_t device) · 8 unmodified lines | |||
| 1919 | 1987 | ||
| 1920 | /* check whether we're reopening an existing tty */ | 1988 | /* check whether we're reopening an existing tty */ |
| 1921 | tty = tty_driver_lookup_tty(driver, NULL, index); | 1989 | tty = tty_driver_lookup_tty(driver, NULL, index); |
| 1922 | if (IS_ERR(tty)) | 1990 | if (IS_ERR(tty) || shared) |
| 1923 | goto out; | 1991 | goto out; |
| 1924 | 1992 | ||
| 1925 | if (tty) { | 1993 | if (tty) { |
| @@ -1937,7 +2005,42 @@ out: · 11 unmodified lines | |||
| 1937 | tty_driver_kref_put(driver); | 2005 | tty_driver_kref_put(driver); |
| 1938 | return tty; | 2006 | return tty; |
| 1939 | } | 2007 | } |
| 1940 | EXPORT_SYMBOL_GPL(tty_kopen); | 2008 | |
| 2009 | /** | ||
| 2010 | * tty_kopen_exclusive - open a tty device for kernel | ||
| 2011 | * @device: dev_t of device to open | ||
| 2012 | * | ||
| 2013 | * Opens tty exclusively for kernel. Performs the driver lookup, | ||
| 2014 | * makes sure it's not already opened and performs the first-time | ||
| 2015 | * tty initialization. | ||
| 2016 | * | ||
| 2017 | * Returns the locked initialized &tty_struct | ||
| 2018 | * | ||
| 2019 | * Claims the global tty_mutex to serialize: | ||
| 2020 | * - concurrent first-time tty initialization | ||
| 2021 | * - concurrent tty driver removal w/ lookup | ||
| 2022 | * - concurrent tty removal from driver table | ||
| 2023 | */ | ||
| 2024 | struct tty_struct *tty_kopen_exclusive(dev_t device) | ||
| 2025 | { | ||
| 2026 | return tty_kopen(device, 0); | ||
| 2027 | } | ||
| 2028 | EXPORT_SYMBOL_GPL(tty_kopen_exclusive); | ||
| 2029 | |||
| 2030 | /** | ||
| 2031 | * tty_kopen_shared - open a tty device for shared in-kernel use | ||
| 2032 | * @device: dev_t of device to open | ||
| 2033 | * | ||
| 2034 | * Opens an already existing tty for in-kernel use. Compared to | ||
| 2035 | * tty_kopen_exclusive() above it doesn't ensure to be the only user. | ||
| 2036 | * | ||
| 2037 | * Locking is identical to tty_kopen() above. | ||
| 2038 | */ | ||
| 2039 | struct tty_struct *tty_kopen_shared(dev_t device) | ||
| 2040 | { | ||
| 2041 | return tty_kopen(device, 1); | ||
| 2042 | } | ||
| 2043 | EXPORT_SYMBOL_GPL(tty_kopen_shared); | ||
| 1941 | 2044 | ||
| 1942 | /** | 2045 | /** |
| 1943 | * tty_open_by_driver - open a tty device | 2046 | * tty_open_by_driver - open a tty device |
| @@ -2488,15 +2591,36 @@ static int tty_tiocmset(struct tty_struct *tty, unsigned int cmd, · 544 unmodified lines | |||
| 2488 | return tty->ops->tiocmset(tty, set, clear); | 2591 | return tty->ops->tiocmset(tty, set, clear); |
| 2489 | } | 2592 | } |
| 2490 | 2593 | ||
| 2594 | /** | ||
| 2595 | * tty_get_icount - get tty statistics | ||
| 2596 | * @tty: tty device | ||
| 2597 | * @icount: output parameter | ||
| 2598 | * | ||
| 2599 | * Gets a copy of the tty's icount statistics. | ||
| 2600 | * | ||
| 2601 | * Locking: none (up to the driver) | ||
| 2602 | */ | ||
| 2603 | int tty_get_icount(struct tty_struct *tty, | ||
| 2604 | struct serial_icounter_struct *icount) | ||
| 2605 | { | ||
| 2606 | memset(icount, 0, sizeof(*icount)); | ||
| 2607 | |||
| 2608 | if (tty->ops->get_icount) | ||
| 2609 | return tty->ops->get_icount(tty, icount); | ||
| 2610 | else | ||
| 2611 | return -EINVAL; | ||
| 2612 | } | ||
| 2613 | EXPORT_SYMBOL_GPL(tty_get_icount); | ||
| 2614 | |||
| 2491 | static int tty_tiocgicount(struct tty_struct *tty, void __user *arg) | 2615 | static int tty_tiocgicount(struct tty_struct *tty, void __user *arg) |
| 2492 | { | 2616 | { |
| 2493 | int retval = -EINVAL; | ||
| 2494 | struct serial_icounter_struct icount; | 2617 | struct serial_icounter_struct icount; |
| 2495 | memset(&icount, 0, sizeof(icount)); | 2618 | int retval; |
| 2496 | if (tty->ops->get_icount) | 2619 | |
| 2497 | retval = tty->ops->get_icount(tty, &icount); | 2620 | retval = tty_get_icount(tty, &icount); |
| 2498 | if (retval != 0) | 2621 | if (retval != 0) |
| 2499 | return retval; | 2622 | return retval; |
| 2623 | |||
| 2500 | if (copy_to_user(arg, &icount, sizeof(icount))) | 2624 | if (copy_to_user(arg, &icount, sizeof(icount))) |
| 2501 | return -EFAULT; | 2625 | return -EFAULT; |
| 2502 | return 0; | 2626 | return 0; |
| @@ -2887,7 +3011,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, · 384 unmodified lines | |||
| 2887 | 3011 | ||
| 2888 | static int this_tty(const void *t, struct file *file, unsigned fd) | 3012 | static int this_tty(const void *t, struct file *file, unsigned fd) |
| 2889 | { | 3013 | { |
| 2890 | if (likely(file->f_op->read != tty_read)) | 3014 | if (likely(file->f_op->read_iter != tty_read)) |
| 2891 | return 0; | 3015 | return 0; |
| 2892 | return file_tty(file) != t ? 0 : fd + 1; | 3016 | return file_tty(file) != t ? 0 : fd + 1; |
| 2893 | } | 3017 | } |
| @@ -681,9 +681,6 @@ static int vcc_remove(struct vio_dev *vdev) · 680 unmodified lines | |||
| 681 | { | 681 | { |
| 682 | struct vcc_port *port = dev_get_drvdata(&vdev->dev); | 682 | struct vcc_port *port = dev_get_drvdata(&vdev->dev); |
| 683 | 683 | ||
| 684 | if (!port) | ||
| 685 | return -ENODEV; | ||
| 686 | |||
| 687 | del_timer_sync(&port->rx_timer); | 684 | del_timer_sync(&port->rx_timer); |
| 688 | del_timer_sync(&port->tx_timer); | 685 | del_timer_sync(&port->tx_timer); |
| 689 | 686 | ||
| @@ -695,12 +692,9 @@ static int vcc_remove(struct vio_dev *vdev) · 5 unmodified lines | |||
| 695 | tty_vhangup(port->tty); | 692 | tty_vhangup(port->tty); |
| 696 | 693 | ||
| 697 | /* Get exclusive reference to VCC, ensures that there are no other | 694 | /* Get exclusive reference to VCC, ensures that there are no other |
| 698 | * clients to this port | 695 | * clients to this port. This cannot fail. |
| 699 | */ | 696 | */ |
| 700 | port = vcc_get(port->index, true); | 697 | vcc_get(port->index, true); |
| 701 | |||
| 702 | if (WARN_ON(!port)) | ||
| 703 | return -ENODEV; | ||
| 704 | 698 | ||
| 705 | tty_unregister_device(vcc_tty_driver, port->index); | 699 | tty_unregister_device(vcc_tty_driver, port->index); |
| 706 | 700 | ||
| @@ -495,7 +495,7 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos) · 494 unmodified lines | |||
| 495 | 495 | ||
| 496 | p2[unicode & 0x3f] = fontpos; | 496 | p2[unicode & 0x3f] = fontpos; |
| 497 | 497 | ||
| 498 | p->sum += (fontpos << 20) + unicode; | 498 | p->sum += (fontpos << 20U) + unicode; |
| 499 | 499 | ||
| 500 | return 0; | 500 | return 0; |
| 501 | } | 501 | } |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | |||
| 6 | #include <linux/keyboard.h> | 6 | #include <linux/keyboard.h> |
| 7 | #include <linux/kd.h> | 7 | #include <linux/kd.h> |
| 8 | 8 | ||
| 9 | u_short plain_map[NR_KEYS] = { | 9 | unsigned short plain_map[NR_KEYS] = { |
| 10 | 0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, | 10 | 0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, |
| 11 | 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf07f, 0xf009, | 11 | 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf07f, 0xf009, |
| 12 | 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, | 12 | 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, |
| @@ -25,7 +25,7 @@ u_short plain_map[NR_KEYS] = { · 12 unmodified lines | |||
| 25 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, | 25 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | u_short shift_map[NR_KEYS] = { | 28 | static unsigned short shift_map[NR_KEYS] = { |
| 29 | 0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e, | 29 | 0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e, |
| 30 | 0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07f, 0xf009, | 30 | 0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07f, 0xf009, |
| 31 | 0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49, | 31 | 0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49, |
| @@ -44,7 +44,7 @@ u_short shift_map[NR_KEYS] = { · 12 unmodified lines | |||
| 44 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, | 44 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, |
| 45 | }; | 45 | }; |
| 46 | 46 | ||
| 47 | u_short altgr_map[NR_KEYS] = { | 47 | static unsigned short altgr_map[NR_KEYS] = { |
| 48 | 0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200, | 48 | 0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200, |
| 49 | 0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200, | 49 | 0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200, |
| 50 | 0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, | 50 | 0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, |
| @@ -63,7 +63,7 @@ u_short altgr_map[NR_KEYS] = { · 12 unmodified lines | |||
| 63 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, | 63 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, |
| 64 | }; | 64 | }; |
| 65 | 65 | ||
| 66 | u_short ctrl_map[NR_KEYS] = { | 66 | static unsigned short ctrl_map[NR_KEYS] = { |
| 67 | 0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e, | 67 | 0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e, |
| 68 | 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200, | 68 | 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200, |
| 69 | 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, | 69 | 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, |
| @@ -82,7 +82,7 @@ u_short ctrl_map[NR_KEYS] = { · 12 unmodified lines | |||
| 82 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, | 82 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, |
| 83 | }; | 83 | }; |
| 84 | 84 | ||
| 85 | u_short shift_ctrl_map[NR_KEYS] = { | 85 | static unsigned short shift_ctrl_map[NR_KEYS] = { |
| 86 | 0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200, | 86 | 0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200, |
| 87 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200, | 87 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200, |
| 88 | 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, | 88 | 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, |
| @@ -101,7 +101,7 @@ u_short shift_ctrl_map[NR_KEYS] = { · 12 unmodified lines | |||
| 101 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, | 101 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, |
| 102 | }; | 102 | }; |
| 103 | 103 | ||
| 104 | u_short alt_map[NR_KEYS] = { | 104 | static unsigned short alt_map[NR_KEYS] = { |
| 105 | 0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836, | 105 | 0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836, |
| 106 | 0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf87f, 0xf809, | 106 | 0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf87f, 0xf809, |
| 107 | 0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869, | 107 | 0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869, |
| @@ -120,7 +120,7 @@ u_short alt_map[NR_KEYS] = { · 12 unmodified lines | |||
| 120 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, | 120 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, |
| 121 | }; | 121 | }; |
| 122 | 122 | ||
| 123 | u_short ctrl_alt_map[NR_KEYS] = { | 123 | static unsigned short ctrl_alt_map[NR_KEYS] = { |
| 124 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, | 124 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, |
| 125 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, | 125 | 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, |
| 126 | 0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809, | 126 | 0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809, |
| @@ -224,40 +224,40 @@ char *func_table[MAX_NR_FUNC] = { · 97 unmodified lines | |||
| 224 | }; | 224 | }; |
| 225 | 225 | ||
| 226 | struct kbdiacruc accent_table[MAX_DIACR] = { | 226 | struct kbdiacruc accent_table[MAX_DIACR] = { |
| 227 | {'`', 'A', 0300}, {'`', 'a', 0340}, | 227 | {'`', 'A', 0x00c0}, {'`', 'a', 0x00e0}, |
| 228 | {'\'', 'A', 0301}, {'\'', 'a', 0341}, | 228 | {'\'', 'A', 0x00c1}, {'\'', 'a', 0x00e1}, |
| 229 | {'^', 'A', 0302}, {'^', 'a', 0342}, | 229 | {'^', 'A', 0x00c2}, {'^', 'a', 0x00e2}, |
| 230 | {'~', 'A', 0303}, {'~', 'a', 0343}, | 230 | {'~', 'A', 0x00c3}, {'~', 'a', 0x00e3}, |
| 231 | {'"', 'A', 0304}, {'"', 'a', 0344}, | 231 | {'"', 'A', 0x00c4}, {'"', 'a', 0x00e4}, |
| 232 | {'O', 'A', 0305}, {'o', 'a', 0345}, | 232 | {'O', 'A', 0x00c5}, {'o', 'a', 0x00e5}, |
| 233 | {'0', 'A', 0305}, {'0', 'a', 0345}, | 233 | {'0', 'A', 0x00c5}, {'0', 'a', 0x00e5}, |
| 234 | {'A', 'A', 0305}, {'a', 'a', 0345}, | 234 | {'A', 'A', 0x00c5}, {'a', 'a', 0x00e5}, |
| 235 | {'A', 'E', 0306}, {'a', 'e', 0346}, | 235 | {'A', 'E', 0x00c6}, {'a', 'e', 0x00e6}, |
| 236 | {',', 'C', 0307}, {',', 'c', 0347}, | 236 | {',', 'C', 0x00c7}, {',', 'c', 0x00e7}, |
| 237 | {'`', 'E', 0310}, {'`', 'e', 0350}, | 237 | {'`', 'E', 0x00c8}, {'`', 'e', 0x00e8}, |
| 238 | {'\'', 'E', 0311}, {'\'', 'e', 0351}, | 238 | {'\'', 'E', 0x00c9}, {'\'', 'e', 0x00e9}, |
| 239 | {'^', 'E', 0312}, {'^', 'e', 0352}, | 239 | {'^', 'E', 0x00ca}, {'^', 'e', 0x00ea}, |
| 240 | {'"', 'E', 0313}, {'"', 'e', 0353}, | 240 | {'"', 'E', 0x00cb}, {'"', 'e', 0x00eb}, |
| 241 | {'`', 'I', 0314}, {'`', 'i', 0354}, | 241 | {'`', 'I', 0x00cc}, {'`', 'i', 0x00ec}, |
| 242 | {'\'', 'I', 0315}, {'\'', 'i', 0355}, | 242 | {'\'', 'I', 0x00cd}, {'\'', 'i', 0x00ed}, |
| 243 | {'^', 'I', 0316}, {'^', 'i', 0356}, | 243 | {'^', 'I', 0x00ce}, {'^', 'i', 0x00ee}, |
| 244 | {'"', 'I', 0317}, {'"', 'i', 0357}, | 244 | {'"', 'I', 0x00cf}, {'"', 'i', 0x00ef}, |
| 245 | {'-', 'D', 0320}, {'-', 'd', 0360}, | 245 | {'-', 'D', 0x00d0}, {'-', 'd', 0x00f0}, |
| 246 | {'~', 'N', 0321}, {'~', 'n', 0361}, | 246 | {'~', 'N', 0x00d1}, {'~', 'n', 0x00f1}, |
| 247 | {'`', 'O', 0322}, {'`', 'o', 0362}, | 247 | {'`', 'O', 0x00d2}, {'`', 'o', 0x00f2}, |
| 248 | {'\'', 'O', 0323}, {'\'', 'o', 0363}, | 248 | {'\'', 'O', 0x00d3}, {'\'', 'o', 0x00f3}, |
| 249 | {'^', 'O', 0324}, {'^', 'o', 0364}, | 249 | {'^', 'O', 0x00d4}, {'^', 'o', 0x00f4}, |
| 250 | {'~', 'O', 0325}, {'~', 'o', 0365}, | 250 | {'~', 'O', 0x00d5}, {'~', 'o', 0x00f5}, |
| 251 | {'"', 'O', 0326}, {'"', 'o', 0366}, | 251 | {'"', 'O', 0x00d6}, {'"', 'o', 0x00f6}, |
| 252 | {'/', 'O', 0330}, {'/', 'o', 0370}, | 252 | {'/', 'O', 0x00d8}, {'/', 'o', 0x00f8}, |
| 253 | {'`', 'U', 0331}, {'`', 'u', 0371}, | 253 | {'`', 'U', 0x00d9}, {'`', 'u', 0x00f9}, |
| 254 | {'\'', 'U', 0332}, {'\'', 'u', 0372}, | 254 | {'\'', 'U', 0x00da}, {'\'', 'u', 0x00fa}, |
| 255 | {'^', 'U', 0333}, {'^', 'u', 0373}, | 255 | {'^', 'U', 0x00db}, {'^', 'u', 0x00fb}, |
| 256 | {'"', 'U', 0334}, {'"', 'u', 0374}, | 256 | {'"', 'U', 0x00dc}, {'"', 'u', 0x00fc}, |
| 257 | {'\'', 'Y', 0335}, {'\'', 'y', 0375}, | 257 | {'\'', 'Y', 0x00dd}, {'\'', 'y', 0x00fd}, |
| 258 | {'T', 'H', 0336}, {'t', 'h', 0376}, | 258 | {'T', 'H', 0x00de}, {'t', 'h', 0x00fe}, |
| 259 | {'s', 's', 0337}, {'"', 'y', 0377}, | 259 | {'s', 's', 0x00df}, {'"', 'y', 0x00ff}, |
| 260 | {'s', 'z', 0337}, {'i', 'j', 0377}, | 260 | {'s', 'z', 0x00df}, {'i', 'j', 0x00ff}, |
| 261 | }; | 261 | }; |
| 262 | 262 | ||
| 263 | unsigned int accent_table_size = 68; | 263 | unsigned int accent_table_size = 68; |
| @@ -131,6 +131,9 @@ static const unsigned char max_vals[] = { · 130 unmodified lines | |||
| 131 | 131 | ||
| 132 | static const int NR_TYPES = ARRAY_SIZE(max_vals); | 132 | static const int NR_TYPES = ARRAY_SIZE(max_vals); |
| 133 | 133 | ||
| 134 | static void kbd_bh(struct tasklet_struct *unused); | ||
| 135 | static DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh); | ||
| 136 | |||
| 134 | static struct input_handler kbd_handler; | 137 | static struct input_handler kbd_handler; |
| 135 | static DEFINE_SPINLOCK(kbd_event_lock); | 138 | static DEFINE_SPINLOCK(kbd_event_lock); |
| 136 | static DEFINE_SPINLOCK(led_lock); | 139 | static DEFINE_SPINLOCK(led_lock); |
| @@ -372,6 +375,12 @@ static void to_utf8(struct vc_data *vc, uint c) · 235 unmodified lines | |||
| 372 | } | 375 | } |
| 373 | } | 376 | } |
| 374 | 377 | ||
| 378 | /* FIXME: review locking for vt.c callers */ | ||
| 379 | static void set_leds(void) | ||
| 380 | { | ||
| 381 | tasklet_schedule(&keyboard_tasklet); | ||
| 382 | } | ||
| 383 | |||
| 375 | /* | 384 | /* |
| 376 | * Called after returning from RAW mode or when changing consoles - recompute | 385 | * Called after returning from RAW mode or when changing consoles - recompute |
| 377 | * shift_down[] and shift_state from key_down[] maybe called when keymap is | 386 | * shift_down[] and shift_state from key_down[] maybe called when keymap is |
| @@ -401,9 +410,12 @@ static void do_compute_shiftstate(void) · 23 unmodified lines | |||
| 401 | } | 410 | } |
| 402 | 411 | ||
| 403 | /* We still have to export this method to vt.c */ | 412 | /* We still have to export this method to vt.c */ |
| 404 | void compute_shiftstate(void) | 413 | void vt_set_leds_compute_shiftstate(void) |
| 405 | { | 414 | { |
| 406 | unsigned long flags; | 415 | unsigned long flags; |
| 416 | |||
| 417 | set_leds(); | ||
| 418 | |||
| 407 | spin_lock_irqsave(&kbd_event_lock, flags); | 419 | spin_lock_irqsave(&kbd_event_lock, flags); |
| 408 | do_compute_shiftstate(); | 420 | do_compute_shiftstate(); |
| 409 | spin_unlock_irqrestore(&kbd_event_lock, flags); | 421 | spin_unlock_irqrestore(&kbd_event_lock, flags); |
| @@ -1233,7 +1245,7 @@ void vt_kbd_con_stop(int console) · 823 unmodified lines | |||
| 1233 | * handle the scenario when keyboard handler is not registered yet | 1245 | * handle the scenario when keyboard handler is not registered yet |
| 1234 | * but we already getting updates from the VT to update led state. | 1246 | * but we already getting updates from the VT to update led state. |
| 1235 | */ | 1247 | */ |
| 1236 | static void kbd_bh(unsigned long dummy) | 1248 | static void kbd_bh(struct tasklet_struct *unused) |
| 1237 | { | 1249 | { |
| 1238 | unsigned int leds; | 1250 | unsigned int leds; |
| 1239 | unsigned long flags; | 1251 | unsigned long flags; |
| @@ -1249,8 +1261,6 @@ static void kbd_bh(unsigned long dummy) · 9 unmodified lines | |||
| 1249 | } | 1261 | } |
| 1250 | } | 1262 | } |
| 1251 | 1263 | ||
| 1252 | DECLARE_TASKLET_DISABLED_OLD(keyboard_tasklet, kbd_bh); | ||
| 1253 | |||
| 1254 | #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\ | 1264 | #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\ |
| 1255 | defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\ | 1265 | defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\ |
| 1256 | defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\ | 1266 | defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\ |
| @@ -1036,8 +1036,7 @@ void redraw_screen(struct vc_data *vc, int is_switch) · 1035 unmodified lines | |||
| 1036 | } | 1036 | } |
| 1037 | set_cursor(vc); | 1037 | set_cursor(vc); |
| 1038 | if (is_switch) { | 1038 | if (is_switch) { |
| 1039 | set_leds(); | 1039 | vt_set_leds_compute_shiftstate(); |
| 1040 | compute_shiftstate(); | ||
| 1041 | notify_update(vc); | 1040 | notify_update(vc); |
| 1042 | } | 1041 | } |
| 1043 | } | 1042 | } |
| @@ -4584,16 +4583,8 @@ static int con_font_get(struct vc_data *vc, struct console_font_op *op) · 3540 unmodified lines | |||
| 4584 | 4583 | ||
| 4585 | if (op->data && font.charcount > op->charcount) | 4584 | if (op->data && font.charcount > op->charcount) |
| 4586 | rc = -ENOSPC; | 4585 | rc = -ENOSPC; |
| 4587 | if (!(op->flags & KD_FONT_FLAG_OLD)) { | 4586 | if (font.width > op->width || font.height > op->height) |
| 4588 | if (font.width > op->width || font.height > op->height) | 4587 | rc = -ENOSPC; |
| 4589 | rc = -ENOSPC; | ||
| 4590 | } else { | ||
| 4591 | if (font.width != 8) | ||
| 4592 | rc = -EIO; | ||
| 4593 | else if ((op->height && font.height > op->height) || | ||
| 4594 | font.height > 32) | ||
| 4595 | rc = -ENOSPC; | ||
| 4596 | } | ||
| 4597 | if (rc) | 4588 | if (rc) |
| 4598 | goto out; | 4589 | goto out; |
| 4599 | 4590 | ||
| @@ -4621,7 +4612,7 @@ static int con_font_set(struct vc_data *vc, struct console_font_op *op) · 21 unmodified lines | |||
| 4621 | return -EINVAL; | 4612 | return -EINVAL; |
| 4622 | if (op->charcount > 512) | 4613 | if (op->charcount > 512) |
| 4623 | return -EINVAL; | 4614 | return -EINVAL; |
| 4624 | if (op->width <= 0 || op->width > 32 || op->height > 32) | 4615 | if (op->width <= 0 || op->width > 32 || !op->height || op->height > 32) |
| 4625 | return -EINVAL; | 4616 | return -EINVAL; |
| 4626 | size = (op->width+7)/8 * 32 * op->charcount; | 4617 | size = (op->width+7)/8 * 32 * op->charcount; |
| 4627 | if (size > max_font_size) | 4618 | if (size > max_font_size) |
| @@ -4631,31 +4622,6 @@ static int con_font_set(struct vc_data *vc, struct console_font_op *op) · 3 unmodified lines | |||
| 4631 | if (IS_ERR(font.data)) | 4622 | if (IS_ERR(font.data)) |
| 4632 | return PTR_ERR(font.data); | 4623 | return PTR_ERR(font.data); |
| 4633 | 4624 | ||
| 4634 | if (!op->height) { /* Need to guess font height [compat] */ | ||
| 4635 | int h, i; | ||
| 4636 | u8 *charmap = font.data; | ||
| 4637 | |||
| 4638 | /* | ||
| 4639 | * If from KDFONTOP ioctl, don't allow things which can be done | ||
| 4640 | * in userland,so that we can get rid of this soon | ||
| 4641 | */ | ||
| 4642 | if (!(op->flags & KD_FONT_FLAG_OLD)) { | ||
| 4643 | kfree(font.data); | ||
| 4644 | return -EINVAL; | ||
| 4645 | } | ||
| 4646 | |||
| 4647 | for (h = 32; h > 0; h--) | ||
| 4648 | for (i = 0; i < op->charcount; i++) | ||
| 4649 | if (charmap[32*i+h-1]) | ||
| 4650 | goto nonzero; | ||
| 4651 | |||
| 4652 | kfree(font.data); | ||
| 4653 | return -EINVAL; | ||
| 4654 | |||
| 4655 | nonzero: | ||
| 4656 | op->height = h; | ||
| 4657 | } | ||
| 4658 | |||
| 4659 | font.charcount = op->charcount; | 4625 | font.charcount = op->charcount; |
| 4660 | font.width = op->width; | 4626 | font.width = op->width; |
| 4661 | font.height = op->height; | 4627 | font.height = op->height; |
| @@ -484,70 +484,6 @@ static int vt_k_ioctl(struct tty_struct *tty, unsigned int cmd, · 483 unmodified lines | |||
| 484 | return 0; | 484 | return 0; |
| 485 | } | 485 | } |
| 486 | 486 | ||
| 487 | static inline int do_fontx_ioctl(struct vc_data *vc, int cmd, | ||
| 488 | struct consolefontdesc __user *user_cfd, | ||
| 489 | struct console_font_op *op) | ||
| 490 | { | ||
| 491 | struct consolefontdesc cfdarg; | ||
| 492 | int i; | ||
| 493 | |||
| 494 | if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc))) | ||
| 495 | return -EFAULT; | ||
| 496 | |||
| 497 | switch (cmd) { | ||
| 498 | case PIO_FONTX: | ||
| 499 | op->op = KD_FONT_OP_SET; | ||
| 500 | op->flags = KD_FONT_FLAG_OLD; | ||
| 501 | op->width = 8; | ||
| 502 | op->height = cfdarg.charheight; | ||
| 503 | op->charcount = cfdarg.charcount; | ||
| 504 | op->data = cfdarg.chardata; | ||
| 505 | return con_font_op(vc, op); | ||
| 506 | |||
| 507 | case GIO_FONTX: | ||
| 508 | op->op = KD_FONT_OP_GET; | ||
| 509 | op->flags = KD_FONT_FLAG_OLD; | ||
| 510 | op->width = 8; | ||
| 511 | op->height = cfdarg.charheight; | ||
| 512 | op->charcount = cfdarg.charcount; | ||
| 513 | op->data = cfdarg.chardata; | ||
| 514 | i = con_font_op(vc, op); | ||
| 515 | if (i) | ||
| 516 | return i; | ||
| 517 | cfdarg.charheight = op->height; | ||
| 518 | cfdarg.charcount = op->charcount; | ||
| 519 | if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc))) | ||
| 520 | return -EFAULT; | ||
| 521 | return 0; | ||
| 522 | } | ||
| 523 | return -EINVAL; | ||
| 524 | } | ||
| 525 | |||
| 526 | static int vt_io_fontreset(struct vc_data *vc, struct console_font_op *op) | ||
| 527 | { | ||
| 528 | int ret; | ||
| 529 | |||
| 530 | if (__is_defined(BROKEN_GRAPHICS_PROGRAMS)) { | ||
| 531 | /* | ||
| 532 | * With BROKEN_GRAPHICS_PROGRAMS defined, the default font is | ||
| 533 | * not saved. | ||
| 534 | */ | ||
| 535 | return -ENOSYS; | ||
| 536 | } | ||
| 537 | |||
| 538 | op->op = KD_FONT_OP_SET_DEFAULT; | ||
| 539 | op->data = NULL; | ||
| 540 | ret = con_font_op(vc, op); | ||
| 541 | if (ret) | ||
| 542 | return ret; | ||
| 543 | |||
| 544 | console_lock(); | ||
| 545 | con_set_default_unimap(vc); | ||
| 546 | console_unlock(); | ||
| 547 | |||
| 548 | return 0; | ||
| 549 | } | ||
| 550 | |||
| 551 | static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, | 487 | static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, |
| 552 | bool perm, struct vc_data *vc) | 488 | bool perm, struct vc_data *vc) |
| 553 | { | 489 | { |
| @@ -572,29 +508,7 @@ static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, · 18 unmodified lines | |||
| 572 | static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up, | 508 | static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up, |
| 573 | bool perm) | 509 | bool perm) |
| 574 | { | 510 | { |
| 575 | struct console_font_op op; /* used in multiple places here */ | ||
| 576 | |||
| 577 | switch (cmd) { | 511 | switch (cmd) { |
| 578 | case PIO_FONT: | ||
| 579 | if (!perm) | ||
| 580 | return -EPERM; | ||
| 581 | op.op = KD_FONT_OP_SET; | ||
| 582 | op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */ | ||
| 583 | op.width = 8; | ||
| 584 | op.height = 0; | ||
| 585 | op.charcount = 256; | ||
| 586 | op.data = up; | ||
| 587 | return con_font_op(vc, &op); | ||
| 588 | |||
| 589 | case GIO_FONT: | ||
| 590 | op.op = KD_FONT_OP_GET; | ||
| 591 | op.flags = KD_FONT_FLAG_OLD; | ||
| 592 | op.width = 8; | ||
| 593 | op.height = 32; | ||
| 594 | op.charcount = 256; | ||
| 595 | op.data = up; | ||
| 596 | return con_font_op(vc, &op); | ||
| 597 | |||
| 598 | case PIO_CMAP: | 512 | case PIO_CMAP: |
| 599 | if (!perm) | 513 | if (!perm) |
| 600 | return -EPERM; | 514 | return -EPERM; |
| @@ -603,20 +517,6 @@ static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up, · 2 unmodified lines | |||
| 603 | case GIO_CMAP: | 517 | case GIO_CMAP: |
| 604 | return con_get_cmap(up); | 518 | return con_get_cmap(up); |
| 605 | 519 | ||
| 606 | case PIO_FONTX: | ||
| 607 | if (!perm) | ||
| 608 | return -EPERM; | ||
| 609 | |||
| 610 | fallthrough; | ||
| 611 | case GIO_FONTX: | ||
| 612 | return do_fontx_ioctl(vc, cmd, up, &op); | ||
| 613 | |||
| 614 | case PIO_FONTRESET: | ||
| 615 | if (!perm) | ||
| 616 | return -EPERM; | ||
| 617 | |||
| 618 | return vt_io_fontreset(vc, &op); | ||
| 619 | |||
| 620 | case PIO_SCRNMAP: | 520 | case PIO_SCRNMAP: |
| 621 | if (!perm) | 521 | if (!perm) |
| 622 | return -EPERM; | 522 | return -EPERM; |
| @@ -1030,8 +930,7 @@ void reset_vc(struct vc_data *vc) · 407 unmodified lines | |||
| 1030 | put_pid(vc->vt_pid); | 930 | put_pid(vc->vt_pid); |
| 1031 | vc->vt_pid = NULL; | 931 | vc->vt_pid = NULL; |
| 1032 | vc->vt_newvt = -1; | 932 | vc->vt_newvt = -1; |
| 1033 | if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */ | 933 | reset_palette(vc); |
| 1034 | reset_palette(vc); | ||
| 1035 | } | 934 | } |
| 1036 | 935 | ||
| 1037 | void vc_SAK(struct work_struct *work) | 936 | void vc_SAK(struct work_struct *work) |
| @@ -1059,54 +958,6 @@ void vc_SAK(struct work_struct *work) · 21 unmodified lines | |||
| 1059 | 958 | ||
| 1060 | #ifdef CONFIG_COMPAT | 959 | #ifdef CONFIG_COMPAT |
| 1061 | 960 | ||
| 1062 | struct compat_consolefontdesc { | ||
| 1063 | unsigned short charcount; /* characters in font (256 or 512) */ | ||
| 1064 | unsigned short charheight; /* scan lines per character (1-32) */ | ||
| 1065 | compat_caddr_t chardata; /* font data in expanded form */ | ||
| 1066 | }; | ||
| 1067 | |||
| 1068 | static inline int | ||
| 1069 | compat_fontx_ioctl(struct vc_data *vc, int cmd, | ||
| 1070 | struct compat_consolefontdesc __user *user_cfd, | ||
| 1071 | int perm, struct console_font_op *op) | ||
| 1072 | { | ||
| 1073 | struct compat_consolefontdesc cfdarg; | ||
| 1074 | int i; | ||
| 1075 | |||
| 1076 | if (copy_from_user(&cfdarg, user_cfd, sizeof(struct compat_consolefontdesc))) | ||
| 1077 | return -EFAULT; | ||
| 1078 | |||
| 1079 | switch (cmd) { | ||
| 1080 | case PIO_FONTX: | ||
| 1081 | if (!perm) | ||
| 1082 | return -EPERM; | ||
| 1083 | op->op = KD_FONT_OP_SET; | ||
| 1084 | op->flags = KD_FONT_FLAG_OLD; | ||
| 1085 | op->width = 8; | ||
| 1086 | op->height = cfdarg.charheight; | ||
| 1087 | op->charcount = cfdarg.charcount; | ||
| 1088 | op->data = compat_ptr(cfdarg.chardata); | ||
| 1089 | return con_font_op(vc, op); | ||
| 1090 | |||
| 1091 | case GIO_FONTX: | ||
| 1092 | op->op = KD_FONT_OP_GET; | ||
| 1093 | op->flags = KD_FONT_FLAG_OLD; | ||
| 1094 | op->width = 8; | ||
| 1095 | op->height = cfdarg.charheight; | ||
| 1096 | op->charcount = cfdarg.charcount; | ||
| 1097 | op->data = compat_ptr(cfdarg.chardata); | ||
| 1098 | i = con_font_op(vc, op); | ||
| 1099 | if (i) | ||
| 1100 | return i; | ||
| 1101 | cfdarg.charheight = op->height; | ||
| 1102 | cfdarg.charcount = op->charcount; | ||
| 1103 | if (copy_to_user(user_cfd, &cfdarg, sizeof(struct compat_consolefontdesc))) | ||
| 1104 | return -EFAULT; | ||
| 1105 | return 0; | ||
| 1106 | } | ||
| 1107 | return -EINVAL; | ||
| 1108 | } | ||
| 1109 | |||
| 1110 | struct compat_console_font_op { | 961 | struct compat_console_font_op { |
| 1111 | compat_uint_t op; /* operation code KD_FONT_OP_* */ | 962 | compat_uint_t op; /* operation code KD_FONT_OP_* */ |
| 1112 | compat_uint_t flags; /* KD_FONT_FLAG_* */ | 963 | compat_uint_t flags; /* KD_FONT_FLAG_* */ |
| @@ -1183,9 +1034,6 @@ long vt_compat_ioctl(struct tty_struct *tty, · 70 unmodified lines | |||
| 1183 | /* | 1034 | /* |
| 1184 | * these need special handlers for incompatible data structures | 1035 | * these need special handlers for incompatible data structures |
| 1185 | */ | 1036 | */ |
| 1186 | case PIO_FONTX: | ||
| 1187 | case GIO_FONTX: | ||
| 1188 | return compat_fontx_ioctl(vc, cmd, up, perm, &op); | ||
| 1189 | 1037 | ||
| 1190 | case KDFONTOP: | 1038 | case KDFONTOP: |
| 1191 | return compat_kdfontop_ioctl(up, perm, &op, vc); | 1039 | return compat_kdfontop_ioctl(up, perm, &op, vc); |
| @@ -90,7 +90,6 @@ static unsigned int vga_video_num_lines; /* Number of text lines */ · 89 unmodified lines | |||
| 90 | static bool vga_can_do_color; /* Do we support colors? */ | 90 | static bool vga_can_do_color; /* Do we support colors? */ |
| 91 | static unsigned int vga_default_font_height __read_mostly; /* Height of default screen font */ | 91 | static unsigned int vga_default_font_height __read_mostly; /* Height of default screen font */ |
| 92 | static unsigned char vga_video_type __read_mostly; /* Card type */ | 92 | static unsigned char vga_video_type __read_mostly; /* Card type */ |
| 93 | static bool vga_font_is_default = true; | ||
| 94 | static int vga_vesa_blanked; | 93 | static int vga_vesa_blanked; |
| 95 | static bool vga_palette_blanked; | 94 | static bool vga_palette_blanked; |
| 96 | static bool vga_is_gfx; | 95 | static bool vga_is_gfx; |
| @@ -878,7 +877,6 @@ static int vgacon_do_font_op(struct vgastate *state, char *arg, int set, · 781 unmodified lines | |||
| 878 | beg = 0x0a; | 877 | beg = 0x0a; |
| 879 | } | 878 | } |
| 880 | 879 | ||
| 881 | #ifdef BROKEN_GRAPHICS_PROGRAMS | ||
| 882 | /* | 880 | /* |
| 883 | * All fonts are loaded in slot 0 (0:1 for 512 ch) | 881 | * All fonts are loaded in slot 0 (0:1 for 512 ch) |
| 884 | */ | 882 | */ |
| @@ -886,24 +884,7 @@ static int vgacon_do_font_op(struct vgastate *state, char *arg, int set, · 1 unmodified line | |||
| 886 | if (!arg) | 884 | if (!arg) |
| 887 | return -EINVAL; /* Return to default font not supported */ | 885 | return -EINVAL; /* Return to default font not supported */ |
| 888 | 886 | ||
| 889 | vga_font_is_default = false; | ||
| 890 | font_select = ch512 ? 0x04 : 0x00; | 887 | font_select = ch512 ? 0x04 : 0x00; |
| 891 | #else | ||
| 892 | /* | ||
| 893 | * The default font is kept in slot 0 and is never touched. | ||
| 894 | * A custom font is loaded in slot 2 (256 ch) or 2:3 (512 ch) | ||
| 895 | */ | ||
| 896 | |||
| 897 | if (set) { | ||
| 898 | vga_font_is_default = !arg; | ||
| 899 | if (!arg) | ||
| 900 | ch512 = false; /* Default font is always 256 */ | ||
| 901 | font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00; | ||
| 902 | } | ||
| 903 | |||
| 904 | if (!vga_font_is_default) | ||
| 905 | charmap += 4 * cmapsz; | ||
| 906 | #endif | ||
| 907 | 888 | ||
| 908 | raw_spin_lock_irq(&vga_lock); | 889 | raw_spin_lock_irq(&vga_lock); |
| 909 | /* First, the Sequencer */ | 890 | /* First, the Sequencer */ |
| @@ -6,8 +6,6 @@ · 5 unmodified lines | |||
| 6 | #include <linux/interrupt.h> | 6 | #include <linux/interrupt.h> |
| 7 | #include <linux/keyboard.h> | 7 | #include <linux/keyboard.h> |
| 8 | 8 | ||
| 9 | extern struct tasklet_struct keyboard_tasklet; | ||
| 10 | |||
| 11 | extern char *func_table[MAX_NR_FUNC]; | 9 | extern char *func_table[MAX_NR_FUNC]; |
| 12 | 10 | ||
| 13 | /* | 11 | /* |
| @@ -71,12 +69,6 @@ extern void (*kbd_ledfunc)(unsigned int led); · 57 unmodified lines | |||
| 71 | extern int set_console(int nr); | 69 | extern int set_console(int nr); |
| 72 | extern void schedule_console_callback(void); | 70 | extern void schedule_console_callback(void); |
| 73 | 71 | ||
| 74 | /* FIXME: review locking for vt.c callers */ | ||
| 75 | static inline void set_leds(void) | ||
| 76 | { | ||
| 77 | tasklet_schedule(&keyboard_tasklet); | ||
| 78 | } | ||
| 79 | |||
| 80 | static inline int vc_kbd_mode(struct kbd_struct * kbd, int flag) | 72 | static inline int vc_kbd_mode(struct kbd_struct * kbd, int flag) |
| 81 | { | 73 | { |
| 82 | return ((kbd->modeflags >> flag) & 1); | 74 | return ((kbd->modeflags >> flag) & 1); |
| @@ -135,7 +127,7 @@ static inline void chg_vc_kbd_led(struct kbd_struct * kbd, int flag) · 52 unmodified lines | |||
| 135 | 127 | ||
| 136 | struct console; | 128 | struct console; |
| 137 | 129 | ||
| 138 | void compute_shiftstate(void); | 130 | void vt_set_leds_compute_shiftstate(void); |
| 139 | 131 | ||
| 140 | /* defkeymap.c */ | 132 | /* defkeymap.c */ |
| 141 | 133 | ||
| @@ -1,8 +0,0 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | #ifndef _LINUX_KD_H | ||
| 3 | #define _LINUX_KD_H | ||
| 4 | |||
| 5 | #include <uapi/linux/kd.h> | ||
| 6 | |||
| 7 | #define KD_FONT_FLAG_OLD 0x80000000 /* Invoked via old interface [compat] */ | ||
| 8 | #endif /* _LINUX_KD_H */ | ||
| @@ -1,19 +0,0 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * | ||
| 4 | * | ||
| 5 | */ | ||
| 6 | #ifndef __LINUX_PLATFORM_DATA_EFM32_UART_H__ | ||
| 7 | #define __LINUX_PLATFORM_DATA_EFM32_UART_H__ | ||
| 8 | |||
| 9 | #include <linux/types.h> | ||
| 10 | |||
| 11 | /** | ||
| 12 | * struct efm32_uart_pdata | ||
| 13 | * @location: pinmux location for the I/O pins (to be written to the ROUTE | ||
| 14 | * register) | ||
| 15 | */ | ||
| 16 | struct efm32_uart_pdata { | ||
| 17 | u8 location; | ||
| 18 | }; | ||
| 19 | #endif /* ifndef __LINUX_PLATFORM_DATA_EFM32_UART_H__ */ | ||
| @@ -1,15 +0,0 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | #ifndef LINUX_IFX_MODEM_H | ||
| 3 | #define LINUX_IFX_MODEM_H | ||
| 4 | |||
| 5 | struct ifx_modem_platform_data { | ||
| 6 | unsigned short tx_pwr; /* modem power threshold */ | ||
| 7 | unsigned char modem_type; /* Modem type */ | ||
| 8 | unsigned long max_hz; /* max SPI frequency */ | ||
| 9 | unsigned short use_dma:1; /* spi protocol driver supplies | ||
| 10 | dma-able addrs */ | ||
| 11 | }; | ||
| 12 | #define IFX_MODEM_6160 1 | ||
| 13 | #define IFX_MODEM_6260 2 | ||
| 14 | |||
| 15 | #endif | ||
| @@ -240,8 +240,7 @@ struct tty_port { · 239 unmodified lines | |||
| 240 | wait_queue_head_t delta_msr_wait; /* Modem status change */ | 240 | wait_queue_head_t delta_msr_wait; /* Modem status change */ |
| 241 | unsigned long flags; /* User TTY flags ASYNC_ */ | 241 | unsigned long flags; /* User TTY flags ASYNC_ */ |
| 242 | unsigned long iflags; /* Internal flags TTY_PORT_ */ | 242 | unsigned long iflags; /* Internal flags TTY_PORT_ */ |
| 243 | unsigned char console:1, /* port is a console */ | 243 | unsigned char console:1; /* port is a console */ |
| 244 | low_latency:1; /* optional: tune for latency */ | ||
| 245 | struct mutex mutex; /* Locking */ | 244 | struct mutex mutex; /* Locking */ |
| 246 | struct mutex buf_mutex; /* Buffer alloc lock */ | 245 | struct mutex buf_mutex; /* Buffer alloc lock */ |
| 247 | unsigned char *xmit_buf; /* Optional buffer */ | 246 | unsigned char *xmit_buf; /* Optional buffer */ |
| @@ -416,12 +415,14 @@ extern struct tty_struct *get_current_tty(void); · 168 unmodified lines | |||
| 416 | /* tty_io.c */ | 415 | /* tty_io.c */ |
| 417 | extern int __init tty_init(void); | 416 | extern int __init tty_init(void); |
| 418 | extern const char *tty_name(const struct tty_struct *tty); | 417 | extern const char *tty_name(const struct tty_struct *tty); |
| 419 | extern struct tty_struct *tty_kopen(dev_t device); | 418 | extern struct tty_struct *tty_kopen_exclusive(dev_t device); |
| 419 | extern struct tty_struct *tty_kopen_shared(dev_t device); | ||
| 420 | extern void tty_kclose(struct tty_struct *tty); | 420 | extern void tty_kclose(struct tty_struct *tty); |
| 421 | extern int tty_dev_name_to_number(const char *name, dev_t *number); | 421 | extern int tty_dev_name_to_number(const char *name, dev_t *number); |
| 422 | extern int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout); | 422 | extern int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout); |
| 423 | extern void tty_ldisc_unlock(struct tty_struct *tty); | 423 | extern void tty_ldisc_unlock(struct tty_struct *tty); |
| 424 | extern ssize_t redirected_tty_write(struct kiocb *, struct iov_iter *); | 424 | extern ssize_t redirected_tty_write(struct kiocb *, struct iov_iter *); |
| 425 | extern struct file *tty_release_redirect(struct tty_struct *tty); | ||
| 425 | #else | 426 | #else |
| 426 | static inline void tty_kref_put(struct tty_struct *tty) | 427 | static inline void tty_kref_put(struct tty_struct *tty) |
| 427 | { } | 428 | { } |
| @@ -442,7 +443,7 @@ static inline int __init tty_init(void) · 14 unmodified lines | |||
| 442 | { return 0; } | 443 | { return 0; } |
| 443 | static inline const char *tty_name(const struct tty_struct *tty) | 444 | static inline const char *tty_name(const struct tty_struct *tty) |
| 444 | { return "(none)"; } | 445 | { return "(none)"; } |
| 445 | static inline struct tty_struct *tty_kopen(dev_t device) | 446 | static inline struct tty_struct *tty_kopen_exclusive(dev_t device) |
| 446 | { return ERR_PTR(-ENODEV); } | 447 | { return ERR_PTR(-ENODEV); } |
| 447 | static inline void tty_kclose(struct tty_struct *tty) | 448 | static inline void tty_kclose(struct tty_struct *tty) |
| 448 | { } | 449 | { } |
| @@ -500,6 +501,8 @@ extern void tty_unthrottle(struct tty_struct *tty); · 51 unmodified lines | |||
| 500 | extern int tty_throttle_safe(struct tty_struct *tty); | 501 | extern int tty_throttle_safe(struct tty_struct *tty); |
| 501 | extern int tty_unthrottle_safe(struct tty_struct *tty); | 502 | extern int tty_unthrottle_safe(struct tty_struct *tty); |
| 502 | extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws); | 503 | extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws); |
| 504 | extern int tty_get_icount(struct tty_struct *tty, | ||
| 505 | struct serial_icounter_struct *icount); | ||
| 503 | extern int is_current_pgrp_orphaned(void); | 506 | extern int is_current_pgrp_orphaned(void); |
| 504 | extern void tty_hangup(struct tty_struct *tty); | 507 | extern void tty_hangup(struct tty_struct *tty); |
| 505 | extern void tty_vhangup(struct tty_struct *tty); | 508 | extern void tty_vhangup(struct tty_struct *tty); |
| @@ -185,7 +185,8 @@ struct tty_ldisc_ops { · 184 unmodified lines | |||
| 185 | void (*close)(struct tty_struct *); | 185 | void (*close)(struct tty_struct *); |
| 186 | void (*flush_buffer)(struct tty_struct *tty); | 186 | void (*flush_buffer)(struct tty_struct *tty); |
| 187 | ssize_t (*read)(struct tty_struct *tty, struct file *file, | 187 | ssize_t (*read)(struct tty_struct *tty, struct file *file, |
| 188 | unsigned char __user *buf, size_t nr); | 188 | unsigned char *buf, size_t nr, |
| 189 | void **cookie, unsigned long offset); | ||
| 189 | ssize_t (*write)(struct tty_struct *tty, struct file *file, | 190 | ssize_t (*write)(struct tty_struct *tty, struct file *file, |
| 190 | const unsigned char *buf, size_t nr); | 191 | const unsigned char *buf, size_t nr); |
| 191 | int (*ioctl)(struct tty_struct *tty, struct file *file, | 192 | int (*ioctl)(struct tty_struct *tty, struct file *file, |
| @@ -16,18 +16,6 @@ · 15 unmodified lines | |||
| 16 | #include <linux/consolemap.h> | 16 | #include <linux/consolemap.h> |
| 17 | #include <linux/notifier.h> | 17 | #include <linux/notifier.h> |
| 18 | 18 | ||
| 19 | /* | ||
| 20 | * Presently, a lot of graphics programs do not restore the contents of | ||
| 21 | * the higher font pages. Defining this flag will avoid use of them, but | ||
| 22 | * will lose support for PIO_FONTRESET. Note that many font operations are | ||
| 23 | * not likely to work with these programs anyway; they need to be | ||
| 24 | * fixed. The linux/Documentation directory includes a code snippet | ||
| 25 | * to save and restore the text font. | ||
| 26 | */ | ||
| 27 | #ifdef CONFIG_VGA_CONSOLE | ||
| 28 | #define BROKEN_GRAPHICS_PROGRAMS 1 | ||
| 29 | #endif | ||
| 30 | |||
| 31 | void kd_mksound(unsigned int hz, unsigned int ticks); | 19 | void kd_mksound(unsigned int hz, unsigned int ticks); |
| 32 | int kbd_rate(struct kbd_repeat *rep); | 20 | int kbd_rate(struct kbd_repeat *rep); |
| 33 | 21 | ||
| @@ -208,9 +208,6 @@ · 207 unmodified lines | |||
| 208 | /* Atheros AR933X SoC */ | 208 | /* Atheros AR933X SoC */ |
| 209 | #define PORT_AR933X 99 | 209 | #define PORT_AR933X 99 |
| 210 | 210 | ||
| 211 | /* Energy Micro efm32 SoC */ | ||
| 212 | #define PORT_EFMUART 100 | ||
| 213 | |||
| 214 | /* ARC (Synopsys) on-chip UART */ | 211 | /* ARC (Synopsys) on-chip UART */ |
| 215 | #define PORT_ARC 101 | 212 | #define PORT_ARC 101 |
| 216 | 213 | ||
| @@ -5,19 +5,4 @@ · 4 unmodified lines | |||
| 5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
| 6 | #include <asm/termios.h> | 6 | #include <asm/termios.h> |
| 7 | 7 | ||
| 8 | #define NFF 5 | ||
| 9 | |||
| 10 | struct termiox | ||
| 11 | { | ||
| 12 | __u16 x_hflag; | ||
| 13 | __u16 x_cflag; | ||
| 14 | __u16 x_rflag[NFF]; | ||
| 15 | __u16 x_sflag; | ||
| 16 | }; | ||
| 17 | |||
| 18 | #define RTSXOFF 0x0001 /* RTS flow control on input */ | ||
| 19 | #define CTSXON 0x0002 /* CTS flow control on output */ | ||
| 20 | #define DTRXOFF 0x0004 /* DTR flow control on input */ | ||
| 21 | #define DSRXON 0x0008 /* DCD flow control on output */ | ||
| 22 | |||
| 23 | #endif | 8 | #endif |
| @@ -292,7 +292,8 @@ static int nci_uart_tty_ioctl(struct tty_struct *tty, struct file *file, · 291 unmodified lines | |||
| 292 | 292 | ||
| 293 | /* We don't provide read/write/poll interface for user space. */ | 293 | /* We don't provide read/write/poll interface for user space. */ |
| 294 | static ssize_t nci_uart_tty_read(struct tty_struct *tty, struct file *file, | 294 | static ssize_t nci_uart_tty_read(struct tty_struct *tty, struct file *file, |
| 295 | unsigned char __user *buf, size_t nr) | 295 | unsigned char *buf, size_t nr, |
| 296 | void **cookie, unsigned long offset) | ||
| 296 | { | 297 | { |
| 297 | return 0; | 298 | return 0; |
| 298 | } | 299 | } |