Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/sh/boards/mach-sdk7786/setup.c
26583 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Renesas Technology Europe SDK7786 Support.
4
*
5
* Copyright (C) 2010 Matt Fleming
6
* Copyright (C) 2010 Paul Mundt
7
*/
8
#include <linux/init.h>
9
#include <linux/platform_device.h>
10
#include <linux/io.h>
11
#include <linux/regulator/fixed.h>
12
#include <linux/regulator/machine.h>
13
#include <linux/smsc911x.h>
14
#include <linux/i2c.h>
15
#include <linux/irq.h>
16
#include <linux/clk.h>
17
#include <linux/clkdev.h>
18
#include <mach/fpga.h>
19
#include <mach/irq.h>
20
#include <asm/machvec.h>
21
#include <asm/heartbeat.h>
22
#include <linux/sizes.h>
23
#include <asm/clock.h>
24
#include <asm/reboot.h>
25
#include <asm/smp-ops.h>
26
27
static struct resource heartbeat_resource = {
28
.start = 0x07fff8b0,
29
.end = 0x07fff8b0 + sizeof(u16) - 1,
30
.flags = IORESOURCE_MEM | IORESOURCE_MEM_16BIT,
31
};
32
33
static struct platform_device heartbeat_device = {
34
.name = "heartbeat",
35
.id = -1,
36
.num_resources = 1,
37
.resource = &heartbeat_resource,
38
};
39
40
/* Dummy supplies, where voltage doesn't matter */
41
static struct regulator_consumer_supply dummy_supplies[] = {
42
REGULATOR_SUPPLY("vddvario", "smsc911x"),
43
REGULATOR_SUPPLY("vdd33a", "smsc911x"),
44
};
45
46
static struct resource smsc911x_resources[] = {
47
[0] = {
48
.name = "smsc911x-memory",
49
.start = 0x07ffff00,
50
.end = 0x07ffff00 + SZ_256 - 1,
51
.flags = IORESOURCE_MEM,
52
},
53
[1] = {
54
.name = "smsc911x-irq",
55
.start = evt2irq(0x2c0),
56
.end = evt2irq(0x2c0),
57
.flags = IORESOURCE_IRQ,
58
},
59
};
60
61
static struct smsc911x_platform_config smsc911x_config = {
62
.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
63
.irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
64
.flags = SMSC911X_USE_32BIT,
65
.phy_interface = PHY_INTERFACE_MODE_MII,
66
};
67
68
static struct platform_device smsc911x_device = {
69
.name = "smsc911x",
70
.id = -1,
71
.num_resources = ARRAY_SIZE(smsc911x_resources),
72
.resource = smsc911x_resources,
73
.dev = {
74
.platform_data = &smsc911x_config,
75
},
76
};
77
78
static struct resource smbus_fpga_resource = {
79
.start = 0x07fff9e0,
80
.end = 0x07fff9e0 + SZ_32 - 1,
81
.flags = IORESOURCE_MEM,
82
};
83
84
static struct platform_device smbus_fpga_device = {
85
.name = "i2c-sdk7786",
86
.id = 0,
87
.num_resources = 1,
88
.resource = &smbus_fpga_resource,
89
};
90
91
static struct resource smbus_pcie_resource = {
92
.start = 0x07fffc30,
93
.end = 0x07fffc30 + SZ_32 - 1,
94
.flags = IORESOURCE_MEM,
95
};
96
97
static struct platform_device smbus_pcie_device = {
98
.name = "i2c-sdk7786",
99
.id = 1,
100
.num_resources = 1,
101
.resource = &smbus_pcie_resource,
102
};
103
104
static struct i2c_board_info __initdata sdk7786_i2c_devices[] = {
105
{
106
I2C_BOARD_INFO("max6900", 0x68),
107
},
108
};
109
110
static struct platform_device *sh7786_devices[] __initdata = {
111
&heartbeat_device,
112
&smsc911x_device,
113
&smbus_fpga_device,
114
&smbus_pcie_device,
115
};
116
117
static int sdk7786_i2c_setup(void)
118
{
119
unsigned int tmp;
120
121
/*
122
* Hand over I2C control to the FPGA.
123
*/
124
tmp = fpga_read_reg(SBCR);
125
tmp &= ~SCBR_I2CCEN;
126
tmp |= SCBR_I2CMEN;
127
fpga_write_reg(tmp, SBCR);
128
129
return i2c_register_board_info(0, sdk7786_i2c_devices,
130
ARRAY_SIZE(sdk7786_i2c_devices));
131
}
132
133
static int __init sdk7786_devices_setup(void)
134
{
135
int ret;
136
137
ret = platform_add_devices(sh7786_devices, ARRAY_SIZE(sh7786_devices));
138
if (unlikely(ret != 0))
139
return ret;
140
141
return sdk7786_i2c_setup();
142
}
143
device_initcall(sdk7786_devices_setup);
144
145
static int sdk7786_mode_pins(void)
146
{
147
return fpga_read_reg(MODSWR);
148
}
149
150
/*
151
* FPGA-driven PCIe clocks
152
*
153
* Historically these include the oscillator, clock B (slots 2/3/4) and
154
* clock A (slot 1 and the CPU clock). Newer revs of the PCB shove
155
* everything under a single PCIe clocks enable bit that happens to map
156
* to the same bit position as the oscillator bit for earlier FPGA
157
* versions.
158
*
159
* Given that the legacy clocks have the side-effect of shutting the CPU
160
* off through the FPGA along with the PCI slots, we simply leave them in
161
* their initial state and don't bother registering them with the clock
162
* framework.
163
*/
164
static int sdk7786_pcie_clk_enable(struct clk *clk)
165
{
166
fpga_write_reg(fpga_read_reg(PCIECR) | PCIECR_CLKEN, PCIECR);
167
return 0;
168
}
169
170
static void sdk7786_pcie_clk_disable(struct clk *clk)
171
{
172
fpga_write_reg(fpga_read_reg(PCIECR) & ~PCIECR_CLKEN, PCIECR);
173
}
174
175
static struct sh_clk_ops sdk7786_pcie_clk_ops = {
176
.enable = sdk7786_pcie_clk_enable,
177
.disable = sdk7786_pcie_clk_disable,
178
};
179
180
static struct clk sdk7786_pcie_clk = {
181
.ops = &sdk7786_pcie_clk_ops,
182
};
183
184
static struct clk_lookup sdk7786_pcie_cl = {
185
.con_id = "pcie_plat_clk",
186
.clk = &sdk7786_pcie_clk,
187
};
188
189
static int sdk7786_clk_init(void)
190
{
191
struct clk *clk;
192
int ret;
193
194
/*
195
* Only handle the EXTAL case, anyone interfacing a crystal
196
* resonator will need to provide their own input clock.
197
*/
198
if (test_mode_pin(MODE_PIN9))
199
return -EINVAL;
200
201
clk = clk_get(NULL, "extal");
202
if (IS_ERR(clk))
203
return PTR_ERR(clk);
204
ret = clk_set_rate(clk, 33333333);
205
clk_put(clk);
206
207
/*
208
* Setup the FPGA clocks.
209
*/
210
ret = clk_register(&sdk7786_pcie_clk);
211
if (unlikely(ret)) {
212
pr_err("FPGA clock registration failed\n");
213
return ret;
214
}
215
216
clkdev_add(&sdk7786_pcie_cl);
217
218
return 0;
219
}
220
221
static void sdk7786_restart(char *cmd)
222
{
223
fpga_write_reg(0xa5a5, SRSTR);
224
}
225
226
static void sdk7786_power_off(void)
227
{
228
fpga_write_reg(fpga_read_reg(PWRCR) | PWRCR_PDWNREQ, PWRCR);
229
230
/*
231
* It can take up to 20us for the R8C to do its job, back off and
232
* wait a bit until we've been shut off. Even though newer FPGA
233
* versions don't set the ACK bit, the latency issue remains.
234
*/
235
while ((fpga_read_reg(PWRCR) & PWRCR_PDWNACK) == 0)
236
cpu_sleep();
237
}
238
239
/* Initialize the board */
240
static void __init sdk7786_setup(char **cmdline_p)
241
{
242
pr_info("Renesas Technology Europe SDK7786 support:\n");
243
244
regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
245
246
sdk7786_fpga_init();
247
sdk7786_nmi_init();
248
249
pr_info("\tPCB revision:\t%d\n", fpga_read_reg(PCBRR) & 0xf);
250
251
machine_ops.restart = sdk7786_restart;
252
pm_power_off = sdk7786_power_off;
253
254
register_smp_ops(&shx3_smp_ops);
255
}
256
257
/*
258
* The Machine Vector
259
*/
260
static struct sh_machine_vector mv_sdk7786 __initmv = {
261
.mv_name = "SDK7786",
262
.mv_setup = sdk7786_setup,
263
.mv_mode_pins = sdk7786_mode_pins,
264
.mv_clk_init = sdk7786_clk_init,
265
.mv_init_irq = sdk7786_init_irq,
266
};
267
268