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