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 ssize_t
bcm_vk_tty_write(struct tty_struct
*tty
, const u8
*buffer
,
194 struct bcm_vk_tty
*vktty
;
198 vk
= dev_get_drvdata(tty
->dev
);
199 vktty
= &vk
->tty
[index
];
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
));
206 if (vktty
->wr
>= vktty
->to_size
)
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);
216 static unsigned int bcm_vk_tty_write_room(struct tty_struct
*tty
)
218 struct bcm_vk
*vk
= dev_get_drvdata(tty
->dev
);
220 return vk
->tty
[tty
->index
].to_size
- 1;
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
,
230 int bcm_vk_tty_init(struct bcm_vk
*vk
, char *name
)
234 struct tty_driver
*tty_drv
;
235 struct device
*dev
= &vk
->pdev
->dev
;
237 tty_drv
= tty_alloc_driver
239 TTY_DRIVER_REAL_RAW
| TTY_DRIVER_DYNAMIC_DEV
);
241 return PTR_ERR(tty_drv
);
243 /* Save struct tty_driver for uninstalling the device */
244 vk
->tty_drv
= tty_drv
;
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
) {
251 goto err_tty_driver_kref_put
;
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
);
258 /* register the tty driver */
259 err
= tty_register_driver(tty_drv
);
261 dev_err(dev
, "tty_register_driver failed\n");
262 goto err_kfree_tty_name
;
265 for (i
= 0; i
< BCM_VK_NUM_TTY
; i
++) {
266 struct device
*tty_dev
;
268 tty_port_init(&vk
->tty
[i
].port
);
269 tty_dev
= tty_port_register_device_attr(&vk
->tty
[i
].port
,
272 if (IS_ERR(tty_dev
)) {
273 err
= PTR_ERR(tty_dev
);
276 vk
->tty
[i
].is_opened
= false;
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");
290 tty_port_unregister_device(&vk
->tty
[i
].port
, tty_drv
, i
);
291 tty_unregister_driver(tty_drv
);
294 kfree(tty_drv
->name
);
295 tty_drv
->name
= NULL
;
297 err_tty_driver_kref_put
:
298 tty_driver_kref_put(tty_drv
);
303 void bcm_vk_tty_exit(struct bcm_vk
*vk
)
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
,
312 tty_port_destroy(&vk
->tty
[i
].port
);
314 tty_unregister_driver(vk
->tty_drv
);
316 kfree(vk
->tty_drv
->name
);
317 vk
->tty_drv
->name
= NULL
;
319 tty_driver_kref_put(vk
->tty_drv
);
322 void bcm_vk_tty_terminate_tty_user(struct bcm_vk
*vk
)
324 struct bcm_vk_tty
*vktty
;
327 for (i
= 0; i
< BCM_VK_NUM_TTY
; ++i
) {
330 kill_pid(find_vpid(vktty
->pid
), SIGKILL
, 1);
334 void bcm_vk_tty_wq_exit(struct bcm_vk
*vk
)
336 cancel_work_sync(&vk
->tty_wq_work
);
337 destroy_workqueue(vk
->tty_wq_thread
);