aboutsummaryrefslogtreecommitdiffstats
path: root/package/boot/uboot-lantiq/patches/0010-net-switchlib-add-driver-for-Lantiq-PSB697X-switch-f.patch
blob: 8f486e86e48877d17e18b322529e1ddc3506ec08 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
From e2c59cedebf72e4a002134a2932f722b508a5448 Mon Sep 17 00:00:00 2001
From: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Date: Wed, 29 Aug 2012 22:08:15 +0200
Subject: net: switchlib: add driver for Lantiq PSB697X switch family

Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

--- a/drivers/net/switch/Makefile
+++ b/drivers/net/switch/Makefile
@@ -10,6 +10,7 @@ include $(TOPDIR)/config.mk
 LIB	:= $(obj)libswitch.o
 
 COBJS-$(CONFIG_SWITCH_MULTI) += switch.o
+COBJS-$(CONFIG_SWITCH_PSB697X) += psb697x.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
--- /dev/null
+++ b/drivers/net/switch/psb697x.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <switch.h>
+#include <miiphy.h>
+
+#define PSB697X_CHIPID1		0x2599
+#define PSB697X_PORT_COUNT	7
+
+#define PSB697X_PORT_BASE(p)	(p * 0x20)
+#define PSB697X_REG_PS(p)	(PSB697X_PORT_BASE(p) + 0x00)
+#define PSB697X_REG_PBC(p)	(PSB697X_PORT_BASE(p) + 0x01)
+#define PSB697X_REG_PEC(p)	(PSB697X_PORT_BASE(p) + 0x02)
+
+#define PSB697X_REG_SGC1	0x0E0	/* Switch Global Control Register 1 */
+#define PSB697X_REG_SGC2	0x0E1	/* Switch Global Control Register 2 */
+#define PSB697X_REG_CMH		0x0E2	/* CPU Port & Mirror Control */
+#define PSB697X_REG_MIICR	0x0F5	/* MII Port Control */
+#define PSB697X_REG_CI0		0x100	/* Chip Identifier 0 */
+#define PSB697X_REG_CI1		0x101	/* Chip Identifier 1 */
+#define PSB697X_REG_MIIAC	0x120	/* MII Indirect Access Control */
+#define PSB697X_REG_MIIWD	0x121	/* MII Indirect Write Data */
+#define PSB697X_REG_MIIRD	0x122	/* MII Indirect Read Data */
+
+#define PSB697X_REG_PORT_FLP	(1 << 2)	/* Force link up */
+#define PSB697X_REG_PORT_FLD	(1 << 1)	/* Force link down */
+
+#define PSB697X_REG_SGC2_SE	(1 << 15)	/* Switch enable */
+
+#define PSB697X_REG_CMH_CPN_MASK	0x7
+#define PSB697X_REG_CMH_CPN_SHIFT	5
+
+
+static inline int psb697x_mii_read(struct mii_dev *bus, u16 reg)
+{
+	int ret;
+
+	ret = bus->read(bus, (reg >> 5) & 0x1f, MDIO_DEVAD_NONE, reg & 0x1f);
+
+	return ret;
+}
+
+static inline int psb697x_mii_write(struct mii_dev *bus, u16 reg, u16 val)
+{
+	int ret;
+
+	ret = bus->write(bus, (reg >> 5) & 0x1f, MDIO_DEVAD_NONE,
+		reg & 0x1f, val);
+
+	return ret;
+}
+
+static int psb697x_probe(struct switch_device *dev)
+{
+	struct mii_dev *bus = dev->bus;
+	int ci1;
+
+	ci1 = psb697x_mii_read(bus, PSB697X_REG_CI1);
+
+	if (ci1 == PSB697X_CHIPID1)
+		return 0;
+
+	return 1;
+}
+
+static void psb697x_setup(struct switch_device *dev)
+{
+	struct mii_dev *bus = dev->bus;
+	int i, state;
+
+	/* Enable switch */
+	psb697x_mii_write(bus, PSB697X_REG_SGC2, PSB697X_REG_SGC2_SE);
+
+	/*
+	 * Force 100 Mbps as default value for CPU ports 5 and 6 to get
+	 * full speed.
+	 */
+	psb697x_mii_write(bus, PSB697X_REG_MIICR, 0x0773);
+
+	for (i = 0; i < PSB697X_PORT_COUNT; i++) {
+		state = dev->port_mask & (1 << i);
+
+		/*
+		 * Software workaround from Errata Sheet:
+		 * Force link down and reset internal PHY, keep that state
+		 * for all unconnected ports and disable force link down
+		 * for all connected ports
+		 */
+		psb697x_mii_write(bus, PSB697X_REG_PBC(i),
+			PSB697X_REG_PORT_FLD);
+
+		if (i == dev->cpu_port)
+			/* Force link up for CPU port */
+			psb697x_mii_write(bus, PSB697X_REG_PBC(i),
+				PSB697X_REG_PORT_FLP);
+		else if (state)
+			/* Disable force link down for active LAN ports */
+			psb697x_mii_write(bus, PSB697X_REG_PBC(i), 0);
+	}
+}
+
+static struct switch_driver psb697x_drv = {
+	.name = "psb697x",
+};
+
+void switch_psb697x_init(void)
+{
+	/* For archs with manual relocation */
+	psb697x_drv.probe = psb697x_probe;
+	psb697x_drv.setup = psb697x_setup;
+
+	switch_driver_register(&psb697x_drv);
+}
--- a/drivers/net/switch/switch.c
+++ b/drivers/net/switch/switch.c
@@ -17,6 +17,10 @@ void switch_init(void)
 	INIT_LIST_HEAD(&switch_drivers);
 	INIT_LIST_HEAD(&switch_devices);
 
+#if defined(CONFIG_SWITCH_PSB697X)
+	switch_psb697x_init();
+#endif
+
 	board_switch_init();
 }
 
--- a/include/switch.h
+++ b/include/switch.h
@@ -97,6 +97,7 @@ static inline void switch_setup(struct s
 }
 
 /* Init functions for supported Switch drivers */
+extern void switch_psb697x_init(void);
 
 #endif /* __SWITCH_H */