WIP FPC-III support
[linux/fpc-iii.git] / arch / arm / mach-pxa / pcm990-baseboard.c
blob8dfcc366d0fe93938b4361f745c4891187ae9bfd
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * arch/arm/mach-pxa/pcm990-baseboard.c
4 * Support for the Phytec phyCORE-PXA270 Development Platform (PCM-990).
6 * Refer
7 * http://www.phytec.com/products/rdk/ARM-XScale/phyCORE-XScale-PXA270.html
8 * for additional hardware info
10 * Author: Juergen Kilb
11 * Created: April 05, 2005
12 * Copyright: Phytec Messtechnik GmbH
13 * e-Mail: armlinux@phytec.de
15 * based on Intel Mainstone Board
17 * Copyright 2007 Juergen Beisert @ Pengutronix (j.beisert@pengutronix.de)
19 #include <linux/gpio.h>
20 #include <linux/irq.h>
21 #include <linux/platform_device.h>
22 #include <linux/i2c.h>
23 #include <linux/platform_data/i2c-pxa.h>
24 #include <linux/pwm.h>
25 #include <linux/pwm_backlight.h>
27 #include <asm/mach/map.h>
28 #include "pxa27x.h"
29 #include <mach/audio.h>
30 #include <linux/platform_data/mmc-pxamci.h>
31 #include <linux/platform_data/usb-ohci-pxa27x.h>
32 #include "pcm990_baseboard.h"
33 #include <linux/platform_data/video-pxafb.h>
35 #include "devices.h"
36 #include "generic.h"
38 static unsigned long pcm990_pin_config[] __initdata = {
39 /* MMC */
40 GPIO32_MMC_CLK,
41 GPIO112_MMC_CMD,
42 GPIO92_MMC_DAT_0,
43 GPIO109_MMC_DAT_1,
44 GPIO110_MMC_DAT_2,
45 GPIO111_MMC_DAT_3,
46 /* USB */
47 GPIO88_USBH1_PWR,
48 GPIO89_USBH1_PEN,
49 /* PWM0 */
50 GPIO16_PWM0_OUT,
52 /* I2C */
53 GPIO117_I2C_SCL,
54 GPIO118_I2C_SDA,
56 /* AC97 */
57 GPIO28_AC97_BITCLK,
58 GPIO29_AC97_SDATA_IN_0,
59 GPIO30_AC97_SDATA_OUT,
60 GPIO31_AC97_SYNC,
63 static void __iomem *pcm990_cpld_base;
65 static u8 pcm990_cpld_readb(unsigned int reg)
67 return readb(pcm990_cpld_base + reg);
70 static void pcm990_cpld_writeb(u8 value, unsigned int reg)
72 writeb(value, pcm990_cpld_base + reg);
76 * pcm990_lcd_power - control power supply to the LCD
77 * @on: 0 = switch off, 1 = switch on
79 * Called by the pxafb driver
81 #ifndef CONFIG_PCM990_DISPLAY_NONE
82 static void pcm990_lcd_power(int on, struct fb_var_screeninfo *var)
84 if (on) {
85 /* enable LCD-Latches
86 * power on LCD
88 pcm990_cpld_writeb(PCM990_CTRL_LCDPWR + PCM990_CTRL_LCDON,
89 PCM990_CTRL_REG3);
90 } else {
91 /* disable LCD-Latches
92 * power off LCD
94 pcm990_cpld_writeb(0, PCM990_CTRL_REG3);
97 #endif
99 #if defined(CONFIG_PCM990_DISPLAY_SHARP)
100 static struct pxafb_mode_info fb_info_sharp_lq084v1dg21 = {
101 .pixclock = 28000,
102 .xres = 640,
103 .yres = 480,
104 .bpp = 16,
105 .hsync_len = 20,
106 .left_margin = 103,
107 .right_margin = 47,
108 .vsync_len = 6,
109 .upper_margin = 28,
110 .lower_margin = 5,
111 .sync = 0,
112 .cmap_greyscale = 0,
115 static struct pxafb_mach_info pcm990_fbinfo __initdata = {
116 .modes = &fb_info_sharp_lq084v1dg21,
117 .num_modes = 1,
118 .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
119 .pxafb_lcd_power = pcm990_lcd_power,
121 #elif defined(CONFIG_PCM990_DISPLAY_NEC)
122 struct pxafb_mode_info fb_info_nec_nl6448bc20_18d = {
123 .pixclock = 39720,
124 .xres = 640,
125 .yres = 480,
126 .bpp = 16,
127 .hsync_len = 32,
128 .left_margin = 16,
129 .right_margin = 48,
130 .vsync_len = 2,
131 .upper_margin = 12,
132 .lower_margin = 17,
133 .sync = 0,
134 .cmap_greyscale = 0,
137 static struct pxafb_mach_info pcm990_fbinfo __initdata = {
138 .modes = &fb_info_nec_nl6448bc20_18d,
139 .num_modes = 1,
140 .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
141 .pxafb_lcd_power = pcm990_lcd_power,
143 #endif
145 static struct pwm_lookup pcm990_pwm_lookup[] = {
146 PWM_LOOKUP("pxa27x-pwm.0", 0, "pwm-backlight.0", NULL, 78770,
147 PWM_POLARITY_NORMAL),
150 static struct platform_pwm_backlight_data pcm990_backlight_data = {
151 .max_brightness = 1023,
152 .dft_brightness = 1023,
155 static struct platform_device pcm990_backlight_device = {
156 .name = "pwm-backlight",
157 .dev = {
158 .parent = &pxa27x_device_pwm0.dev,
159 .platform_data = &pcm990_backlight_data,
164 * The PCM-990 development baseboard uses PCM-027's hardware in the
165 * following way:
167 * - LCD support is in use
168 * - GPIO16 is output for back light on/off with PWM
169 * - GPIO58 ... GPIO73 are outputs for display data
170 * - GPIO74 is output output for LCDFCLK
171 * - GPIO75 is output for LCDLCLK
172 * - GPIO76 is output for LCDPCLK
173 * - GPIO77 is output for LCDBIAS
174 * - MMC support is in use
175 * - GPIO32 is output for MMCCLK
176 * - GPIO92 is MMDAT0
177 * - GPIO109 is MMDAT1
178 * - GPIO110 is MMCS0
179 * - GPIO111 is MMCS1
180 * - GPIO112 is MMCMD
181 * - IDE/CF card is in use
182 * - GPIO48 is output /POE
183 * - GPIO49 is output /PWE
184 * - GPIO50 is output /PIOR
185 * - GPIO51 is output /PIOW
186 * - GPIO54 is output /PCE2
187 * - GPIO55 is output /PREG
188 * - GPIO56 is input /PWAIT
189 * - GPIO57 is output /PIOS16
190 * - GPIO79 is output PSKTSEL
191 * - GPIO85 is output /PCE1
192 * - FFUART is in use
193 * - GPIO34 is input FFRXD
194 * - GPIO35 is input FFCTS
195 * - GPIO36 is input FFDCD
196 * - GPIO37 is input FFDSR
197 * - GPIO38 is input FFRI
198 * - GPIO39 is output FFTXD
199 * - GPIO40 is output FFDTR
200 * - GPIO41 is output FFRTS
201 * - BTUART is in use
202 * - GPIO42 is input BTRXD
203 * - GPIO43 is output BTTXD
204 * - GPIO44 is input BTCTS
205 * - GPIO45 is output BTRTS
206 * - IRUART is in use
207 * - GPIO46 is input STDRXD
208 * - GPIO47 is output STDTXD
209 * - AC97 is in use*)
210 * - GPIO28 is input AC97CLK
211 * - GPIO29 is input AC97DatIn
212 * - GPIO30 is output AC97DatO
213 * - GPIO31 is output AC97SYNC
214 * - GPIO113 is output AC97_RESET
215 * - SSP is in use
216 * - GPIO23 is output SSPSCLK
217 * - GPIO24 is output chip select to Max7301
218 * - GPIO25 is output SSPTXD
219 * - GPIO26 is input SSPRXD
220 * - GPIO27 is input for Max7301 IRQ
221 * - GPIO53 is input SSPSYSCLK
222 * - SSP3 is in use
223 * - GPIO81 is output SSPTXD3
224 * - GPIO82 is input SSPRXD3
225 * - GPIO83 is output SSPSFRM
226 * - GPIO84 is output SSPCLK3
228 * Otherwise claimed GPIOs:
229 * GPIO1 -> IRQ from user switch
230 * GPIO9 -> IRQ from power management
231 * GPIO10 -> IRQ from WML9712 AC97 controller
232 * GPIO11 -> IRQ from IDE controller
233 * GPIO12 -> IRQ from CF controller
234 * GPIO13 -> IRQ from CF controller
235 * GPIO14 -> GPIO free
236 * GPIO15 -> /CS1 selects baseboard's Control CPLD (U7, 16 bit wide data path)
237 * GPIO19 -> GPIO free
238 * GPIO20 -> /SDCS2
239 * GPIO21 -> /CS3 PC card socket select
240 * GPIO33 -> /CS5 network controller select
241 * GPIO78 -> /CS2 (16 bit wide data path)
242 * GPIO80 -> /CS4 (16 bit wide data path)
243 * GPIO86 -> GPIO free
244 * GPIO87 -> GPIO free
245 * GPIO90 -> LED0 on CPU module
246 * GPIO91 -> LED1 on CPI module
247 * GPIO117 -> SCL
248 * GPIO118 -> SDA
251 static unsigned long pcm990_irq_enabled;
253 static void pcm990_mask_ack_irq(struct irq_data *d)
255 int pcm990_irq = (d->irq - PCM027_IRQ(0));
257 pcm990_irq_enabled &= ~(1 << pcm990_irq);
259 pcm990_cpld_writeb(pcm990_irq_enabled, PCM990_CTRL_INTMSKENA);
262 static void pcm990_unmask_irq(struct irq_data *d)
264 int pcm990_irq = (d->irq - PCM027_IRQ(0));
265 u8 val;
267 /* the irq can be acknowledged only if deasserted, so it's done here */
269 pcm990_irq_enabled |= (1 << pcm990_irq);
271 val = pcm990_cpld_readb(PCM990_CTRL_INTSETCLR);
272 val |= 1 << pcm990_irq;
273 pcm990_cpld_writeb(val, PCM990_CTRL_INTSETCLR);
275 pcm990_cpld_writeb(pcm990_irq_enabled, PCM990_CTRL_INTMSKENA);
278 static struct irq_chip pcm990_irq_chip = {
279 .irq_mask_ack = pcm990_mask_ack_irq,
280 .irq_unmask = pcm990_unmask_irq,
283 static void pcm990_irq_handler(struct irq_desc *desc)
285 unsigned int irq;
286 unsigned long pending;
288 pending = ~pcm990_cpld_readb(PCM990_CTRL_INTSETCLR);
289 pending &= pcm990_irq_enabled;
291 do {
292 /* clear our parent IRQ */
293 desc->irq_data.chip->irq_ack(&desc->irq_data);
294 if (likely(pending)) {
295 irq = PCM027_IRQ(0) + __ffs(pending);
296 generic_handle_irq(irq);
298 pending = ~pcm990_cpld_readb(PCM990_CTRL_INTSETCLR);
299 pending &= pcm990_irq_enabled;
300 } while (pending);
303 static void __init pcm990_init_irq(void)
305 int irq;
307 /* setup extra PCM990 irqs */
308 for (irq = PCM027_IRQ(0); irq <= PCM027_IRQ(3); irq++) {
309 irq_set_chip_and_handler(irq, &pcm990_irq_chip,
310 handle_level_irq);
311 irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
314 /* disable all Interrupts */
315 pcm990_cpld_writeb(0x0, PCM990_CTRL_INTMSKENA);
316 pcm990_cpld_writeb(0xff, PCM990_CTRL_INTSETCLR);
318 irq_set_chained_handler(PCM990_CTRL_INT_IRQ, pcm990_irq_handler);
319 irq_set_irq_type(PCM990_CTRL_INT_IRQ, PCM990_CTRL_INT_IRQ_EDGE);
322 static int pcm990_mci_init(struct device *dev, irq_handler_t mci_detect_int,
323 void *data)
325 int err;
327 err = request_irq(PCM027_MMCDET_IRQ, mci_detect_int, 0,
328 "MMC card detect", data);
329 if (err)
330 printk(KERN_ERR "pcm990_mci_init: MMC/SD: can't request MMC "
331 "card detect IRQ\n");
333 return err;
336 static int pcm990_mci_setpower(struct device *dev, unsigned int vdd)
338 struct pxamci_platform_data *p_d = dev->platform_data;
339 u8 val;
341 val = pcm990_cpld_readb(PCM990_CTRL_REG5);
343 if ((1 << vdd) & p_d->ocr_mask)
344 val |= PCM990_CTRL_MMC2PWR;
345 else
346 val &= ~PCM990_CTRL_MMC2PWR;
348 pcm990_cpld_writeb(PCM990_CTRL_MMC2PWR, PCM990_CTRL_REG5);
349 return 0;
352 static void pcm990_mci_exit(struct device *dev, void *data)
354 free_irq(PCM027_MMCDET_IRQ, data);
357 #define MSECS_PER_JIFFY (1000/HZ)
359 static struct pxamci_platform_data pcm990_mci_platform_data = {
360 .detect_delay_ms = 250,
361 .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
362 .init = pcm990_mci_init,
363 .setpower = pcm990_mci_setpower,
364 .exit = pcm990_mci_exit,
367 static struct pxaohci_platform_data pcm990_ohci_platform_data = {
368 .port_mode = PMM_PERPORT_MODE,
369 .flags = ENABLE_PORT1 | POWER_CONTROL_LOW | POWER_SENSE_LOW,
370 .power_on_delay = 10,
374 * system init for baseboard usage. Will be called by pcm027 init.
376 * Add platform devices present on this baseboard and init
377 * them from CPU side as far as required to use them later on
379 void __init pcm990_baseboard_init(void)
381 pxa2xx_mfp_config(ARRAY_AND_SIZE(pcm990_pin_config));
383 pcm990_cpld_base = ioremap(PCM990_CTRL_PHYS, PCM990_CTRL_SIZE);
384 if (!pcm990_cpld_base) {
385 pr_err("pcm990: failed to ioremap cpld\n");
386 return;
389 /* register CPLD's IRQ controller */
390 pcm990_init_irq();
392 #ifndef CONFIG_PCM990_DISPLAY_NONE
393 pxa_set_fb_info(NULL, &pcm990_fbinfo);
394 #endif
395 pwm_add_table(pcm990_pwm_lookup, ARRAY_SIZE(pcm990_pwm_lookup));
396 platform_device_register(&pcm990_backlight_device);
398 /* MMC */
399 pxa_set_mci_info(&pcm990_mci_platform_data);
401 /* USB host */
402 pxa_set_ohci_info(&pcm990_ohci_platform_data);
404 pxa_set_i2c_info(NULL);
405 pxa_set_ac97_info(NULL);
407 printk(KERN_INFO "PCM-990 Evaluation baseboard initialized\n");