Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/avr32/boards/favr-32/setup.c
10819 views
1
/*
2
* Favr-32 board-specific setup code.
3
*
4
* Copyright (C) 2008 Atmel Corporation
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2 as
8
* published by the Free Software Foundation.
9
*/
10
#include <linux/clk.h>
11
#include <linux/etherdevice.h>
12
#include <linux/bootmem.h>
13
#include <linux/fb.h>
14
#include <linux/init.h>
15
#include <linux/platform_device.h>
16
#include <linux/types.h>
17
#include <linux/linkage.h>
18
#include <linux/gpio.h>
19
#include <linux/leds.h>
20
#include <linux/atmel-mci.h>
21
#include <linux/atmel-pwm-bl.h>
22
#include <linux/spi/spi.h>
23
#include <linux/spi/ads7846.h>
24
25
#include <sound/atmel-abdac.h>
26
27
#include <video/atmel_lcdc.h>
28
29
#include <asm/setup.h>
30
31
#include <mach/at32ap700x.h>
32
#include <mach/init.h>
33
#include <mach/board.h>
34
#include <mach/portmux.h>
35
36
/* Oscillator frequencies. These are board-specific */
37
unsigned long at32_board_osc_rates[3] = {
38
[0] = 32768, /* 32.768 kHz on RTC osc */
39
[1] = 20000000, /* 20 MHz on osc0 */
40
[2] = 12000000, /* 12 MHz on osc1 */
41
};
42
43
/* Initialized by bootloader-specific startup code. */
44
struct tag *bootloader_tags __initdata;
45
46
static struct atmel_abdac_pdata __initdata abdac0_data = {
47
};
48
49
struct eth_addr {
50
u8 addr[6];
51
};
52
static struct eth_addr __initdata hw_addr[1];
53
static struct eth_platform_data __initdata eth_data[1] = {
54
{
55
.phy_mask = ~(1U << 1),
56
},
57
};
58
59
static int ads7843_get_pendown_state(void)
60
{
61
return !gpio_get_value(GPIO_PIN_PB(3));
62
}
63
64
static struct ads7846_platform_data ads7843_data = {
65
.model = 7843,
66
.get_pendown_state = ads7843_get_pendown_state,
67
.pressure_max = 255,
68
/*
69
* Values below are for debounce filtering, these can be experimented
70
* with further.
71
*/
72
.debounce_max = 20,
73
.debounce_rep = 4,
74
.debounce_tol = 5,
75
76
.keep_vref_on = true,
77
.settle_delay_usecs = 500,
78
.penirq_recheck_delay_usecs = 100,
79
};
80
81
static struct spi_board_info __initdata spi1_board_info[] = {
82
{
83
/* ADS7843 touch controller */
84
.modalias = "ads7846",
85
.max_speed_hz = 2000000,
86
.chip_select = 0,
87
.bus_num = 1,
88
.platform_data = &ads7843_data,
89
},
90
};
91
92
static struct mci_platform_data __initdata mci0_data = {
93
.slot[0] = {
94
.bus_width = 4,
95
.detect_pin = -ENODEV,
96
.wp_pin = -ENODEV,
97
},
98
};
99
100
static struct fb_videomode __initdata lb104v03_modes[] = {
101
{
102
.name = "640x480 @ 50",
103
.refresh = 50,
104
.xres = 640, .yres = 480,
105
.pixclock = KHZ2PICOS(25100),
106
107
.left_margin = 90, .right_margin = 70,
108
.upper_margin = 30, .lower_margin = 15,
109
.hsync_len = 12, .vsync_len = 2,
110
111
.sync = 0,
112
.vmode = FB_VMODE_NONINTERLACED,
113
},
114
};
115
116
static struct fb_monspecs __initdata favr32_default_monspecs = {
117
.manufacturer = "LG",
118
.monitor = "LB104V03",
119
.modedb = lb104v03_modes,
120
.modedb_len = ARRAY_SIZE(lb104v03_modes),
121
.hfmin = 27273,
122
.hfmax = 31111,
123
.vfmin = 45,
124
.vfmax = 60,
125
.dclkmax = 28000000,
126
};
127
128
struct atmel_lcdfb_info __initdata favr32_lcdc_data = {
129
.default_bpp = 16,
130
.default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
131
.default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
132
| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE
133
| ATMEL_LCDC_MEMOR_BIG),
134
.default_monspecs = &favr32_default_monspecs,
135
.guard_time = 2,
136
};
137
138
static struct gpio_led favr32_leds[] = {
139
{
140
.name = "green",
141
.gpio = GPIO_PIN_PE(19),
142
.default_trigger = "heartbeat",
143
.active_low = 1,
144
},
145
{
146
.name = "red",
147
.gpio = GPIO_PIN_PE(20),
148
.active_low = 1,
149
},
150
};
151
152
static struct gpio_led_platform_data favr32_led_data = {
153
.num_leds = ARRAY_SIZE(favr32_leds),
154
.leds = favr32_leds,
155
};
156
157
static struct platform_device favr32_led_dev = {
158
.name = "leds-gpio",
159
.id = 0,
160
.dev = {
161
.platform_data = &favr32_led_data,
162
},
163
};
164
165
/*
166
* The next two functions should go away as the boot loader is
167
* supposed to initialize the macb address registers with a valid
168
* ethernet address. But we need to keep it around for a while until
169
* we can be reasonably sure the boot loader does this.
170
*
171
* The phy_id is ignored as the driver will probe for it.
172
*/
173
static int __init parse_tag_ethernet(struct tag *tag)
174
{
175
int i;
176
177
i = tag->u.ethernet.mac_index;
178
if (i < ARRAY_SIZE(hw_addr))
179
memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address,
180
sizeof(hw_addr[i].addr));
181
182
return 0;
183
}
184
__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
185
186
static void __init set_hw_addr(struct platform_device *pdev)
187
{
188
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
189
const u8 *addr;
190
void __iomem *regs;
191
struct clk *pclk;
192
193
if (!res)
194
return;
195
if (pdev->id >= ARRAY_SIZE(hw_addr))
196
return;
197
198
addr = hw_addr[pdev->id].addr;
199
if (!is_valid_ether_addr(addr))
200
return;
201
202
/*
203
* Since this is board-specific code, we'll cheat and use the
204
* physical address directly as we happen to know that it's
205
* the same as the virtual address.
206
*/
207
regs = (void __iomem __force *)res->start;
208
pclk = clk_get(&pdev->dev, "pclk");
209
if (IS_ERR(pclk))
210
return;
211
212
clk_enable(pclk);
213
__raw_writel((addr[3] << 24) | (addr[2] << 16)
214
| (addr[1] << 8) | addr[0], regs + 0x98);
215
__raw_writel((addr[5] << 8) | addr[4], regs + 0x9c);
216
clk_disable(pclk);
217
clk_put(pclk);
218
}
219
220
void __init favr32_setup_leds(void)
221
{
222
unsigned i;
223
224
for (i = 0; i < ARRAY_SIZE(favr32_leds); i++)
225
at32_select_gpio(favr32_leds[i].gpio, AT32_GPIOF_OUTPUT);
226
227
platform_device_register(&favr32_led_dev);
228
}
229
230
static struct atmel_pwm_bl_platform_data atmel_pwm_bl_pdata = {
231
.pwm_channel = 2,
232
.pwm_frequency = 200000,
233
.pwm_compare_max = 345,
234
.pwm_duty_max = 345,
235
.pwm_duty_min = 90,
236
.pwm_active_low = 1,
237
.gpio_on = GPIO_PIN_PA(28),
238
.on_active_low = 0,
239
};
240
241
static struct platform_device atmel_pwm_bl_dev = {
242
.name = "atmel-pwm-bl",
243
.id = 0,
244
.dev = {
245
.platform_data = &atmel_pwm_bl_pdata,
246
},
247
};
248
249
static void __init favr32_setup_atmel_pwm_bl(void)
250
{
251
platform_device_register(&atmel_pwm_bl_dev);
252
at32_select_gpio(atmel_pwm_bl_pdata.gpio_on, 0);
253
}
254
255
void __init setup_board(void)
256
{
257
at32_map_usart(3, 0, 0); /* USART 3 => /dev/ttyS0 */
258
at32_setup_serial_console(0);
259
}
260
261
static int __init set_abdac_rate(struct platform_device *pdev)
262
{
263
int retval;
264
struct clk *osc1;
265
struct clk *pll1;
266
struct clk *abdac;
267
268
if (pdev == NULL)
269
return -ENXIO;
270
271
osc1 = clk_get(NULL, "osc1");
272
if (IS_ERR(osc1)) {
273
retval = PTR_ERR(osc1);
274
goto out;
275
}
276
277
pll1 = clk_get(NULL, "pll1");
278
if (IS_ERR(pll1)) {
279
retval = PTR_ERR(pll1);
280
goto out_osc1;
281
}
282
283
abdac = clk_get(&pdev->dev, "sample_clk");
284
if (IS_ERR(abdac)) {
285
retval = PTR_ERR(abdac);
286
goto out_pll1;
287
}
288
289
retval = clk_set_parent(pll1, osc1);
290
if (retval != 0)
291
goto out_abdac;
292
293
/*
294
* Rate is 32000 to 50000 and ABDAC oversamples 256x. Multiply, in
295
* power of 2, to a value above 80 MHz. Power of 2 so it is possible
296
* for the generic clock to divide it down again and 80 MHz is the
297
* lowest frequency for the PLL.
298
*/
299
retval = clk_round_rate(pll1,
300
CONFIG_BOARD_FAVR32_ABDAC_RATE * 256 * 16);
301
if (retval < 0)
302
goto out_abdac;
303
304
retval = clk_set_rate(pll1, retval);
305
if (retval != 0)
306
goto out_abdac;
307
308
retval = clk_set_parent(abdac, pll1);
309
if (retval != 0)
310
goto out_abdac;
311
312
out_abdac:
313
clk_put(abdac);
314
out_pll1:
315
clk_put(pll1);
316
out_osc1:
317
clk_put(osc1);
318
out:
319
return retval;
320
}
321
322
static int __init favr32_init(void)
323
{
324
/*
325
* Favr-32 uses 32-bit SDRAM interface. Reserve the SDRAM-specific
326
* pins so that nobody messes with them.
327
*/
328
at32_reserve_pin(GPIO_PIOE_BASE, ATMEL_EBI_PE_DATA_ALL);
329
330
at32_select_gpio(GPIO_PIN_PB(3), 0); /* IRQ from ADS7843 */
331
332
at32_add_device_usart(0);
333
334
set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
335
336
spi1_board_info[0].irq = gpio_to_irq(GPIO_PIN_PB(3));
337
338
set_abdac_rate(at32_add_device_abdac(0, &abdac0_data));
339
340
at32_add_device_pwm(1 << atmel_pwm_bl_pdata.pwm_channel);
341
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
342
at32_add_device_mci(0, &mci0_data);
343
at32_add_device_usba(0, NULL);
344
at32_add_device_lcdc(0, &favr32_lcdc_data, fbmem_start, fbmem_size, 0);
345
346
favr32_setup_leds();
347
348
favr32_setup_atmel_pwm_bl();
349
350
return 0;
351
}
352
postcore_initcall(favr32_init);
353
354