aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/hvc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-06 14:14:33 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-06 14:14:33 -0400
commit4de9ad9bc08b4953fc03336ad38908496e2f8826 (patch)
treebd44add223061a58317034a0d6c9686d95d12fba /drivers/tty/hvc
parent576c25eb5954035b64112188d9a2683144600f3d (diff)
parent06da6629e68ddc8ffe2933d33b3681f09104b3f1 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile
Pull Tile arch updates from Chris Metcalf: "These changes bring in a bunch of new functionality that has been maintained internally at Tilera over the last year, plus other stray bits of work that I've taken into the tile tree from other folks. The changes include some PCI root complex work, interrupt-driven console support, support for performing fast-path unaligned data fixups by kernel-based JIT code generation, CONFIG_PREEMPT support, vDSO support for gettimeofday(), a serial driver for the tilegx on-chip UART, KGDB support, more optimized string routines, support for ftrace and kprobes, improved ASLR, and many bug fixes. We also remove support for the old TILE64 chip, which is no longer buildable" * git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile: (85 commits) tile: refresh tile defconfig files tile: rework <asm/cmpxchg.h> tile PCI RC: make default consistent DMA mask 32-bit tile: add null check for kzalloc in tile/kernel/setup.c tile: make __write_once a synonym for __read_mostly tile: remove support for TILE64 tile: use asm-generic/bitops/builtin-*.h tile: eliminate no-op "noatomichash" boot argument tile: use standard tile_bundle_bits type in traps.c tile: simplify code referencing hypervisor API addresses tile: change <asm/system.h> to <asm/switch_to.h> in comments tile: mark pcibios_init() as __init tile: check for correct compiler earlier in asm-offsets.c tile: use standard 'generic-y' model for <asm/hw_irq.h> tile: use asm-generic version of <asm/local64.h> tile PCI RC: add comment about "PCI hole" problem tile: remove DEBUG_EXTRA_FLAGS kernel config option tile: add virt_to_kpte() API and clean up and document behavior tile: support FRAME_POINTER tile: support reporting Tilera hypervisor statistics ...
Diffstat (limited to 'drivers/tty/hvc')
-rw-r--r--drivers/tty/hvc/hvc_tile.c149
1 files changed, 143 insertions, 6 deletions
diff --git a/drivers/tty/hvc/hvc_tile.c b/drivers/tty/hvc/hvc_tile.c
index 7a84a0595477..af8cdaa1dcb9 100644
--- a/drivers/tty/hvc/hvc_tile.c
+++ b/drivers/tty/hvc/hvc_tile.c
@@ -18,16 +18,46 @@
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/err.h> 19#include <linux/err.h>
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/interrupt.h>
22#include <linux/irq.h>
21#include <linux/moduleparam.h> 23#include <linux/moduleparam.h>
24#include <linux/platform_device.h>
22#include <linux/types.h> 25#include <linux/types.h>
23 26
27#include <asm/setup.h>
28#include <arch/sim_def.h>
29
24#include <hv/hypervisor.h> 30#include <hv/hypervisor.h>
25 31
26#include "hvc_console.h" 32#include "hvc_console.h"
27 33
34static int use_sim_console;
35static int __init sim_console(char *str)
36{
37 use_sim_console = 1;
38 return 0;
39}
40early_param("sim_console", sim_console);
41
42int tile_console_write(const char *buf, int count)
43{
44 if (unlikely(use_sim_console)) {
45 int i;
46 for (i = 0; i < count; ++i)
47 __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
48 (buf[i] << _SIM_CONTROL_OPERATOR_BITS));
49 __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
50 (SIM_PUTC_FLUSH_BINARY <<
51 _SIM_CONTROL_OPERATOR_BITS));
52 return 0;
53 } else {
54 return hv_console_write((HV_VirtAddr)buf, count);
55 }
56}
57
28static int hvc_tile_put_chars(uint32_t vt, const char *buf, int count) 58static int hvc_tile_put_chars(uint32_t vt, const char *buf, int count)
29{ 59{
30 return hv_console_write((HV_VirtAddr)buf, count); 60 return tile_console_write(buf, count);
31} 61}
32 62
33static int hvc_tile_get_chars(uint32_t vt, char *buf, int count) 63static int hvc_tile_get_chars(uint32_t vt, char *buf, int count)
@@ -44,25 +74,132 @@ static int hvc_tile_get_chars(uint32_t vt, char *buf, int count)
44 return i; 74 return i;
45} 75}
46 76
77#ifdef __tilegx__
78/*
79 * IRQ based callbacks.
80 */
81static int hvc_tile_notifier_add_irq(struct hvc_struct *hp, int irq)
82{
83 int rc;
84 int cpu = raw_smp_processor_id(); /* Choose an arbitrary cpu */
85 HV_Coord coord = { .x = cpu_x(cpu), .y = cpu_y(cpu) };
86
87 rc = notifier_add_irq(hp, irq);
88 if (rc)
89 return rc;
90
91 /*
92 * Request that the hypervisor start sending us interrupts.
93 * If the hypervisor returns an error, we still return 0, so that
94 * we can fall back to polling.
95 */
96 if (hv_console_set_ipi(KERNEL_PL, irq, coord) < 0)
97 notifier_del_irq(hp, irq);
98
99 return 0;
100}
101
102static void hvc_tile_notifier_del_irq(struct hvc_struct *hp, int irq)
103{
104 HV_Coord coord = { 0, 0 };
105
106 /* Tell the hypervisor to stop sending us interrupts. */
107 hv_console_set_ipi(KERNEL_PL, -1, coord);
108
109 notifier_del_irq(hp, irq);
110}
111
112static void hvc_tile_notifier_hangup_irq(struct hvc_struct *hp, int irq)
113{
114 hvc_tile_notifier_del_irq(hp, irq);
115}
116#endif
117
47static const struct hv_ops hvc_tile_get_put_ops = { 118static const struct hv_ops hvc_tile_get_put_ops = {
48 .get_chars = hvc_tile_get_chars, 119 .get_chars = hvc_tile_get_chars,
49 .put_chars = hvc_tile_put_chars, 120 .put_chars = hvc_tile_put_chars,
121#ifdef __tilegx__
122 .notifier_add = hvc_tile_notifier_add_irq,
123 .notifier_del = hvc_tile_notifier_del_irq,
124 .notifier_hangup = hvc_tile_notifier_hangup_irq,
125#endif
126};
127
128
129#ifdef __tilegx__
130static int hvc_tile_probe(struct platform_device *pdev)
131{
132 struct hvc_struct *hp;
133 int tile_hvc_irq;
134
135 /* Create our IRQ and register it. */
136 tile_hvc_irq = create_irq();
137 if (tile_hvc_irq < 0)
138 return -ENXIO;
139
140 tile_irq_activate(tile_hvc_irq, TILE_IRQ_PERCPU);
141 hp = hvc_alloc(0, tile_hvc_irq, &hvc_tile_get_put_ops, 128);
142 if (IS_ERR(hp)) {
143 destroy_irq(tile_hvc_irq);
144 return PTR_ERR(hp);
145 }
146 dev_set_drvdata(&pdev->dev, hp);
147
148 return 0;
149}
150
151static int hvc_tile_remove(struct platform_device *pdev)
152{
153 int rc;
154 struct hvc_struct *hp = dev_get_drvdata(&pdev->dev);
155
156 rc = hvc_remove(hp);
157 if (rc == 0)
158 destroy_irq(hp->data);
159
160 return rc;
161}
162
163static void hvc_tile_shutdown(struct platform_device *pdev)
164{
165 struct hvc_struct *hp = dev_get_drvdata(&pdev->dev);
166
167 hvc_tile_notifier_del_irq(hp, hp->data);
168}
169
170static struct platform_device hvc_tile_pdev = {
171 .name = "hvc-tile",
172 .id = 0,
173};
174
175static struct platform_driver hvc_tile_driver = {
176 .probe = hvc_tile_probe,
177 .remove = hvc_tile_remove,
178 .shutdown = hvc_tile_shutdown,
179 .driver = {
180 .name = "hvc-tile",
181 .owner = THIS_MODULE,
182 }
50}; 183};
184#endif
51 185
52static int __init hvc_tile_console_init(void) 186static int __init hvc_tile_console_init(void)
53{ 187{
54 extern void disable_early_printk(void);
55 hvc_instantiate(0, 0, &hvc_tile_get_put_ops); 188 hvc_instantiate(0, 0, &hvc_tile_get_put_ops);
56 add_preferred_console("hvc", 0, NULL); 189 add_preferred_console("hvc", 0, NULL);
57 disable_early_printk();
58 return 0; 190 return 0;
59} 191}
60console_initcall(hvc_tile_console_init); 192console_initcall(hvc_tile_console_init);
61 193
62static int __init hvc_tile_init(void) 194static int __init hvc_tile_init(void)
63{ 195{
64 struct hvc_struct *s; 196#ifndef __tilegx__
65 s = hvc_alloc(0, 0, &hvc_tile_get_put_ops, 128); 197 struct hvc_struct *hp;
66 return IS_ERR(s) ? PTR_ERR(s) : 0; 198 hp = hvc_alloc(0, 0, &hvc_tile_get_put_ops, 128);
199 return IS_ERR(hp) ? PTR_ERR(hp) : 0;
200#else
201 platform_device_register(&hvc_tile_pdev);
202 return platform_driver_register(&hvc_tile_driver);
203#endif
67} 204}
68device_initcall(hvc_tile_init); 205device_initcall(hvc_tile_init);