OpenWrt – Blame information for rev 4
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From e2c59cedebf72e4a002134a2932f722b508a5448 Mon Sep 17 00:00:00 2001 |
2 | From: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> |
||
3 | Date: Wed, 29 Aug 2012 22:08:15 +0200 |
||
4 | Subject: net: switchlib: add driver for Lantiq PSB697X switch family |
||
5 | |||
6 | Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> |
||
7 | |||
8 | --- a/drivers/net/switch/Makefile |
||
9 | +++ b/drivers/net/switch/Makefile |
||
10 | @@ -10,6 +10,7 @@ include $(TOPDIR)/config.mk |
||
11 | LIB := $(obj)libswitch.o |
||
12 | |||
13 | COBJS-$(CONFIG_SWITCH_MULTI) += switch.o |
||
14 | +COBJS-$(CONFIG_SWITCH_PSB697X) += psb697x.o |
||
15 | |||
16 | COBJS := $(COBJS-y) |
||
17 | SRCS := $(COBJS:.o=.c) |
||
18 | --- /dev/null |
||
19 | +++ b/drivers/net/switch/psb697x.c |
||
20 | @@ -0,0 +1,118 @@ |
||
21 | +/* |
||
22 | + * Copyright (C) 2011-2013 Daniel Schwierzeck, daniel.schwierzeck@gmail.com |
||
23 | + * |
||
24 | + * SPDX-License-Identifier: GPL-2.0+ |
||
25 | + */ |
||
26 | + |
||
27 | +#include <common.h> |
||
28 | +#include <malloc.h> |
||
29 | +#include <switch.h> |
||
30 | +#include <miiphy.h> |
||
31 | + |
||
32 | +#define PSB697X_CHIPID1 0x2599 |
||
33 | +#define PSB697X_PORT_COUNT 7 |
||
34 | + |
||
35 | +#define PSB697X_PORT_BASE(p) (p * 0x20) |
||
36 | +#define PSB697X_REG_PS(p) (PSB697X_PORT_BASE(p) + 0x00) |
||
37 | +#define PSB697X_REG_PBC(p) (PSB697X_PORT_BASE(p) + 0x01) |
||
38 | +#define PSB697X_REG_PEC(p) (PSB697X_PORT_BASE(p) + 0x02) |
||
39 | + |
||
40 | +#define PSB697X_REG_SGC1 0x0E0 /* Switch Global Control Register 1 */ |
||
41 | +#define PSB697X_REG_SGC2 0x0E1 /* Switch Global Control Register 2 */ |
||
42 | +#define PSB697X_REG_CMH 0x0E2 /* CPU Port & Mirror Control */ |
||
43 | +#define PSB697X_REG_MIICR 0x0F5 /* MII Port Control */ |
||
44 | +#define PSB697X_REG_CI0 0x100 /* Chip Identifier 0 */ |
||
45 | +#define PSB697X_REG_CI1 0x101 /* Chip Identifier 1 */ |
||
46 | +#define PSB697X_REG_MIIAC 0x120 /* MII Indirect Access Control */ |
||
47 | +#define PSB697X_REG_MIIWD 0x121 /* MII Indirect Write Data */ |
||
48 | +#define PSB697X_REG_MIIRD 0x122 /* MII Indirect Read Data */ |
||
49 | + |
||
50 | +#define PSB697X_REG_PORT_FLP (1 << 2) /* Force link up */ |
||
51 | +#define PSB697X_REG_PORT_FLD (1 << 1) /* Force link down */ |
||
52 | + |
||
53 | +#define PSB697X_REG_SGC2_SE (1 << 15) /* Switch enable */ |
||
54 | + |
||
55 | +#define PSB697X_REG_CMH_CPN_MASK 0x7 |
||
56 | +#define PSB697X_REG_CMH_CPN_SHIFT 5 |
||
57 | + |
||
58 | + |
||
59 | +static inline int psb697x_mii_read(struct mii_dev *bus, u16 reg) |
||
60 | +{ |
||
61 | + int ret; |
||
62 | + |
||
63 | + ret = bus->read(bus, (reg >> 5) & 0x1f, MDIO_DEVAD_NONE, reg & 0x1f); |
||
64 | + |
||
65 | + return ret; |
||
66 | +} |
||
67 | + |
||
68 | +static inline int psb697x_mii_write(struct mii_dev *bus, u16 reg, u16 val) |
||
69 | +{ |
||
70 | + int ret; |
||
71 | + |
||
72 | + ret = bus->write(bus, (reg >> 5) & 0x1f, MDIO_DEVAD_NONE, |
||
73 | + reg & 0x1f, val); |
||
74 | + |
||
75 | + return ret; |
||
76 | +} |
||
77 | + |
||
78 | +static int psb697x_probe(struct switch_device *dev) |
||
79 | +{ |
||
80 | + struct mii_dev *bus = dev->bus; |
||
81 | + int ci1; |
||
82 | + |
||
83 | + ci1 = psb697x_mii_read(bus, PSB697X_REG_CI1); |
||
84 | + |
||
85 | + if (ci1 == PSB697X_CHIPID1) |
||
86 | + return 0; |
||
87 | + |
||
88 | + return 1; |
||
89 | +} |
||
90 | + |
||
91 | +static void psb697x_setup(struct switch_device *dev) |
||
92 | +{ |
||
93 | + struct mii_dev *bus = dev->bus; |
||
94 | + int i, state; |
||
95 | + |
||
96 | + /* Enable switch */ |
||
97 | + psb697x_mii_write(bus, PSB697X_REG_SGC2, PSB697X_REG_SGC2_SE); |
||
98 | + |
||
99 | + /* |
||
100 | + * Force 100 Mbps as default value for CPU ports 5 and 6 to get |
||
101 | + * full speed. |
||
102 | + */ |
||
103 | + psb697x_mii_write(bus, PSB697X_REG_MIICR, 0x0773); |
||
104 | + |
||
105 | + for (i = 0; i < PSB697X_PORT_COUNT; i++) { |
||
106 | + state = dev->port_mask & (1 << i); |
||
107 | + |
||
108 | + /* |
||
109 | + * Software workaround from Errata Sheet: |
||
110 | + * Force link down and reset internal PHY, keep that state |
||
111 | + * for all unconnected ports and disable force link down |
||
112 | + * for all connected ports |
||
113 | + */ |
||
114 | + psb697x_mii_write(bus, PSB697X_REG_PBC(i), |
||
115 | + PSB697X_REG_PORT_FLD); |
||
116 | + |
||
117 | + if (i == dev->cpu_port) |
||
118 | + /* Force link up for CPU port */ |
||
119 | + psb697x_mii_write(bus, PSB697X_REG_PBC(i), |
||
120 | + PSB697X_REG_PORT_FLP); |
||
121 | + else if (state) |
||
122 | + /* Disable force link down for active LAN ports */ |
||
123 | + psb697x_mii_write(bus, PSB697X_REG_PBC(i), 0); |
||
124 | + } |
||
125 | +} |
||
126 | + |
||
127 | +static struct switch_driver psb697x_drv = { |
||
128 | + .name = "psb697x", |
||
129 | +}; |
||
130 | + |
||
131 | +void switch_psb697x_init(void) |
||
132 | +{ |
||
133 | + /* For archs with manual relocation */ |
||
134 | + psb697x_drv.probe = psb697x_probe; |
||
135 | + psb697x_drv.setup = psb697x_setup; |
||
136 | + |
||
137 | + switch_driver_register(&psb697x_drv); |
||
138 | +} |
||
139 | --- a/drivers/net/switch/switch.c |
||
140 | +++ b/drivers/net/switch/switch.c |
||
141 | @@ -17,6 +17,10 @@ void switch_init(void) |
||
142 | INIT_LIST_HEAD(&switch_drivers); |
||
143 | INIT_LIST_HEAD(&switch_devices); |
||
144 | |||
145 | +#if defined(CONFIG_SWITCH_PSB697X) |
||
146 | + switch_psb697x_init(); |
||
147 | +#endif |
||
148 | + |
||
149 | board_switch_init(); |
||
150 | } |
||
151 | |||
152 | --- a/include/switch.h |
||
153 | +++ b/include/switch.h |
||
154 | @@ -97,6 +97,7 @@ static inline void switch_setup(struct s |
||
155 | } |
||
156 | |||
157 | /* Init functions for supported Switch drivers */ |
||
158 | +extern void switch_psb697x_init(void); |
||
159 | |||
160 | #endif /* __SWITCH_H */ |
||
161 |