blob: 9484484c82c3bd498d0bf4c08a29309c7c0380c4 [file] [log] [blame]
Matt Porter2b0c28d7f2005-11-07 01:00:19 -08001/*
Zhang Weid02443a2008-04-18 13:33:38 -07002 * Freescale MPC85xx/MPC86xx RapidIO support
Matt Porter2b0c28d7f2005-11-07 01:00:19 -08003 *
Thomas Mollbd4fb652010-05-26 14:44:05 -07004 * Copyright 2009 Sysgo AG
5 * Thomas Moll <thomas.moll@sysgo.com>
6 * - fixed maintenance access routines, check for aligned access
7 *
Alexandre Bounine5b2074a2010-05-26 14:44:00 -07008 * Copyright 2009 Integrated Device Technology, Inc.
9 * Alex Bounine <alexandre.bounine@idt.com>
10 * - Added Port-Write message handling
11 * - Added Machine Check exception handling
12 *
Liu Gang6ec4bed2011-11-12 20:02:28 +080013 * Copyright (C) 2007, 2008, 2010, 2011 Freescale Semiconductor, Inc.
Zhang Weiad1e9382008-04-18 13:33:41 -070014 * Zhang Wei <wei.zhang@freescale.com>
15 *
Matt Porter2b0c28d7f2005-11-07 01:00:19 -080016 * Copyright 2005 MontaVista Software, Inc.
17 * Matt Porter <mporter@kernel.crashing.org>
18 *
19 * This program is free software; you can redistribute it and/or modify it
20 * under the terms of the GNU General Public License as published by the
21 * Free Software Foundation; either version 2 of the License, or (at your
22 * option) any later version.
23 */
24
Matt Porter2b0c28d7f2005-11-07 01:00:19 -080025#include <linux/init.h>
Liu Gange0ce42e2011-11-11 21:48:28 +080026#include <linux/module.h>
Matt Porter2b0c28d7f2005-11-07 01:00:19 -080027#include <linux/types.h>
28#include <linux/dma-mapping.h>
29#include <linux/interrupt.h>
Anton Vorontsov0dbbbf12009-04-18 21:48:52 +040030#include <linux/device.h>
Zhang Weicc2bb692008-04-18 13:33:41 -070031#include <linux/of_platform.h>
Zhang Wei61b26912008-04-18 13:33:44 -070032#include <linux/delay.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090033#include <linux/slab.h>
Matt Porter2b0c28d7f2005-11-07 01:00:19 -080034
Liu Gang6ec4bed2011-11-12 20:02:28 +080035#include <linux/io.h>
36#include <linux/uaccess.h>
Alexandre Bouninea52c8f52010-05-26 14:44:00 -070037#include <asm/machdep.h>
Liu Gang6ec4bed2011-11-12 20:02:28 +080038
39#include "fsl_rio.h"
Matt Porter2b0c28d7f2005-11-07 01:00:19 -080040
Alexandre Bounine5b2074a2010-05-26 14:44:00 -070041#undef DEBUG_PW /* Port-Write debugging */
42
Shaohui Xie6ff31452010-11-18 14:57:53 +080043#define RIO_PORT1_EDCSR 0x0640
44#define RIO_PORT2_EDCSR 0x0680
45#define RIO_PORT1_IECSR 0x10130
46#define RIO_PORT2_IECSR 0x101B0
Shaohui Xie6ff31452010-11-18 14:57:53 +080047
Matt Porter2b0c28d7f2005-11-07 01:00:19 -080048#define RIO_ATMU_REGS_OFFSET 0x10c00
Alexandre Bounineaf84ca32010-10-27 15:34:34 -070049#define RIO_GCCSR 0x13c
Zhang Wei61b26912008-04-18 13:33:44 -070050#define RIO_ESCSR 0x158
Liu Gang6ec4bed2011-11-12 20:02:28 +080051#define ESCSR_CLEAR 0x07120204
Shaohui Xie6ff31452010-11-18 14:57:53 +080052#define RIO_PORT2_ESCSR 0x178
Zhang Wei61b26912008-04-18 13:33:44 -070053#define RIO_CCSR 0x15c
Shaohui Xie6ff31452010-11-18 14:57:53 +080054#define RIO_LTLEDCSR_IER 0x80000000
55#define RIO_LTLEDCSR_PRT 0x01000000
Liu Gang6ec4bed2011-11-12 20:02:28 +080056#define IECSR_CLEAR 0x80000000
Zhang Wei61b26912008-04-18 13:33:44 -070057#define RIO_ISR_AACR 0x10120
58#define RIO_ISR_AACR_AA 0x1 /* Accept All ID */
Matt Porter2b0c28d7f2005-11-07 01:00:19 -080059
Alexandre Bouninea52c8f52010-05-26 14:44:00 -070060#define __fsl_read_rio_config(x, addr, err, op) \
61 __asm__ __volatile__( \
62 "1: "op" %1,0(%2)\n" \
63 " eieio\n" \
64 "2:\n" \
65 ".section .fixup,\"ax\"\n" \
66 "3: li %1,-1\n" \
67 " li %0,%3\n" \
68 " b 2b\n" \
69 ".section __ex_table,\"a\"\n" \
70 " .align 2\n" \
71 " .long 1b,3b\n" \
72 ".text" \
73 : "=r" (err), "=r" (x) \
74 : "b" (addr), "i" (-EFAULT), "0" (err))
75
Liu Gang6ec4bed2011-11-12 20:02:28 +080076void __iomem *rio_regs_win;
Alexandre Bouninea52c8f52010-05-26 14:44:00 -070077
Li Yangff33f182010-06-18 14:24:20 +080078#ifdef CONFIG_E500
Shaohui Xiecce1f102010-11-18 14:57:32 +080079int fsl_rio_mcheck_exception(struct pt_regs *regs)
Alexandre Bouninea52c8f52010-05-26 14:44:00 -070080{
Scott Wood82a9a482011-06-16 14:09:17 -050081 const struct exception_table_entry *entry;
82 unsigned long reason;
Alexandre Bouninea52c8f52010-05-26 14:44:00 -070083
Scott Wood82a9a482011-06-16 14:09:17 -050084 if (!rio_regs_win)
85 return 0;
86
87 reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR));
88 if (reason & (RIO_LTLEDCSR_IER | RIO_LTLEDCSR_PRT)) {
89 /* Check if we are prepared to handle this fault */
90 entry = search_exception_tables(regs->nip);
91 if (entry) {
92 pr_debug("RIO: %s - MC Exception handled\n",
93 __func__);
94 out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR),
95 0);
96 regs->msr |= MSR_RI;
97 regs->nip = entry->fixup;
98 return 1;
Alexandre Bouninea52c8f52010-05-26 14:44:00 -070099 }
100 }
101
Shaohui Xiecce1f102010-11-18 14:57:32 +0800102 return 0;
Alexandre Bouninea52c8f52010-05-26 14:44:00 -0700103}
Shaohui Xiecce1f102010-11-18 14:57:32 +0800104EXPORT_SYMBOL_GPL(fsl_rio_mcheck_exception);
Li Yangff33f182010-06-18 14:24:20 +0800105#endif
Alexandre Bouninea52c8f52010-05-26 14:44:00 -0700106
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800107/**
Zhang Weid02443a2008-04-18 13:33:38 -0700108 * fsl_local_config_read - Generate a MPC85xx local config space read
Randy Dunlap9941d942008-04-30 16:45:58 -0700109 * @mport: RapidIO master port info
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800110 * @index: ID of RapdiIO interface
111 * @offset: Offset into configuration space
112 * @len: Length (in bytes) of the maintenance transaction
113 * @data: Value to be read into
114 *
115 * Generates a MPC85xx local configuration space read. Returns %0 on
116 * success or %-EINVAL on failure.
117 */
Zhang Weiad1e9382008-04-18 13:33:41 -0700118static int fsl_local_config_read(struct rio_mport *mport,
119 int index, u32 offset, int len, u32 *data)
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800120{
Zhang Weiad1e9382008-04-18 13:33:41 -0700121 struct rio_priv *priv = mport->priv;
Zhang Weid02443a2008-04-18 13:33:38 -0700122 pr_debug("fsl_local_config_read: index %d offset %8.8x\n", index,
Liu Gang6ec4bed2011-11-12 20:02:28 +0800123 offset);
Zhang Weiad1e9382008-04-18 13:33:41 -0700124 *data = in_be32(priv->regs_win + offset);
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800125
126 return 0;
127}
128
129/**
Zhang Weid02443a2008-04-18 13:33:38 -0700130 * fsl_local_config_write - Generate a MPC85xx local config space write
Randy Dunlap9941d942008-04-30 16:45:58 -0700131 * @mport: RapidIO master port info
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800132 * @index: ID of RapdiIO interface
133 * @offset: Offset into configuration space
134 * @len: Length (in bytes) of the maintenance transaction
135 * @data: Value to be written
136 *
137 * Generates a MPC85xx local configuration space write. Returns %0 on
138 * success or %-EINVAL on failure.
139 */
Zhang Weiad1e9382008-04-18 13:33:41 -0700140static int fsl_local_config_write(struct rio_mport *mport,
141 int index, u32 offset, int len, u32 data)
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800142{
Zhang Weiad1e9382008-04-18 13:33:41 -0700143 struct rio_priv *priv = mport->priv;
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800144 pr_debug
Liu Gang6ec4bed2011-11-12 20:02:28 +0800145 ("fsl_local_config_write: index %d offset %8.8x data %8.8x\n",
146 index, offset, data);
Zhang Weiad1e9382008-04-18 13:33:41 -0700147 out_be32(priv->regs_win + offset, data);
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800148
149 return 0;
150}
151
152/**
Zhang Weid02443a2008-04-18 13:33:38 -0700153 * fsl_rio_config_read - Generate a MPC85xx read maintenance transaction
Randy Dunlap9941d942008-04-30 16:45:58 -0700154 * @mport: RapidIO master port info
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800155 * @index: ID of RapdiIO interface
156 * @destid: Destination ID of transaction
157 * @hopcount: Number of hops to target device
158 * @offset: Offset into configuration space
159 * @len: Length (in bytes) of the maintenance transaction
160 * @val: Location to be read into
161 *
162 * Generates a MPC85xx read maintenance transaction. Returns %0 on
163 * success or %-EINVAL on failure.
164 */
165static int
Zhang Weiad1e9382008-04-18 13:33:41 -0700166fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
167 u8 hopcount, u32 offset, int len, u32 *val)
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800168{
Zhang Weiad1e9382008-04-18 13:33:41 -0700169 struct rio_priv *priv = mport->priv;
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800170 u8 *data;
Alexandre Bouninea52c8f52010-05-26 14:44:00 -0700171 u32 rval, err = 0;
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800172
173 pr_debug
Liu Gang6ec4bed2011-11-12 20:02:28 +0800174 ("fsl_rio_config_read:"
175 " index %d destid %d hopcount %d offset %8.8x len %d\n",
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800176 index, destid, hopcount, offset, len);
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800177
Thomas Mollbd4fb652010-05-26 14:44:05 -0700178 /* 16MB maintenance window possible */
179 /* allow only aligned access to maintenance registers */
180 if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len))
181 return -EINVAL;
182
183 out_be32(&priv->maint_atmu_regs->rowtar,
184 (destid << 22) | (hopcount << 12) | (offset >> 12));
Liu Gang6ec4bed2011-11-12 20:02:28 +0800185 out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10));
Thomas Mollbd4fb652010-05-26 14:44:05 -0700186
187 data = (u8 *) priv->maint_win + (offset & (RIO_MAINT_WIN_SIZE - 1));
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800188 switch (len) {
189 case 1:
Alexandre Bouninea52c8f52010-05-26 14:44:00 -0700190 __fsl_read_rio_config(rval, data, err, "lbz");
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800191 break;
192 case 2:
Alexandre Bouninea52c8f52010-05-26 14:44:00 -0700193 __fsl_read_rio_config(rval, data, err, "lhz");
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800194 break;
Thomas Mollbd4fb652010-05-26 14:44:05 -0700195 case 4:
Alexandre Bouninea52c8f52010-05-26 14:44:00 -0700196 __fsl_read_rio_config(rval, data, err, "lwz");
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800197 break;
Thomas Mollbd4fb652010-05-26 14:44:05 -0700198 default:
199 return -EINVAL;
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800200 }
201
Alexandre Bouninea52c8f52010-05-26 14:44:00 -0700202 if (err) {
203 pr_debug("RIO: cfg_read error %d for %x:%x:%x\n",
204 err, destid, hopcount, offset);
205 }
206
207 *val = rval;
208
209 return err;
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800210}
211
212/**
Zhang Weid02443a2008-04-18 13:33:38 -0700213 * fsl_rio_config_write - Generate a MPC85xx write maintenance transaction
Randy Dunlap9941d942008-04-30 16:45:58 -0700214 * @mport: RapidIO master port info
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800215 * @index: ID of RapdiIO interface
216 * @destid: Destination ID of transaction
217 * @hopcount: Number of hops to target device
218 * @offset: Offset into configuration space
219 * @len: Length (in bytes) of the maintenance transaction
220 * @val: Value to be written
221 *
222 * Generates an MPC85xx write maintenance transaction. Returns %0 on
223 * success or %-EINVAL on failure.
224 */
225static int
Zhang Weiad1e9382008-04-18 13:33:41 -0700226fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
227 u8 hopcount, u32 offset, int len, u32 val)
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800228{
Zhang Weiad1e9382008-04-18 13:33:41 -0700229 struct rio_priv *priv = mport->priv;
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800230 u8 *data;
231 pr_debug
Liu Gang6ec4bed2011-11-12 20:02:28 +0800232 ("fsl_rio_config_write:"
233 "index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n",
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800234 index, destid, hopcount, offset, len, val);
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800235
Thomas Mollbd4fb652010-05-26 14:44:05 -0700236 /* 16MB maintenance windows possible */
237 /* allow only aligned access to maintenance registers */
238 if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len))
239 return -EINVAL;
240
241 out_be32(&priv->maint_atmu_regs->rowtar,
242 (destid << 22) | (hopcount << 12) | (offset >> 12));
Liu Gang6ec4bed2011-11-12 20:02:28 +0800243 out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10));
Thomas Mollbd4fb652010-05-26 14:44:05 -0700244
245 data = (u8 *) priv->maint_win + (offset & (RIO_MAINT_WIN_SIZE - 1));
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800246 switch (len) {
247 case 1:
248 out_8((u8 *) data, val);
249 break;
250 case 2:
251 out_be16((u16 *) data, val);
252 break;
Thomas Mollbd4fb652010-05-26 14:44:05 -0700253 case 4:
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800254 out_be32((u32 *) data, val);
255 break;
Thomas Mollbd4fb652010-05-26 14:44:05 -0700256 default:
257 return -EINVAL;
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800258 }
259
260 return 0;
261}
262
Liu Gang6ec4bed2011-11-12 20:02:28 +0800263void fsl_rio_port_error_handler(struct rio_mport *port, int offset)
Shaohui Xie6ff31452010-11-18 14:57:53 +0800264{
265 /*XXX: Error recovery is not implemented, we just clear errors */
266 out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 0);
267
268 if (offset == 0) {
269 out_be32((u32 *)(rio_regs_win + RIO_PORT1_EDCSR), 0);
Liu Gang-B34182671ee7f2011-08-25 15:59:25 -0700270 out_be32((u32 *)(rio_regs_win + RIO_PORT1_IECSR), IECSR_CLEAR);
Shaohui Xie6ff31452010-11-18 14:57:53 +0800271 out_be32((u32 *)(rio_regs_win + RIO_ESCSR), ESCSR_CLEAR);
272 } else {
273 out_be32((u32 *)(rio_regs_win + RIO_PORT2_EDCSR), 0);
Liu Gang-B34182671ee7f2011-08-25 15:59:25 -0700274 out_be32((u32 *)(rio_regs_win + RIO_PORT2_IECSR), IECSR_CLEAR);
Shaohui Xie6ff31452010-11-18 14:57:53 +0800275 out_be32((u32 *)(rio_regs_win + RIO_PORT2_ESCSR), ESCSR_CLEAR);
276 }
277}
Zhang Wei7f620df2008-04-18 13:33:44 -0700278static inline void fsl_rio_info(struct device *dev, u32 ccsr)
279{
280 const char *str;
281 if (ccsr & 1) {
282 /* Serial phy */
283 switch (ccsr >> 30) {
284 case 0:
285 str = "1";
286 break;
287 case 1:
288 str = "4";
289 break;
290 default:
291 str = "Unknown";
Joe Perchesd258e642009-06-28 06:26:10 +0000292 break;
Zhang Wei7f620df2008-04-18 13:33:44 -0700293 }
294 dev_info(dev, "Hardware port width: %s\n", str);
295
296 switch ((ccsr >> 27) & 7) {
297 case 0:
298 str = "Single-lane 0";
299 break;
300 case 1:
301 str = "Single-lane 2";
302 break;
303 case 2:
304 str = "Four-lane";
305 break;
306 default:
307 str = "Unknown";
308 break;
309 }
310 dev_info(dev, "Training connection status: %s\n", str);
311 } else {
312 /* Parallel phy */
313 if (!(ccsr & 0x80000000))
314 dev_info(dev, "Output port operating in 8-bit mode\n");
315 if (!(ccsr & 0x08000000))
316 dev_info(dev, "Input port operating in 8-bit mode\n");
317 }
318}
319
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800320/**
Randy Dunlap9941d942008-04-30 16:45:58 -0700321 * fsl_rio_setup - Setup Freescale PowerPC RapidIO interface
Grant Likely2dc11582010-08-06 09:25:50 -0600322 * @dev: platform_device pointer
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800323 *
324 * Initializes MPC85xx RapidIO hardware interface, configures
325 * master port with system-specific info, and registers the
326 * master port with the RapidIO subsystem.
327 */
Grant Likelya454dc52010-07-22 15:52:34 -0600328int fsl_rio_setup(struct platform_device *dev)
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800329{
330 struct rio_ops *ops;
331 struct rio_mport *port;
Zhang Weicc2bb692008-04-18 13:33:41 -0700332 struct rio_priv *priv;
333 int rc = 0;
334 const u32 *dt_range, *cell;
335 struct resource regs;
336 int rlen;
Zhang Wei61b26912008-04-18 13:33:44 -0700337 u32 ccsr;
Zhang Weicc2bb692008-04-18 13:33:41 -0700338 u64 law_start, law_size;
339 int paw, aw, sw;
340
Grant Likely61c7a082010-04-13 16:12:29 -0700341 if (!dev->dev.of_node) {
Zhang Weicc2bb692008-04-18 13:33:41 -0700342 dev_err(&dev->dev, "Device OF-Node is NULL");
343 return -EFAULT;
344 }
345
Grant Likely61c7a082010-04-13 16:12:29 -0700346 rc = of_address_to_resource(dev->dev.of_node, 0, &regs);
Zhang Weicc2bb692008-04-18 13:33:41 -0700347 if (rc) {
348 dev_err(&dev->dev, "Can't get %s property 'reg'\n",
Grant Likely61c7a082010-04-13 16:12:29 -0700349 dev->dev.of_node->full_name);
Zhang Weicc2bb692008-04-18 13:33:41 -0700350 return -EFAULT;
351 }
Liu Gang6ec4bed2011-11-12 20:02:28 +0800352 dev_info(&dev->dev, "Of-device full name %s\n",
353 dev->dev.of_node->full_name);
Kumar Galafc274a12009-05-13 17:02:24 -0500354 dev_info(&dev->dev, "Regs: %pR\n", &regs);
Zhang Weicc2bb692008-04-18 13:33:41 -0700355
Grant Likely61c7a082010-04-13 16:12:29 -0700356 dt_range = of_get_property(dev->dev.of_node, "ranges", &rlen);
Zhang Weicc2bb692008-04-18 13:33:41 -0700357 if (!dt_range) {
358 dev_err(&dev->dev, "Can't get %s property 'ranges'\n",
Grant Likely61c7a082010-04-13 16:12:29 -0700359 dev->dev.of_node->full_name);
Zhang Weicc2bb692008-04-18 13:33:41 -0700360 return -EFAULT;
361 }
362
363 /* Get node address wide */
Grant Likely61c7a082010-04-13 16:12:29 -0700364 cell = of_get_property(dev->dev.of_node, "#address-cells", NULL);
Zhang Weicc2bb692008-04-18 13:33:41 -0700365 if (cell)
366 aw = *cell;
367 else
Grant Likely61c7a082010-04-13 16:12:29 -0700368 aw = of_n_addr_cells(dev->dev.of_node);
Zhang Weicc2bb692008-04-18 13:33:41 -0700369 /* Get node size wide */
Grant Likely61c7a082010-04-13 16:12:29 -0700370 cell = of_get_property(dev->dev.of_node, "#size-cells", NULL);
Zhang Weicc2bb692008-04-18 13:33:41 -0700371 if (cell)
372 sw = *cell;
373 else
Grant Likely61c7a082010-04-13 16:12:29 -0700374 sw = of_n_size_cells(dev->dev.of_node);
Zhang Weicc2bb692008-04-18 13:33:41 -0700375 /* Get parent address wide wide */
Grant Likely61c7a082010-04-13 16:12:29 -0700376 paw = of_n_addr_cells(dev->dev.of_node);
Zhang Weicc2bb692008-04-18 13:33:41 -0700377
378 law_start = of_read_number(dt_range + aw, paw);
379 law_size = of_read_number(dt_range + aw + paw, sw);
380
381 dev_info(&dev->dev, "LAW start 0x%016llx, size 0x%016llx.\n",
382 law_start, law_size);
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800383
Alexandre Bouninee5cabeb2010-05-26 14:43:59 -0700384 ops = kzalloc(sizeof(struct rio_ops), GFP_KERNEL);
Julia Lawall6c759332009-08-07 09:00:34 +0200385 if (!ops) {
386 rc = -ENOMEM;
387 goto err_ops;
388 }
Zhang Weid02443a2008-04-18 13:33:38 -0700389 ops->lcread = fsl_local_config_read;
390 ops->lcwrite = fsl_local_config_write;
391 ops->cread = fsl_rio_config_read;
392 ops->cwrite = fsl_rio_config_write;
Alexandre Bounine5b2074a2010-05-26 14:44:00 -0700393 ops->pwenable = fsl_rio_pw_enable;
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800394
Zhang Weiad1e9382008-04-18 13:33:41 -0700395 port = kzalloc(sizeof(struct rio_mport), GFP_KERNEL);
Julia Lawall6c759332009-08-07 09:00:34 +0200396 if (!port) {
397 rc = -ENOMEM;
398 goto err_port;
399 }
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800400 port->index = 0;
Zhang Weiad1e9382008-04-18 13:33:41 -0700401
402 priv = kzalloc(sizeof(struct rio_priv), GFP_KERNEL);
403 if (!priv) {
404 printk(KERN_ERR "Can't alloc memory for 'priv'\n");
405 rc = -ENOMEM;
Julia Lawall6c759332009-08-07 09:00:34 +0200406 goto err_priv;
Zhang Weiad1e9382008-04-18 13:33:41 -0700407 }
408
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800409 INIT_LIST_HEAD(&port->dbells);
410 port->iores.start = law_start;
Li Yang186e74b2009-05-12 16:35:59 +0800411 port->iores.end = law_start + law_size - 1;
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800412 port->iores.flags = IORESOURCE_MEM;
Li Yang186e74b2009-05-12 16:35:59 +0800413 port->iores.name = "rio_io_win";
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800414
Alexandre Bouninec1256eb2011-03-23 16:43:06 -0700415 if (request_resource(&iomem_resource, &port->iores) < 0) {
416 dev_err(&dev->dev, "RIO: Error requesting master port region"
417 " 0x%016llx-0x%016llx\n",
418 (u64)port->iores.start, (u64)port->iores.end);
419 rc = -ENOMEM;
420 goto err_res;
421 }
422
Liu Gang6ec4bed2011-11-12 20:02:28 +0800423 priv->pwirq = irq_of_parse_and_map(dev->dev.of_node, 0);
424 dev_info(&dev->dev, "pwirq: %d\n", priv->pwirq);
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800425 strcpy(port->name, "RIO0 mport");
426
Anton Vorontsov0dbbbf12009-04-18 21:48:52 +0400427 priv->dev = &dev->dev;
428
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800429 port->ops = ops;
Zhang Weiad1e9382008-04-18 13:33:41 -0700430 port->priv = priv;
Alexandre Bounineaf84ca32010-10-27 15:34:34 -0700431 port->phys_efptr = 0x100;
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800432
Joe Perches28f65c112011-06-09 09:13:32 -0700433 priv->regs_win = ioremap(regs.start, resource_size(&regs));
Alexandre Bouninea52c8f52010-05-26 14:44:00 -0700434 rio_regs_win = priv->regs_win;
Zhang Weie0423232008-04-18 13:33:42 -0700435
Zhang Wei61b26912008-04-18 13:33:44 -0700436 /* Probe the master port phy type */
437 ccsr = in_be32(priv->regs_win + RIO_CCSR);
438 port->phy_type = (ccsr & 1) ? RIO_PHY_SERIAL : RIO_PHY_PARALLEL;
439 dev_info(&dev->dev, "RapidIO PHY type: %s\n",
440 (port->phy_type == RIO_PHY_PARALLEL) ? "parallel" :
441 ((port->phy_type == RIO_PHY_SERIAL) ? "serial" :
442 "unknown"));
Zhang Wei7f620df2008-04-18 13:33:44 -0700443 /* Checking the port training status */
444 if (in_be32((priv->regs_win + RIO_ESCSR)) & 1) {
445 dev_err(&dev->dev, "Port is not ready. "
Liu Gang6ec4bed2011-11-12 20:02:28 +0800446 "Try to restart connection...\n");
Zhang Wei7f620df2008-04-18 13:33:44 -0700447 switch (port->phy_type) {
448 case RIO_PHY_SERIAL:
449 /* Disable ports */
450 out_be32(priv->regs_win + RIO_CCSR, 0);
451 /* Set 1x lane */
452 setbits32(priv->regs_win + RIO_CCSR, 0x02000000);
453 /* Enable ports */
454 setbits32(priv->regs_win + RIO_CCSR, 0x00600000);
455 break;
456 case RIO_PHY_PARALLEL:
457 /* Disable ports */
458 out_be32(priv->regs_win + RIO_CCSR, 0x22000000);
459 /* Enable ports */
460 out_be32(priv->regs_win + RIO_CCSR, 0x44000000);
461 break;
462 }
463 msleep(100);
464 if (in_be32((priv->regs_win + RIO_ESCSR)) & 1) {
465 dev_err(&dev->dev, "Port restart failed.\n");
466 rc = -ENOLINK;
467 goto err;
468 }
469 dev_info(&dev->dev, "Port restart success!\n");
470 }
471 fsl_rio_info(&dev->dev, ccsr);
Zhang Wei61b26912008-04-18 13:33:44 -0700472
Zhang Weie0423232008-04-18 13:33:42 -0700473 port->sys_size = (in_be32((priv->regs_win + RIO_PEF_CAR))
474 & RIO_PEF_CTLS) >> 4;
475 dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n",
476 port->sys_size ? 65536 : 256);
477
Alexandre Bounine59f99962011-04-14 15:22:14 -0700478 if (rio_register_mport(port))
479 goto err;
480
Alexandre Bounineaf84ca32010-10-27 15:34:34 -0700481 if (port->host_deviceid >= 0)
482 out_be32(priv->regs_win + RIO_GCCSR, RIO_PORT_GEN_HOST |
483 RIO_PORT_GEN_MASTER | RIO_PORT_GEN_DISCOVERED);
484 else
485 out_be32(priv->regs_win + RIO_GCCSR, 0x00000000);
486
Zhang Weiad1e9382008-04-18 13:33:41 -0700487 priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win
488 + RIO_ATMU_REGS_OFFSET);
489 priv->maint_atmu_regs = priv->atmu_regs + 1;
Zhang Wei61b26912008-04-18 13:33:44 -0700490
491 /* Set to receive any dist ID for serial RapidIO controller. */
492 if (port->phy_type == RIO_PHY_SERIAL)
493 out_be32((priv->regs_win + RIO_ISR_AACR), RIO_ISR_AACR_AA);
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800494
495 /* Configure maintenance transaction window */
Li Yang186e74b2009-05-12 16:35:59 +0800496 out_be32(&priv->maint_atmu_regs->rowbar, law_start >> 12);
Thomas Mollbd4fb652010-05-26 14:44:05 -0700497 out_be32(&priv->maint_atmu_regs->rowar,
498 0x80077000 | (ilog2(RIO_MAINT_WIN_SIZE) - 1));
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800499
Zhang Weiad1e9382008-04-18 13:33:41 -0700500 priv->maint_win = ioremap(law_start, RIO_MAINT_WIN_SIZE);
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800501
Liu Gang6ec4bed2011-11-12 20:02:28 +0800502 fsl_rio_setup_rmu(port, dev->dev.of_node);
503
Alexandre Bounine5b2074a2010-05-26 14:44:00 -0700504 fsl_rio_port_write_init(port);
Zhang Weiad1e9382008-04-18 13:33:41 -0700505
Zhang Weicc2bb692008-04-18 13:33:41 -0700506 return 0;
Zhang Weiad1e9382008-04-18 13:33:41 -0700507err:
Julia Lawall6c759332009-08-07 09:00:34 +0200508 iounmap(priv->regs_win);
Liu Gange80dd9a2011-11-02 13:39:07 -0700509 release_resource(&port->iores);
Alexandre Bouninec1256eb2011-03-23 16:43:06 -0700510err_res:
Zhang Weiad1e9382008-04-18 13:33:41 -0700511 kfree(priv);
Julia Lawall6c759332009-08-07 09:00:34 +0200512err_priv:
Zhang Weiad1e9382008-04-18 13:33:41 -0700513 kfree(port);
Julia Lawall6c759332009-08-07 09:00:34 +0200514err_port:
515 kfree(ops);
516err_ops:
Zhang Weicc2bb692008-04-18 13:33:41 -0700517 return rc;
Matt Porter2b0c28d7f2005-11-07 01:00:19 -0800518}
Zhang Weicc2bb692008-04-18 13:33:41 -0700519
520/* The probe function for RapidIO peer-to-peer network.
521 */
Grant Likely00006122011-02-22 19:59:54 -0700522static int __devinit fsl_of_rio_rpn_probe(struct platform_device *dev)
Zhang Weicc2bb692008-04-18 13:33:41 -0700523{
Zhang Weicc2bb692008-04-18 13:33:41 -0700524 printk(KERN_INFO "Setting up RapidIO peer-to-peer network %s\n",
Grant Likely61c7a082010-04-13 16:12:29 -0700525 dev->dev.of_node->full_name);
Zhang Weicc2bb692008-04-18 13:33:41 -0700526
Alexandre Bounine2f809982011-03-23 16:43:04 -0700527 return fsl_rio_setup(dev);
Zhang Weicc2bb692008-04-18 13:33:41 -0700528};
529
530static const struct of_device_id fsl_of_rio_rpn_ids[] = {
531 {
532 .compatible = "fsl,rapidio-delta",
533 },
534 {},
535};
536
Grant Likely00006122011-02-22 19:59:54 -0700537static struct platform_driver fsl_of_rio_rpn_driver = {
Grant Likely40182942010-04-13 16:13:02 -0700538 .driver = {
539 .name = "fsl-of-rio",
540 .owner = THIS_MODULE,
541 .of_match_table = fsl_of_rio_rpn_ids,
542 },
Zhang Weicc2bb692008-04-18 13:33:41 -0700543 .probe = fsl_of_rio_rpn_probe,
544};
545
546static __init int fsl_of_rio_rpn_init(void)
547{
Grant Likely00006122011-02-22 19:59:54 -0700548 return platform_driver_register(&fsl_of_rio_rpn_driver);
Zhang Weicc2bb692008-04-18 13:33:41 -0700549}
550
551subsys_initcall(fsl_of_rio_rpn_init);