1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright 2018-2020 Broadcom.
7 #include <linux/tty_driver.h>
8 #include <linux/tty_flip.h>
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)
24 struct bcm_vk_tty_chan {
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))
39 #define VK_BAR0_REGSEG_TTY_DB_OFFSET 0x86c
41 /* Poll every 1/10 of second - temp hack till we use MSI interrupt */
42 #define SERIAL_TIMER_VALUE (HZ / 10)
44 static void bcm_vk_tty_poll(struct timer_list *t)
46 struct bcm_vk *vk = from_timer(vk, t, serial_timer);
48 queue_work(vk->tty_wq_thread, &vk->tty_wq_work);
49 mod_timer(&vk->serial_timer, jiffies + SERIAL_TIMER_VALUE);
52 irqreturn_t bcm_vk_tty_irqhandler(int irq, void *dev_id)
54 struct bcm_vk *vk = dev_id;
56 queue_work(vk->tty_wq_thread, &vk->tty_wq_work);
61 static void bcm_vk_tty_wq_handler(struct work_struct *work)
63 struct bcm_vk *vk = container_of(work, struct bcm_vk, tty_wq_work);
64 struct bcm_vk_tty *vktty;
71 card_status = vkread32(vk, BAR_0, BAR_CARD_STATUS);
72 if (BCM_VK_INTF_IS_DOWN(card_status))
75 for (i = 0; i < BCM_VK_NUM_TTY; i++) {
77 /* Check the card status that the tty channel is ready */
78 if ((card_status & BIT(i)) == 0)
83 /* Don't increment read index if tty app is closed */
84 if (!vktty->is_opened)
87 /* Fetch the wr offset in buffer from VK */
88 wr = vkread32(vk, BAR_1, VK_BAR_CHAN_WR(vktty, from));
90 /* safe to ignore until bar read gives proper size */
91 if (vktty->from_size == 0)
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 */
103 * Simple read of circular buffer and
104 * insert into tty flip buffer
106 while (vk->tty[i].rd != wr) {
107 c = vkread8(vk, BAR_1,
108 VK_BAR_CHAN_DATA(vktty, from, vktty->rd));
110 if (vktty->rd >= vktty->from_size)
112 tty_insert_flip_char(&vktty->port, c, TTY_NORMAL);
117 tty_flip_buffer_push(&vktty->port);
119 /* Update read offset from shadow register to card */
120 vkwrite32(vk, vktty->rd, BAR_1,
121 VK_BAR_CHAN_RD(vktty, from));
126 static int bcm_vk_tty_open(struct tty_struct *tty, struct file *file)
130 struct bcm_vk_tty *vktty;
133 /* initialize the pointer in case something fails */
134 tty->driver_data = NULL;
136 vk = (struct bcm_vk *)dev_get_drvdata(tty->dev);
139 if (index >= BCM_VK_NUM_TTY)
142 vktty = &vk->tty[index];
144 vktty->pid = task_pid_nr(current);
145 vktty->to_offset = TO_TTYK_BASE(index);
146 vktty->from_offset = FROM_TTYK_BASE(index);
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))
154 * Get shadow registers of the buffer sizes and the "to" write offset
155 * and "from" read offset
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;
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);
170 static void bcm_vk_tty_close(struct tty_struct *tty, struct file *file)
172 struct bcm_vk *vk = dev_get_drvdata(tty->dev);
174 if (tty->index >= BCM_VK_NUM_TTY)
177 vk->tty[tty->index].is_opened = false;
180 del_timer_sync(&vk->serial_timer);
183 static void bcm_vk_tty_doorbell(struct bcm_vk *vk, u32 db_val)
185 vkwrite32(vk, db_val, BAR_0,
186 VK_BAR0_REGSEG_DB_BASE + VK_BAR0_REGSEG_TTY_DB_OFFSET);
189 static int bcm_vk_tty_write(struct tty_struct *tty,
190 const unsigned char *buffer,
195 struct bcm_vk_tty *vktty;
199 vk = dev_get_drvdata(tty->dev);
200 vktty = &vk->tty[index];
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));
207 if (vktty->wr >= vktty->to_size)
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);
217 static unsigned int bcm_vk_tty_write_room(struct tty_struct *tty)
219 struct bcm_vk *vk = dev_get_drvdata(tty->dev);
221 return vk->tty[tty->index].to_size - 1;
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,
231 int bcm_vk_tty_init(struct bcm_vk *vk, char *name)
235 struct tty_driver *tty_drv;
236 struct device *dev = &vk->pdev->dev;
238 tty_drv = tty_alloc_driver
240 TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
242 return PTR_ERR(tty_drv);
244 /* Save struct tty_driver for uninstalling the device */
245 vk->tty_drv = tty_drv;
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) {
252 goto err_tty_driver_kref_put;
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);
259 /* register the tty driver */
260 err = tty_register_driver(tty_drv);
262 dev_err(dev, "tty_register_driver failed\n");
263 goto err_kfree_tty_name;
266 for (i = 0; i < BCM_VK_NUM_TTY; i++) {
267 struct device *tty_dev;
269 tty_port_init(&vk->tty[i].port);
270 tty_dev = tty_port_register_device(&vk->tty[i].port, tty_drv,
272 if (IS_ERR(tty_dev)) {
273 err = PTR_ERR(tty_dev);
276 dev_set_drvdata(tty_dev, vk);
277 vk->tty[i].is_opened = false;
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");
291 tty_port_unregister_device(&vk->tty[i].port, tty_drv, i);
292 tty_unregister_driver(tty_drv);
295 kfree(tty_drv->name);
296 tty_drv->name = NULL;
298 err_tty_driver_kref_put:
299 tty_driver_kref_put(tty_drv);
304 void bcm_vk_tty_exit(struct bcm_vk *vk)
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,
313 tty_port_destroy(&vk->tty[i].port);
315 tty_unregister_driver(vk->tty_drv);
317 kfree(vk->tty_drv->name);
318 vk->tty_drv->name = NULL;
320 tty_driver_kref_put(vk->tty_drv);
323 void bcm_vk_tty_terminate_tty_user(struct bcm_vk *vk)
325 struct bcm_vk_tty *vktty;
328 for (i = 0; i < BCM_VK_NUM_TTY; ++i) {
331 kill_pid(find_vpid(vktty->pid), SIGKILL, 1);
335 void bcm_vk_tty_wq_exit(struct bcm_vk *vk)
337 cancel_work_sync(&vk->tty_wq_work);
338 destroy_workqueue(vk->tty_wq_thread);