aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLogan Gunthorpe <logang@deltatee.com>2017-08-03 14:19:47 -0400
committerJon Mason <jdmason@kudzu.us>2017-11-18 20:37:12 -0500
commitec0467ccbdeb69a86c8729073057bda7bce00eec (patch)
tree1ecef00f35997951e9f3380c8057fd9e0e4567d3
parent33dea5aae0320345af26ae9aba0894a930e0d4ec (diff)
NTB: switchtec_ntb: Initialize hardware for memory windows
Add the code to initialize the memory windows in the hardware. This includes setting up the requester ID table, and figuring out which BAR corresponds to which memory window. (Seeing the switch can be configured with any number of BARs.) Also, seeing the device doesn't have hardware for scratchpads or determining the link status, we create a shared memory window that has these features. A magic number with a version component will be used to determine if the other side's driver is actually up. The shared memory window also informs the other side of the size and count of the local memory windows. Signed-off-by: Logan Gunthorpe <logang@deltatee.com> Reviewed-by: Stephen Bates <sbates@raithlin.com> Reviewed-by: Kurt Schwemmer <kurt.schwemmer@microsemi.com> Acked-by: Allen Hubbe <Allen.Hubbe@dell.com> Signed-off-by: Jon Mason <jdmason@kudzu.us>
-rw-r--r--drivers/ntb/hw/mscc/ntb_hw_switchtec.c360
1 files changed, 360 insertions, 0 deletions
diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
index 253efba72275..831bfdf40068 100644
--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -15,37 +15,396 @@
15 15
16#include <linux/switchtec.h> 16#include <linux/switchtec.h>
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/delay.h>
19#include <linux/kthread.h>
18 20
19MODULE_DESCRIPTION("Microsemi Switchtec(tm) NTB Driver"); 21MODULE_DESCRIPTION("Microsemi Switchtec(tm) NTB Driver");
20MODULE_VERSION("0.1"); 22MODULE_VERSION("0.1");
21MODULE_LICENSE("GPL"); 23MODULE_LICENSE("GPL");
22MODULE_AUTHOR("Microsemi Corporation"); 24MODULE_AUTHOR("Microsemi Corporation");
23 25
26static bool use_lut_mws;
27module_param(use_lut_mws, bool, 0644);
28MODULE_PARM_DESC(use_lut_mws,
29 "Enable the use of the LUT based memory windows");
30
31#ifndef ioread64
32#ifdef readq
33#define ioread64 readq
34#else
35#define ioread64 _ioread64
36static inline u64 _ioread64(void __iomem *mmio)
37{
38 u64 low, high;
39
40 low = ioread32(mmio);
41 high = ioread32(mmio + sizeof(u32));
42 return low | (high << 32);
43}
44#endif
45#endif
46
47#ifndef iowrite64
48#ifdef writeq
49#define iowrite64 writeq
50#else
51#define iowrite64 _iowrite64
52static inline void _iowrite64(u64 val, void __iomem *mmio)
53{
54 iowrite32(val, mmio);
55 iowrite32(val >> 32, mmio + sizeof(u32));
56}
57#endif
58#endif
59
60#define SWITCHTEC_NTB_MAGIC 0x45CC0001
61#define MAX_MWS 128
62
63struct shared_mw {
64 u32 magic;
65 u32 partition_id;
66 u64 mw_sizes[MAX_MWS];
67};
68
69#define MAX_DIRECT_MW ARRAY_SIZE(((struct ntb_ctrl_regs *)(0))->bar_entry)
70#define LUT_SIZE SZ_64K
71
24struct switchtec_ntb { 72struct switchtec_ntb {
25 struct switchtec_dev *stdev; 73 struct switchtec_dev *stdev;
74
75 int self_partition;
76 int peer_partition;
77
78 struct ntb_info_regs __iomem *mmio_ntb;
79 struct ntb_ctrl_regs __iomem *mmio_ctrl;
80 struct ntb_dbmsg_regs __iomem *mmio_dbmsg;
81 struct ntb_ctrl_regs __iomem *mmio_self_ctrl;
82 struct ntb_ctrl_regs __iomem *mmio_peer_ctrl;
83 struct ntb_dbmsg_regs __iomem *mmio_self_dbmsg;
84
85 struct shared_mw *self_shared;
86 struct shared_mw __iomem *peer_shared;
87 dma_addr_t self_shared_dma;
88
89 int nr_direct_mw;
90 int nr_lut_mw;
91 int direct_mw_to_bar[MAX_DIRECT_MW];
92
93 int peer_nr_direct_mw;
94 int peer_nr_lut_mw;
95 int peer_direct_mw_to_bar[MAX_DIRECT_MW];
26}; 96};
27 97
98static int switchtec_ntb_part_op(struct switchtec_ntb *sndev,
99 struct ntb_ctrl_regs __iomem *ctl,
100 u32 op, int wait_status)
101{
102 static const char * const op_text[] = {
103 [NTB_CTRL_PART_OP_LOCK] = "lock",
104 [NTB_CTRL_PART_OP_CFG] = "configure",
105 [NTB_CTRL_PART_OP_RESET] = "reset",
106 };
107
108 int i;
109 u32 ps;
110 int status;
111
112 switch (op) {
113 case NTB_CTRL_PART_OP_LOCK:
114 status = NTB_CTRL_PART_STATUS_LOCKING;
115 break;
116 case NTB_CTRL_PART_OP_CFG:
117 status = NTB_CTRL_PART_STATUS_CONFIGURING;
118 break;
119 case NTB_CTRL_PART_OP_RESET:
120 status = NTB_CTRL_PART_STATUS_RESETTING;
121 break;
122 default:
123 return -EINVAL;
124 }
125
126 iowrite32(op, &ctl->partition_op);
127
128 for (i = 0; i < 1000; i++) {
129 if (msleep_interruptible(50) != 0) {
130 iowrite32(NTB_CTRL_PART_OP_RESET, &ctl->partition_op);
131 return -EINTR;
132 }
133
134 ps = ioread32(&ctl->partition_status) & 0xFFFF;
135
136 if (ps != status)
137 break;
138 }
139
140 if (ps == wait_status)
141 return 0;
142
143 if (ps == status) {
144 dev_err(&sndev->stdev->dev,
145 "Timed out while peforming %s (%d). (%08x)",
146 op_text[op], op,
147 ioread32(&ctl->partition_status));
148
149 return -ETIMEDOUT;
150 }
151
152 return -EIO;
153}
154
155static void switchtec_ntb_init_sndev(struct switchtec_ntb *sndev)
156{
157 u64 part_map;
158
159 sndev->self_partition = sndev->stdev->partition;
160
161 sndev->mmio_ntb = sndev->stdev->mmio_ntb;
162 part_map = ioread64(&sndev->mmio_ntb->ep_map);
163 part_map &= ~(1 << sndev->self_partition);
164 sndev->peer_partition = ffs(part_map) - 1;
165
166 dev_dbg(&sndev->stdev->dev, "Partition ID %d of %d (%llx)",
167 sndev->self_partition, sndev->stdev->partition_count,
168 part_map);
169
170 sndev->mmio_ctrl = (void * __iomem)sndev->mmio_ntb +
171 SWITCHTEC_NTB_REG_CTRL_OFFSET;
172 sndev->mmio_dbmsg = (void * __iomem)sndev->mmio_ntb +
173 SWITCHTEC_NTB_REG_DBMSG_OFFSET;
174
175 sndev->mmio_self_ctrl = &sndev->mmio_ctrl[sndev->self_partition];
176 sndev->mmio_peer_ctrl = &sndev->mmio_ctrl[sndev->peer_partition];
177 sndev->mmio_self_dbmsg = &sndev->mmio_dbmsg[sndev->self_partition];
178}
179
180static int map_bars(int *map, struct ntb_ctrl_regs __iomem *ctrl)
181{
182 int i;
183 int cnt = 0;
184
185 for (i = 0; i < ARRAY_SIZE(ctrl->bar_entry); i++) {
186 u32 r = ioread32(&ctrl->bar_entry[i].ctl);
187
188 if (r & NTB_CTRL_BAR_VALID)
189 map[cnt++] = i;
190 }
191
192 return cnt;
193}
194
195static void switchtec_ntb_init_mw(struct switchtec_ntb *sndev)
196{
197 sndev->nr_direct_mw = map_bars(sndev->direct_mw_to_bar,
198 sndev->mmio_self_ctrl);
199
200 sndev->nr_lut_mw = ioread16(&sndev->mmio_self_ctrl->lut_table_entries);
201 sndev->nr_lut_mw = rounddown_pow_of_two(sndev->nr_lut_mw);
202
203 dev_dbg(&sndev->stdev->dev, "MWs: %d direct, %d lut",
204 sndev->nr_direct_mw, sndev->nr_lut_mw);
205
206 sndev->peer_nr_direct_mw = map_bars(sndev->peer_direct_mw_to_bar,
207 sndev->mmio_peer_ctrl);
208
209 sndev->peer_nr_lut_mw =
210 ioread16(&snd