Merge branch 'work.ecryptfs' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux-2.6-microblaze.git] / drivers / misc / bcm-vk / bcm_vk_tty.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2018-2020 Broadcom.
4  */
5
6 #include <linux/tty.h>
7 #include <linux/tty_driver.h>
8 #include <linux/tty_flip.h>
9
10 #include "bcm_vk.h"
11
12 /* TTYVK base offset is 0x30000 into BAR1 */
13 #define BAR1_TTYVK_BASE_OFFSET  0x300000
14 /* Each TTYVK channel (TO or FROM) is 0x10000 */
15 #define BAR1_TTYVK_CHAN_OFFSET  0x100000
16 /* Each TTYVK channel has TO and FROM, hence the * 2 */
17 #define BAR1_TTYVK_BASE(index)  (BAR1_TTYVK_BASE_OFFSET + \
18                                  ((index) * BAR1_TTYVK_CHAN_OFFSET * 2))
19 /* TO TTYVK channel base comes before FROM for each index */
20 #define TO_TTYK_BASE(index)     BAR1_TTYVK_BASE(index)
21 #define FROM_TTYK_BASE(index)   (BAR1_TTYVK_BASE(index) + \
22                                  BAR1_TTYVK_CHAN_OFFSET)
23
24 struct bcm_vk_tty_chan {
25         u32 reserved;
26         u32 size;
27         u32 wr;
28         u32 rd;
29         u32 *data;
30 };
31
32 #define VK_BAR_CHAN(v, DIR, e)  ((v)->DIR##_offset \
33                                  + offsetof(struct bcm_vk_tty_chan, e))
34 #define VK_BAR_CHAN_SIZE(v, DIR)        VK_BAR_CHAN(v, DIR, size)
35 #define VK_BAR_CHAN_WR(v, DIR)          VK_BAR_CHAN(v, DIR, wr)
36 #define VK_BAR_CHAN_RD(v, DIR)          VK_BAR_CHAN(v, DIR, rd)
37 #define VK_BAR_CHAN_DATA(v, DIR, off)   (VK_BAR_CHAN(v, DIR, data) + (off))
38
39 #define VK_BAR0_REGSEG_TTY_DB_OFFSET    0x86c
40
41 /* Poll every 1/10 of second - temp hack till we use MSI interrupt */
42 #define SERIAL_TIMER_VALUE (HZ / 10)
43
44 static void bcm_vk_tty_poll(struct timer_list *t)
45 {
46         struct bcm_vk *vk = from_timer(vk, t, serial_timer);
47
48         queue_work(vk->tty_wq_thread, &vk->tty_wq_work);
49         mod_timer(&vk->serial_timer, jiffies + SERIAL_TIMER_VALUE);
50 }
51
52 irqreturn_t bcm_vk_tty_irqhandler(int irq, void *dev_id)
53 {
54         struct bcm_vk *vk = dev_id;
55
56         queue_work(vk->tty_wq_thread, &vk->tty_wq_work);
57
58         return IRQ_HANDLED;
59 }
60
61 static void bcm_vk_tty_wq_handler(struct work_struct *work)
62 {
63         struct bcm_vk *vk = container_of(work, struct bcm_vk, tty_wq_work);
64         struct bcm_vk_tty *vktty;
65         int card_status;
66         int count;
67         unsigned char c;
68         int i;
69         int wr;
70
71         card_status = vkread32(vk, BAR_0, BAR_CARD_STATUS);
72         if (BCM_VK_INTF_IS_DOWN(card_status))
73                 return;
74
75         for (i = 0; i < BCM_VK_NUM_TTY; i++) {
76                 count = 0;
77                 /* Check the card status that the tty channel is ready */
78                 if ((card_status & BIT(i)) == 0)
79                         continue;
80
81                 vktty = &vk->tty[i];
82
83                 /* Don't increment read index if tty app is closed */
84                 if (!vktty->is_opened)
85                         continue;
86
87                 /* Fetch the wr offset in buffer from VK */
88                 wr = vkread32(vk, BAR_1, VK_BAR_CHAN_WR(vktty, from));
89
90                 /* safe to ignore until bar read gives proper size */
91                 if (vktty->from_size == 0)
92                         continue;
93
94                 if (wr >= vktty->from_size) {
95                         dev_err(&vk->pdev->dev,
96                                 "ERROR: wq handler ttyVK%d wr:0x%x > 0x%x\n",
97                                 i, wr, vktty->from_size);
98                         /* Need to signal and close device in this case */
99                         continue;
100                 }
101
102                 /*
103                  * Simple read of circular buffer and
104                  * insert into tty flip buffer
105                  */
106                 while (vk->tty[i].rd != wr) {
107                         c = vkread8(vk, BAR_1,
108                                     VK_BAR_CHAN_DATA(vktty, from, vktty->rd));
109                         vktty->rd++;
110                         if (vktty->rd >= vktty->from_size)
111                                 vktty->rd = 0;
112                         tty_insert_flip_char(&vktty->port, c, TTY_NORMAL);
113                         count++;
114                 }
115
116                 if (count) {
117                         tty_flip_buffer_push(&vktty->port);
118
119                         /* Update read offset from shadow register to card */
120                         vkwrite32(vk, vktty->rd, BAR_1,
121                                   VK_BAR_CHAN_RD(vktty, from));
122                 }
123         }
124 }
125
126 static int bcm_vk_tty_open(struct tty_struct *tty, struct file *file)
127 {
128         int card_status;
129         struct bcm_vk *vk;
130         struct bcm_vk_tty *vktty;
131         int index;
132
133         /* initialize the pointer in case something fails */
134         tty->driver_data = NULL;
135
136         vk = (struct bcm_vk *)dev_get_drvdata(tty->dev);
137         index = tty->index;
138
139         if (index >= BCM_VK_NUM_TTY)
140                 return -EINVAL;
141
142         vktty = &vk->tty[index];
143
144         vktty->pid = task_pid_nr(current);
145         vktty->to_offset = TO_TTYK_BASE(index);
146         vktty->from_offset = FROM_TTYK_BASE(index);
147
148         /* Do not allow tty device to be opened if tty on card not ready */
149         card_status = vkread32(vk, BAR_0, BAR_CARD_STATUS);
150         if (BCM_VK_INTF_IS_DOWN(card_status) || ((card_status & BIT(index)) == 0))
151                 return -EBUSY;
152
153         /*
154          * Get shadow registers of the buffer sizes and the "to" write offset
155          * and "from" read offset
156          */
157         vktty->to_size = vkread32(vk, BAR_1, VK_BAR_CHAN_SIZE(vktty, to));
158         vktty->wr = vkread32(vk, BAR_1,  VK_BAR_CHAN_WR(vktty, to));
159         vktty->from_size = vkread32(vk, BAR_1, VK_BAR_CHAN_SIZE(vktty, from));
160         vktty->rd = vkread32(vk, BAR_1,  VK_BAR_CHAN_RD(vktty, from));
161         vktty->is_opened = true;
162
163         if (tty->count == 1 && !vktty->irq_enabled) {
164                 timer_setup(&vk->serial_timer, bcm_vk_tty_poll, 0);
165                 mod_timer(&vk->serial_timer, jiffies + SERIAL_TIMER_VALUE);
166         }
167         return 0;
168 }
169
170 static void bcm_vk_tty_close(struct tty_struct *tty, struct file *file)
171 {
172         struct bcm_vk *vk = dev_get_drvdata(tty->dev);
173
174         if (tty->index >= BCM_VK_NUM_TTY)
175                 return;
176
177         vk->tty[tty->index].is_opened = false;
178
179         if (tty->count == 1)
180                 del_timer_sync(&vk->serial_timer);
181 }
182
183 static void bcm_vk_tty_doorbell(struct bcm_vk *vk, u32 db_val)
184 {
185         vkwrite32(vk, db_val, BAR_0,
186                   VK_BAR0_REGSEG_DB_BASE + VK_BAR0_REGSEG_TTY_DB_OFFSET);
187 }
188
189 static int bcm_vk_tty_write(struct tty_struct *tty,
190                             const unsigned char *buffer,
191                             int count)
192 {
193         int index;
194         struct bcm_vk *vk;
195         struct bcm_vk_tty *vktty;
196         int i;
197
198         index = tty->index;
199         vk = dev_get_drvdata(tty->dev);
200         vktty = &vk->tty[index];
201
202         /* Simple write each byte to circular buffer */
203         for (i = 0; i < count; i++) {
204                 vkwrite8(vk, buffer[i], BAR_1,
205                          VK_BAR_CHAN_DATA(vktty, to, vktty->wr));
206                 vktty->wr++;
207                 if (vktty->wr >= vktty->to_size)
208                         vktty->wr = 0;
209         }
210         /* Update write offset from shadow register to card */
211         vkwrite32(vk, vktty->wr, BAR_1, VK_BAR_CHAN_WR(vktty, to));
212         bcm_vk_tty_doorbell(vk, 0);
213
214         return count;
215 }
216
217 static int bcm_vk_tty_write_room(struct tty_struct *tty)
218 {
219         struct bcm_vk *vk = dev_get_drvdata(tty->dev);
220
221         return vk->tty[tty->index].to_size - 1;
222 }
223
224 static const struct tty_operations serial_ops = {
225         .open = bcm_vk_tty_open,
226         .close = bcm_vk_tty_close,
227         .write = bcm_vk_tty_write,
228         .write_room = bcm_vk_tty_write_room,
229 };
230
231 int bcm_vk_tty_init(struct bcm_vk *vk, char *name)
232 {
233         int i;
234         int err;
235         struct tty_driver *tty_drv;
236         struct device *dev = &vk->pdev->dev;
237
238         tty_drv = tty_alloc_driver
239                                 (BCM_VK_NUM_TTY,
240                                  TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
241         if (IS_ERR(tty_drv))
242                 return PTR_ERR(tty_drv);
243
244         /* Save struct tty_driver for uninstalling the device */
245         vk->tty_drv = tty_drv;
246
247         /* initialize the tty driver */
248         tty_drv->driver_name = KBUILD_MODNAME;
249         tty_drv->name = kstrdup(name, GFP_KERNEL);
250         if (!tty_drv->name) {
251                 err = -ENOMEM;
252                 goto err_put_tty_driver;
253         }
254         tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
255         tty_drv->subtype = SERIAL_TYPE_NORMAL;
256         tty_drv->init_termios = tty_std_termios;
257         tty_set_operations(tty_drv, &serial_ops);
258
259         /* register the tty driver */
260         err = tty_register_driver(tty_drv);
261         if (err) {
262                 dev_err(dev, "tty_register_driver failed\n");
263                 goto err_kfree_tty_name;
264         }
265
266         for (i = 0; i < BCM_VK_NUM_TTY; i++) {
267                 struct device *tty_dev;
268
269                 tty_port_init(&vk->tty[i].port);
270                 tty_dev = tty_port_register_device(&vk->tty[i].port, tty_drv,
271                                                    i, dev);
272                 if (IS_ERR(tty_dev)) {
273                         err = PTR_ERR(tty_dev);
274                         goto unwind;
275                 }
276                 dev_set_drvdata(tty_dev, vk);
277                 vk->tty[i].is_opened = false;
278         }
279
280         INIT_WORK(&vk->tty_wq_work, bcm_vk_tty_wq_handler);
281         vk->tty_wq_thread = create_singlethread_workqueue("tty");
282         if (!vk->tty_wq_thread) {
283                 dev_err(dev, "Fail to create tty workqueue thread\n");
284                 err = -ENOMEM;
285                 goto unwind;
286         }
287         return 0;
288
289 unwind:
290         while (--i >= 0)
291                 tty_port_unregister_device(&vk->tty[i].port, tty_drv, i);
292         tty_unregister_driver(tty_drv);
293
294 err_kfree_tty_name:
295         kfree(tty_drv->name);
296         tty_drv->name = NULL;
297
298 err_put_tty_driver:
299         put_tty_driver(tty_drv);
300
301         return err;
302 }
303
304 void bcm_vk_tty_exit(struct bcm_vk *vk)
305 {
306         int i;
307
308         del_timer_sync(&vk->serial_timer);
309         for (i = 0; i < BCM_VK_NUM_TTY; ++i) {
310                 tty_port_unregister_device(&vk->tty[i].port,
311                                            vk->tty_drv,
312                                            i);
313                 tty_port_destroy(&vk->tty[i].port);
314         }
315         tty_unregister_driver(vk->tty_drv);
316
317         kfree(vk->tty_drv->name);
318         vk->tty_drv->name = NULL;
319
320         put_tty_driver(vk->tty_drv);
321 }
322
323 void bcm_vk_tty_terminate_tty_user(struct bcm_vk *vk)
324 {
325         struct bcm_vk_tty *vktty;
326         int i;
327
328         for (i = 0; i < BCM_VK_NUM_TTY; ++i) {
329                 vktty = &vk->tty[i];
330                 if (vktty->pid)
331                         kill_pid(find_vpid(vktty->pid), SIGKILL, 1);
332         }
333 }
334
335 void bcm_vk_tty_wq_exit(struct bcm_vk *vk)
336 {
337         cancel_work_sync(&vk->tty_wq_work);
338         destroy_workqueue(vk->tty_wq_thread);
339 }