xref: /linux/drivers/misc/bcm-vk/bcm_vk_tty.c (revision 69851e4ab8feeb369119a44ddca430c0ee15f0d8)
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, const u8 *buffer, int count)
190 {
191 	int index;
192 	struct bcm_vk *vk;
193 	struct bcm_vk_tty *vktty;
194 	int i;
195 
196 	index = tty->index;
197 	vk = dev_get_drvdata(tty->dev);
198 	vktty = &vk->tty[index];
199 
200 	/* Simple write each byte to circular buffer */
201 	for (i = 0; i < count; i++) {
202 		vkwrite8(vk, buffer[i], BAR_1,
203 			 VK_BAR_CHAN_DATA(vktty, to, vktty->wr));
204 		vktty->wr++;
205 		if (vktty->wr >= vktty->to_size)
206 			vktty->wr = 0;
207 	}
208 	/* Update write offset from shadow register to card */
209 	vkwrite32(vk, vktty->wr, BAR_1, VK_BAR_CHAN_WR(vktty, to));
210 	bcm_vk_tty_doorbell(vk, 0);
211 
212 	return count;
213 }
214 
215 static unsigned int bcm_vk_tty_write_room(struct tty_struct *tty)
216 {
217 	struct bcm_vk *vk = dev_get_drvdata(tty->dev);
218 
219 	return vk->tty[tty->index].to_size - 1;
220 }
221 
222 static const struct tty_operations serial_ops = {
223 	.open = bcm_vk_tty_open,
224 	.close = bcm_vk_tty_close,
225 	.write = bcm_vk_tty_write,
226 	.write_room = bcm_vk_tty_write_room,
227 };
228 
229 int bcm_vk_tty_init(struct bcm_vk *vk, char *name)
230 {
231 	int i;
232 	int err;
233 	struct tty_driver *tty_drv;
234 	struct device *dev = &vk->pdev->dev;
235 
236 	tty_drv = tty_alloc_driver
237 				(BCM_VK_NUM_TTY,
238 				 TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
239 	if (IS_ERR(tty_drv))
240 		return PTR_ERR(tty_drv);
241 
242 	/* Save struct tty_driver for uninstalling the device */
243 	vk->tty_drv = tty_drv;
244 
245 	/* initialize the tty driver */
246 	tty_drv->driver_name = KBUILD_MODNAME;
247 	tty_drv->name = kstrdup(name, GFP_KERNEL);
248 	if (!tty_drv->name) {
249 		err = -ENOMEM;
250 		goto err_tty_driver_kref_put;
251 	}
252 	tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
253 	tty_drv->subtype = SERIAL_TYPE_NORMAL;
254 	tty_drv->init_termios = tty_std_termios;
255 	tty_set_operations(tty_drv, &serial_ops);
256 
257 	/* register the tty driver */
258 	err = tty_register_driver(tty_drv);
259 	if (err) {
260 		dev_err(dev, "tty_register_driver failed\n");
261 		goto err_kfree_tty_name;
262 	}
263 
264 	for (i = 0; i < BCM_VK_NUM_TTY; i++) {
265 		struct device *tty_dev;
266 
267 		tty_port_init(&vk->tty[i].port);
268 		tty_dev = tty_port_register_device_attr(&vk->tty[i].port,
269 							tty_drv, i, dev, vk,
270 							NULL);
271 		if (IS_ERR(tty_dev)) {
272 			err = PTR_ERR(tty_dev);
273 			goto unwind;
274 		}
275 		vk->tty[i].is_opened = false;
276 	}
277 
278 	INIT_WORK(&vk->tty_wq_work, bcm_vk_tty_wq_handler);
279 	vk->tty_wq_thread = create_singlethread_workqueue("tty");
280 	if (!vk->tty_wq_thread) {
281 		dev_err(dev, "Fail to create tty workqueue thread\n");
282 		err = -ENOMEM;
283 		goto unwind;
284 	}
285 	return 0;
286 
287 unwind:
288 	while (--i >= 0)
289 		tty_port_unregister_device(&vk->tty[i].port, tty_drv, i);
290 	tty_unregister_driver(tty_drv);
291 
292 err_kfree_tty_name:
293 	kfree(tty_drv->name);
294 	tty_drv->name = NULL;
295 
296 err_tty_driver_kref_put:
297 	tty_driver_kref_put(tty_drv);
298 
299 	return err;
300 }
301 
302 void bcm_vk_tty_exit(struct bcm_vk *vk)
303 {
304 	int i;
305 
306 	del_timer_sync(&vk->serial_timer);
307 	for (i = 0; i < BCM_VK_NUM_TTY; ++i) {
308 		tty_port_unregister_device(&vk->tty[i].port,
309 					   vk->tty_drv,
310 					   i);
311 		tty_port_destroy(&vk->tty[i].port);
312 	}
313 	tty_unregister_driver(vk->tty_drv);
314 
315 	kfree(vk->tty_drv->name);
316 	vk->tty_drv->name = NULL;
317 
318 	tty_driver_kref_put(vk->tty_drv);
319 }
320 
321 void bcm_vk_tty_terminate_tty_user(struct bcm_vk *vk)
322 {
323 	struct bcm_vk_tty *vktty;
324 	int i;
325 
326 	for (i = 0; i < BCM_VK_NUM_TTY; ++i) {
327 		vktty = &vk->tty[i];
328 		if (vktty->pid)
329 			kill_pid(find_vpid(vktty->pid), SIGKILL, 1);
330 	}
331 }
332 
333 void bcm_vk_tty_wq_exit(struct bcm_vk *vk)
334 {
335 	cancel_work_sync(&vk->tty_wq_work);
336 	destroy_workqueue(vk->tty_wq_thread);
337 }
338