• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/rapidio/switches/
1/*
2 * RapidIO Tsi568 switch support
3 *
4 * Copyright 2009-2010 Integrated Device Technology, Inc.
5 * Alexandre Bounine <alexandre.bounine@idt.com>
6 *  - Added EM support
7 *  - Modified switch operations initialization.
8 *
9 * Copyright 2005 MontaVista Software, Inc.
10 * Matt Porter <mporter@kernel.crashing.org>
11 *
12 * This program is free software; you can redistribute  it and/or modify it
13 * under  the terms of  the GNU General  Public License as published by the
14 * Free Software Foundation;  either version 2 of the  License, or (at your
15 * option) any later version.
16 */
17
18#include <linux/rio.h>
19#include <linux/rio_drv.h>
20#include <linux/rio_ids.h>
21#include <linux/delay.h>
22#include "../rio.h"
23
24/* Global (broadcast) route registers */
25#define SPBC_ROUTE_CFG_DESTID	0x10070
26#define SPBC_ROUTE_CFG_PORT	0x10074
27
28/* Per port route registers */
29#define SPP_ROUTE_CFG_DESTID(n)	(0x11070 + 0x100*n)
30#define SPP_ROUTE_CFG_PORT(n)	(0x11074 + 0x100*n)
31
32#define TSI568_SP_MODE_BC	0x10004
33#define  TSI568_SP_MODE_PW_DIS	0x08000000
34
35static int
36tsi568_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
37		       u16 table, u16 route_destid, u8 route_port)
38{
39	if (table == RIO_GLOBAL_TABLE) {
40		rio_mport_write_config_32(mport, destid, hopcount,
41					SPBC_ROUTE_CFG_DESTID, route_destid);
42		rio_mport_write_config_32(mport, destid, hopcount,
43					SPBC_ROUTE_CFG_PORT, route_port);
44	} else {
45		rio_mport_write_config_32(mport, destid, hopcount,
46					SPP_ROUTE_CFG_DESTID(table),
47					route_destid);
48		rio_mport_write_config_32(mport, destid, hopcount,
49					SPP_ROUTE_CFG_PORT(table), route_port);
50	}
51
52	udelay(10);
53
54	return 0;
55}
56
57static int
58tsi568_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
59		       u16 table, u16 route_destid, u8 *route_port)
60{
61	int ret = 0;
62	u32 result;
63
64	if (table == RIO_GLOBAL_TABLE) {
65		rio_mport_write_config_32(mport, destid, hopcount,
66					SPBC_ROUTE_CFG_DESTID, route_destid);
67		rio_mport_read_config_32(mport, destid, hopcount,
68					SPBC_ROUTE_CFG_PORT, &result);
69	} else {
70		rio_mport_write_config_32(mport, destid, hopcount,
71					SPP_ROUTE_CFG_DESTID(table),
72					route_destid);
73		rio_mport_read_config_32(mport, destid, hopcount,
74					SPP_ROUTE_CFG_PORT(table), &result);
75	}
76
77	*route_port = result;
78	if (*route_port > 15)
79		ret = -1;
80
81	return ret;
82}
83
84static int
85tsi568_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
86		       u16 table)
87{
88	u32 route_idx;
89	u32 lut_size;
90
91	lut_size = (mport->sys_size) ? 0x1ff : 0xff;
92
93	if (table == RIO_GLOBAL_TABLE) {
94		rio_mport_write_config_32(mport, destid, hopcount,
95					SPBC_ROUTE_CFG_DESTID, 0x80000000);
96		for (route_idx = 0; route_idx <= lut_size; route_idx++)
97			rio_mport_write_config_32(mport, destid, hopcount,
98						SPBC_ROUTE_CFG_PORT,
99						RIO_INVALID_ROUTE);
100	} else {
101		rio_mport_write_config_32(mport, destid, hopcount,
102					SPP_ROUTE_CFG_DESTID(table),
103					0x80000000);
104		for (route_idx = 0; route_idx <= lut_size; route_idx++)
105			rio_mport_write_config_32(mport, destid, hopcount,
106						SPP_ROUTE_CFG_PORT(table),
107						RIO_INVALID_ROUTE);
108	}
109
110	return 0;
111}
112
113static int
114tsi568_em_init(struct rio_dev *rdev)
115{
116	struct rio_mport *mport = rdev->net->hport;
117	u16 destid = rdev->rswitch->destid;
118	u8 hopcount = rdev->rswitch->hopcount;
119	u32 regval;
120
121	pr_debug("TSI568 %s [%d:%d]\n", __func__, destid, hopcount);
122
123	/* Make sure that Port-Writes are disabled (for all ports) */
124	rio_mport_read_config_32(mport, destid, hopcount,
125			TSI568_SP_MODE_BC, &regval);
126	rio_mport_write_config_32(mport, destid, hopcount,
127			TSI568_SP_MODE_BC, regval | TSI568_SP_MODE_PW_DIS);
128
129	return 0;
130}
131
132static int tsi568_switch_init(struct rio_dev *rdev, int do_enum)
133{
134	pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
135	rdev->rswitch->add_entry = tsi568_route_add_entry;
136	rdev->rswitch->get_entry = tsi568_route_get_entry;
137	rdev->rswitch->clr_table = tsi568_route_clr_table;
138	rdev->rswitch->set_domain = NULL;
139	rdev->rswitch->get_domain = NULL;
140	rdev->rswitch->em_init = tsi568_em_init;
141	rdev->rswitch->em_handle = NULL;
142
143	return 0;
144}
145
146DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI568, tsi568_switch_init);
147