Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-lpc32xx/phy3250.c
10817 views
1
/*
2
* arch/arm/mach-lpc32xx/phy3250.c
3
*
4
* Author: Kevin Wells <[email protected]>
5
*
6
* Copyright (C) 2010 NXP Semiconductors
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
12
*
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
17
*/
18
19
#include <linux/init.h>
20
#include <linux/platform_device.h>
21
#include <linux/sysdev.h>
22
#include <linux/interrupt.h>
23
#include <linux/irq.h>
24
#include <linux/dma-mapping.h>
25
#include <linux/device.h>
26
#include <linux/spi/spi.h>
27
#include <linux/spi/eeprom.h>
28
#include <linux/leds.h>
29
#include <linux/gpio.h>
30
#include <linux/amba/bus.h>
31
#include <linux/amba/clcd.h>
32
#include <linux/amba/pl022.h>
33
34
#include <asm/setup.h>
35
#include <asm/mach-types.h>
36
#include <asm/mach/arch.h>
37
38
#include <mach/hardware.h>
39
#include <mach/platform.h>
40
#include "common.h"
41
42
/*
43
* Mapped GPIOLIB GPIOs
44
*/
45
#define SPI0_CS_GPIO LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
46
#define LCD_POWER_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 0)
47
#define BKL_POWER_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 4)
48
#define LED_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 1)
49
50
/*
51
* AMBA LCD controller
52
*/
53
static struct clcd_panel conn_lcd_panel = {
54
.mode = {
55
.name = "QVGA portrait",
56
.refresh = 60,
57
.xres = 240,
58
.yres = 320,
59
.pixclock = 191828,
60
.left_margin = 22,
61
.right_margin = 11,
62
.upper_margin = 2,
63
.lower_margin = 1,
64
.hsync_len = 5,
65
.vsync_len = 2,
66
.sync = 0,
67
.vmode = FB_VMODE_NONINTERLACED,
68
},
69
.width = -1,
70
.height = -1,
71
.tim2 = (TIM2_IVS | TIM2_IHS),
72
.cntl = (CNTL_BGR | CNTL_LCDTFT | CNTL_LCDVCOMP(1) |
73
CNTL_LCDBPP16_565),
74
.bpp = 16,
75
};
76
#define PANEL_SIZE (3 * SZ_64K)
77
78
static int lpc32xx_clcd_setup(struct clcd_fb *fb)
79
{
80
dma_addr_t dma;
81
82
fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev,
83
PANEL_SIZE, &dma, GFP_KERNEL);
84
if (!fb->fb.screen_base) {
85
printk(KERN_ERR "CLCD: unable to map framebuffer\n");
86
return -ENOMEM;
87
}
88
89
fb->fb.fix.smem_start = dma;
90
fb->fb.fix.smem_len = PANEL_SIZE;
91
fb->panel = &conn_lcd_panel;
92
93
if (gpio_request(LCD_POWER_GPIO, "LCD power"))
94
printk(KERN_ERR "Error requesting gpio %u",
95
LCD_POWER_GPIO);
96
else if (gpio_direction_output(LCD_POWER_GPIO, 1))
97
printk(KERN_ERR "Error setting gpio %u to output",
98
LCD_POWER_GPIO);
99
100
if (gpio_request(BKL_POWER_GPIO, "LCD backlight power"))
101
printk(KERN_ERR "Error requesting gpio %u",
102
BKL_POWER_GPIO);
103
else if (gpio_direction_output(BKL_POWER_GPIO, 1))
104
printk(KERN_ERR "Error setting gpio %u to output",
105
BKL_POWER_GPIO);
106
107
return 0;
108
}
109
110
static int lpc32xx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
111
{
112
return dma_mmap_writecombine(&fb->dev->dev, vma,
113
fb->fb.screen_base, fb->fb.fix.smem_start,
114
fb->fb.fix.smem_len);
115
}
116
117
static void lpc32xx_clcd_remove(struct clcd_fb *fb)
118
{
119
dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
120
fb->fb.screen_base, fb->fb.fix.smem_start);
121
}
122
123
/*
124
* On some early LCD modules (1307.0), the backlight logic is inverted.
125
* For those board variants, swap the disable and enable states for
126
* BKL_POWER_GPIO.
127
*/
128
static void clcd_disable(struct clcd_fb *fb)
129
{
130
gpio_set_value(BKL_POWER_GPIO, 0);
131
gpio_set_value(LCD_POWER_GPIO, 0);
132
}
133
134
static void clcd_enable(struct clcd_fb *fb)
135
{
136
gpio_set_value(BKL_POWER_GPIO, 1);
137
gpio_set_value(LCD_POWER_GPIO, 1);
138
}
139
140
static struct clcd_board lpc32xx_clcd_data = {
141
.name = "Phytec LCD",
142
.check = clcdfb_check,
143
.decode = clcdfb_decode,
144
.disable = clcd_disable,
145
.enable = clcd_enable,
146
.setup = lpc32xx_clcd_setup,
147
.mmap = lpc32xx_clcd_mmap,
148
.remove = lpc32xx_clcd_remove,
149
};
150
151
static struct amba_device lpc32xx_clcd_device = {
152
.dev = {
153
.coherent_dma_mask = ~0,
154
.init_name = "dev:clcd",
155
.platform_data = &lpc32xx_clcd_data,
156
},
157
.res = {
158
.start = LPC32XX_LCD_BASE,
159
.end = (LPC32XX_LCD_BASE + SZ_4K - 1),
160
.flags = IORESOURCE_MEM,
161
},
162
.dma_mask = ~0,
163
.irq = {IRQ_LPC32XX_LCD, NO_IRQ},
164
};
165
166
/*
167
* AMBA SSP (SPI)
168
*/
169
static void phy3250_spi_cs_set(u32 control)
170
{
171
gpio_set_value(SPI0_CS_GPIO, (int) control);
172
}
173
174
static struct pl022_config_chip spi0_chip_info = {
175
.com_mode = INTERRUPT_TRANSFER,
176
.iface = SSP_INTERFACE_MOTOROLA_SPI,
177
.hierarchy = SSP_MASTER,
178
.slave_tx_disable = 0,
179
.rx_lev_trig = SSP_RX_4_OR_MORE_ELEM,
180
.tx_lev_trig = SSP_TX_4_OR_MORE_EMPTY_LOC,
181
.ctrl_len = SSP_BITS_8,
182
.wait_state = SSP_MWIRE_WAIT_ZERO,
183
.duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
184
.cs_control = phy3250_spi_cs_set,
185
};
186
187
static struct pl022_ssp_controller lpc32xx_ssp0_data = {
188
.bus_id = 0,
189
.num_chipselect = 1,
190
.enable_dma = 0,
191
};
192
193
static struct amba_device lpc32xx_ssp0_device = {
194
.dev = {
195
.coherent_dma_mask = ~0,
196
.init_name = "dev:ssp0",
197
.platform_data = &lpc32xx_ssp0_data,
198
},
199
.res = {
200
.start = LPC32XX_SSP0_BASE,
201
.end = (LPC32XX_SSP0_BASE + SZ_4K - 1),
202
.flags = IORESOURCE_MEM,
203
},
204
.dma_mask = ~0,
205
.irq = {IRQ_LPC32XX_SSP0, NO_IRQ},
206
};
207
208
/* AT25 driver registration */
209
static int __init phy3250_spi_board_register(void)
210
{
211
#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
212
static struct spi_board_info info[] = {
213
{
214
.modalias = "spidev",
215
.max_speed_hz = 5000000,
216
.bus_num = 0,
217
.chip_select = 0,
218
.controller_data = &spi0_chip_info,
219
},
220
};
221
222
#else
223
static struct spi_eeprom eeprom = {
224
.name = "at25256a",
225
.byte_len = 0x8000,
226
.page_size = 64,
227
.flags = EE_ADDR2,
228
};
229
230
static struct spi_board_info info[] = {
231
{
232
.modalias = "at25",
233
.max_speed_hz = 5000000,
234
.bus_num = 0,
235
.chip_select = 0,
236
.mode = SPI_MODE_0,
237
.platform_data = &eeprom,
238
.controller_data = &spi0_chip_info,
239
},
240
};
241
#endif
242
return spi_register_board_info(info, ARRAY_SIZE(info));
243
}
244
arch_initcall(phy3250_spi_board_register);
245
246
static struct i2c_board_info __initdata phy3250_i2c_board_info[] = {
247
{
248
I2C_BOARD_INFO("pcf8563", 0x51),
249
},
250
};
251
252
static struct gpio_led phy_leds[] = {
253
{
254
.name = "led0",
255
.gpio = LED_GPIO,
256
.active_low = 1,
257
.default_trigger = "heartbeat",
258
},
259
};
260
261
static struct gpio_led_platform_data led_data = {
262
.leds = phy_leds,
263
.num_leds = ARRAY_SIZE(phy_leds),
264
};
265
266
static struct platform_device lpc32xx_gpio_led_device = {
267
.name = "leds-gpio",
268
.id = -1,
269
.dev.platform_data = &led_data,
270
};
271
272
static struct platform_device *phy3250_devs[] __initdata = {
273
&lpc32xx_i2c0_device,
274
&lpc32xx_i2c1_device,
275
&lpc32xx_i2c2_device,
276
&lpc32xx_watchdog_device,
277
&lpc32xx_gpio_led_device,
278
};
279
280
static struct amba_device *amba_devs[] __initdata = {
281
&lpc32xx_clcd_device,
282
&lpc32xx_ssp0_device,
283
};
284
285
/*
286
* Board specific functions
287
*/
288
static void __init phy3250_board_init(void)
289
{
290
u32 tmp;
291
int i;
292
293
lpc32xx_gpio_init();
294
295
/* Register GPIOs used on this board */
296
if (gpio_request(SPI0_CS_GPIO, "spi0 cs"))
297
printk(KERN_ERR "Error requesting gpio %u",
298
SPI0_CS_GPIO);
299
else if (gpio_direction_output(SPI0_CS_GPIO, 1))
300
printk(KERN_ERR "Error setting gpio %u to output",
301
SPI0_CS_GPIO);
302
303
/* Setup network interface for RMII mode */
304
tmp = __raw_readl(LPC32XX_CLKPWR_MACCLK_CTRL);
305
tmp &= ~LPC32XX_CLKPWR_MACCTRL_PINS_MSK;
306
tmp |= LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS;
307
__raw_writel(tmp, LPC32XX_CLKPWR_MACCLK_CTRL);
308
309
/* Setup SLC NAND controller muxing */
310
__raw_writel(LPC32XX_CLKPWR_NANDCLK_SEL_SLC,
311
LPC32XX_CLKPWR_NAND_CLK_CTRL);
312
313
/* Setup LCD muxing to RGB565 */
314
tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL) &
315
~(LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_MSK |
316
LPC32XX_CLKPWR_LCDCTRL_PSCALE_MSK);
317
tmp |= LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT16;
318
__raw_writel(tmp, LPC32XX_CLKPWR_LCDCLK_CTRL);
319
320
/* Set up I2C pull levels */
321
tmp = __raw_readl(LPC32XX_CLKPWR_I2C_CLK_CTRL);
322
tmp |= LPC32XX_CLKPWR_I2CCLK_USBI2CHI_DRIVE |
323
LPC32XX_CLKPWR_I2CCLK_I2C2HI_DRIVE;
324
__raw_writel(tmp, LPC32XX_CLKPWR_I2C_CLK_CTRL);
325
326
/* Disable IrDA pulsing support on UART6 */
327
tmp = __raw_readl(LPC32XX_UARTCTL_CTRL);
328
tmp |= LPC32XX_UART_UART6_IRDAMOD_BYPASS;
329
__raw_writel(tmp, LPC32XX_UARTCTL_CTRL);
330
331
/* Enable DMA for I2S1 channel */
332
tmp = __raw_readl(LPC32XX_CLKPWR_I2S_CLK_CTRL);
333
tmp = LPC32XX_CLKPWR_I2SCTRL_I2S1_USE_DMA;
334
__raw_writel(tmp, LPC32XX_CLKPWR_I2S_CLK_CTRL);
335
336
lpc32xx_serial_init();
337
338
/*
339
* AMBA peripheral clocks need to be enabled prior to AMBA device
340
* detection or a data fault will occur, so enable the clocks
341
* here. However, we don't want to enable them if the peripheral
342
* isn't included in the image
343
*/
344
#ifdef CONFIG_FB_ARMCLCD
345
tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL);
346
__raw_writel((tmp | LPC32XX_CLKPWR_LCDCTRL_CLK_EN),
347
LPC32XX_CLKPWR_LCDCLK_CTRL);
348
#endif
349
#ifdef CONFIG_SPI_PL022
350
tmp = __raw_readl(LPC32XX_CLKPWR_SSP_CLK_CTRL);
351
__raw_writel((tmp | LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN),
352
LPC32XX_CLKPWR_SSP_CLK_CTRL);
353
#endif
354
355
platform_add_devices(phy3250_devs, ARRAY_SIZE(phy3250_devs));
356
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
357
struct amba_device *d = amba_devs[i];
358
amba_device_register(d, &iomem_resource);
359
}
360
361
/* Test clock needed for UDA1380 initial init */
362
__raw_writel(LPC32XX_CLKPWR_TESTCLK2_SEL_MOSC |
363
LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN,
364
LPC32XX_CLKPWR_TEST_CLK_SEL);
365
366
i2c_register_board_info(0, phy3250_i2c_board_info,
367
ARRAY_SIZE(phy3250_i2c_board_info));
368
}
369
370
static int __init lpc32xx_display_uid(void)
371
{
372
u32 uid[4];
373
374
lpc32xx_get_uid(uid);
375
376
printk(KERN_INFO "LPC32XX unique ID: %08x%08x%08x%08x\n",
377
uid[3], uid[2], uid[1], uid[0]);
378
379
return 1;
380
}
381
arch_initcall(lpc32xx_display_uid);
382
383
MACHINE_START(PHY3250, "Phytec 3250 board with the LPC3250 Microcontroller")
384
/* Maintainer: Kevin Wells, NXP Semiconductors */
385
.boot_params = 0x80000100,
386
.map_io = lpc32xx_map_io,
387
.init_irq = lpc32xx_init_irq,
388
.timer = &lpc32xx_timer,
389
.init_machine = phy3250_board_init,
390
MACHINE_END
391
392