0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #include <linux/gpio.h>
0020 #include <linux/irq.h>
0021 #include <linux/platform_device.h>
0022 #include <linux/i2c.h>
0023 #include <linux/platform_data/i2c-pxa.h>
0024 #include <linux/pwm.h>
0025 #include <linux/pwm_backlight.h>
0026
0027 #include <asm/mach/map.h>
0028 #include "pxa27x.h"
0029 #include <linux/platform_data/asoc-pxa.h>
0030 #include <linux/platform_data/mmc-pxamci.h>
0031 #include <linux/platform_data/usb-ohci-pxa27x.h>
0032 #include "pcm990_baseboard.h"
0033 #include <linux/platform_data/video-pxafb.h>
0034
0035 #include "devices.h"
0036 #include "generic.h"
0037
0038 static unsigned long pcm990_pin_config[] __initdata = {
0039
0040 GPIO32_MMC_CLK,
0041 GPIO112_MMC_CMD,
0042 GPIO92_MMC_DAT_0,
0043 GPIO109_MMC_DAT_1,
0044 GPIO110_MMC_DAT_2,
0045 GPIO111_MMC_DAT_3,
0046
0047 GPIO88_USBH1_PWR,
0048 GPIO89_USBH1_PEN,
0049
0050 GPIO16_PWM0_OUT,
0051
0052
0053 GPIO117_I2C_SCL,
0054 GPIO118_I2C_SDA,
0055
0056
0057 GPIO28_AC97_BITCLK,
0058 GPIO29_AC97_SDATA_IN_0,
0059 GPIO30_AC97_SDATA_OUT,
0060 GPIO31_AC97_SYNC,
0061 };
0062
0063 static void __iomem *pcm990_cpld_base;
0064
0065 static u8 pcm990_cpld_readb(unsigned int reg)
0066 {
0067 return readb(pcm990_cpld_base + reg);
0068 }
0069
0070 static void pcm990_cpld_writeb(u8 value, unsigned int reg)
0071 {
0072 writeb(value, pcm990_cpld_base + reg);
0073 }
0074
0075
0076
0077
0078
0079
0080
0081 #ifndef CONFIG_PCM990_DISPLAY_NONE
0082 static void pcm990_lcd_power(int on, struct fb_var_screeninfo *var)
0083 {
0084 if (on) {
0085
0086
0087
0088 pcm990_cpld_writeb(PCM990_CTRL_LCDPWR + PCM990_CTRL_LCDON,
0089 PCM990_CTRL_REG3);
0090 } else {
0091
0092
0093
0094 pcm990_cpld_writeb(0, PCM990_CTRL_REG3);
0095 }
0096 }
0097 #endif
0098
0099 #if defined(CONFIG_PCM990_DISPLAY_SHARP)
0100 static struct pxafb_mode_info fb_info_sharp_lq084v1dg21 = {
0101 .pixclock = 28000,
0102 .xres = 640,
0103 .yres = 480,
0104 .bpp = 16,
0105 .hsync_len = 20,
0106 .left_margin = 103,
0107 .right_margin = 47,
0108 .vsync_len = 6,
0109 .upper_margin = 28,
0110 .lower_margin = 5,
0111 .sync = 0,
0112 .cmap_greyscale = 0,
0113 };
0114
0115 static struct pxafb_mach_info pcm990_fbinfo __initdata = {
0116 .modes = &fb_info_sharp_lq084v1dg21,
0117 .num_modes = 1,
0118 .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
0119 .pxafb_lcd_power = pcm990_lcd_power,
0120 };
0121 #elif defined(CONFIG_PCM990_DISPLAY_NEC)
0122 struct pxafb_mode_info fb_info_nec_nl6448bc20_18d = {
0123 .pixclock = 39720,
0124 .xres = 640,
0125 .yres = 480,
0126 .bpp = 16,
0127 .hsync_len = 32,
0128 .left_margin = 16,
0129 .right_margin = 48,
0130 .vsync_len = 2,
0131 .upper_margin = 12,
0132 .lower_margin = 17,
0133 .sync = 0,
0134 .cmap_greyscale = 0,
0135 };
0136
0137 static struct pxafb_mach_info pcm990_fbinfo __initdata = {
0138 .modes = &fb_info_nec_nl6448bc20_18d,
0139 .num_modes = 1,
0140 .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
0141 .pxafb_lcd_power = pcm990_lcd_power,
0142 };
0143 #endif
0144
0145 static struct pwm_lookup pcm990_pwm_lookup[] = {
0146 PWM_LOOKUP("pxa27x-pwm.0", 0, "pwm-backlight.0", NULL, 78770,
0147 PWM_POLARITY_NORMAL),
0148 };
0149
0150 static struct platform_pwm_backlight_data pcm990_backlight_data = {
0151 .max_brightness = 1023,
0152 .dft_brightness = 1023,
0153 };
0154
0155 static struct platform_device pcm990_backlight_device = {
0156 .name = "pwm-backlight",
0157 .dev = {
0158 .parent = &pxa27x_device_pwm0.dev,
0159 .platform_data = &pcm990_backlight_data,
0160 },
0161 };
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251 static unsigned long pcm990_irq_enabled;
0252
0253 static void pcm990_mask_ack_irq(struct irq_data *d)
0254 {
0255 int pcm990_irq = (d->irq - PCM027_IRQ(0));
0256
0257 pcm990_irq_enabled &= ~(1 << pcm990_irq);
0258
0259 pcm990_cpld_writeb(pcm990_irq_enabled, PCM990_CTRL_INTMSKENA);
0260 }
0261
0262 static void pcm990_unmask_irq(struct irq_data *d)
0263 {
0264 int pcm990_irq = (d->irq - PCM027_IRQ(0));
0265 u8 val;
0266
0267
0268
0269 pcm990_irq_enabled |= (1 << pcm990_irq);
0270
0271 val = pcm990_cpld_readb(PCM990_CTRL_INTSETCLR);
0272 val |= 1 << pcm990_irq;
0273 pcm990_cpld_writeb(val, PCM990_CTRL_INTSETCLR);
0274
0275 pcm990_cpld_writeb(pcm990_irq_enabled, PCM990_CTRL_INTMSKENA);
0276 }
0277
0278 static struct irq_chip pcm990_irq_chip = {
0279 .irq_mask_ack = pcm990_mask_ack_irq,
0280 .irq_unmask = pcm990_unmask_irq,
0281 };
0282
0283 static void pcm990_irq_handler(struct irq_desc *desc)
0284 {
0285 unsigned int irq;
0286 unsigned long pending;
0287
0288 pending = ~pcm990_cpld_readb(PCM990_CTRL_INTSETCLR);
0289 pending &= pcm990_irq_enabled;
0290
0291 do {
0292
0293 desc->irq_data.chip->irq_ack(&desc->irq_data);
0294 if (likely(pending)) {
0295 irq = PCM027_IRQ(0) + __ffs(pending);
0296 generic_handle_irq(irq);
0297 }
0298 pending = ~pcm990_cpld_readb(PCM990_CTRL_INTSETCLR);
0299 pending &= pcm990_irq_enabled;
0300 } while (pending);
0301 }
0302
0303 static void __init pcm990_init_irq(void)
0304 {
0305 int irq;
0306
0307
0308 for (irq = PCM027_IRQ(0); irq <= PCM027_IRQ(3); irq++) {
0309 irq_set_chip_and_handler(irq, &pcm990_irq_chip,
0310 handle_level_irq);
0311 irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
0312 }
0313
0314
0315 pcm990_cpld_writeb(0x0, PCM990_CTRL_INTMSKENA);
0316 pcm990_cpld_writeb(0xff, PCM990_CTRL_INTSETCLR);
0317
0318 irq_set_chained_handler(PCM990_CTRL_INT_IRQ, pcm990_irq_handler);
0319 irq_set_irq_type(PCM990_CTRL_INT_IRQ, PCM990_CTRL_INT_IRQ_EDGE);
0320 }
0321
0322 static int pcm990_mci_init(struct device *dev, irq_handler_t mci_detect_int,
0323 void *data)
0324 {
0325 int err;
0326
0327 err = request_irq(PCM027_MMCDET_IRQ, mci_detect_int, 0,
0328 "MMC card detect", data);
0329 if (err)
0330 printk(KERN_ERR "pcm990_mci_init: MMC/SD: can't request MMC "
0331 "card detect IRQ\n");
0332
0333 return err;
0334 }
0335
0336 static int pcm990_mci_setpower(struct device *dev, unsigned int vdd)
0337 {
0338 struct pxamci_platform_data *p_d = dev->platform_data;
0339 u8 val;
0340
0341 val = pcm990_cpld_readb(PCM990_CTRL_REG5);
0342
0343 if ((1 << vdd) & p_d->ocr_mask)
0344 val |= PCM990_CTRL_MMC2PWR;
0345 else
0346 val &= ~PCM990_CTRL_MMC2PWR;
0347
0348 pcm990_cpld_writeb(PCM990_CTRL_MMC2PWR, PCM990_CTRL_REG5);
0349 return 0;
0350 }
0351
0352 static void pcm990_mci_exit(struct device *dev, void *data)
0353 {
0354 free_irq(PCM027_MMCDET_IRQ, data);
0355 }
0356
0357 #define MSECS_PER_JIFFY (1000/HZ)
0358
0359 static struct pxamci_platform_data pcm990_mci_platform_data = {
0360 .detect_delay_ms = 250,
0361 .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
0362 .init = pcm990_mci_init,
0363 .setpower = pcm990_mci_setpower,
0364 .exit = pcm990_mci_exit,
0365 };
0366
0367 static struct pxaohci_platform_data pcm990_ohci_platform_data = {
0368 .port_mode = PMM_PERPORT_MODE,
0369 .flags = ENABLE_PORT1 | POWER_CONTROL_LOW | POWER_SENSE_LOW,
0370 .power_on_delay = 10,
0371 };
0372
0373
0374
0375
0376
0377
0378
0379 void __init pcm990_baseboard_init(void)
0380 {
0381 pxa2xx_mfp_config(ARRAY_AND_SIZE(pcm990_pin_config));
0382
0383 pcm990_cpld_base = ioremap(PCM990_CTRL_PHYS, PCM990_CTRL_SIZE);
0384 if (!pcm990_cpld_base) {
0385 pr_err("pcm990: failed to ioremap cpld\n");
0386 return;
0387 }
0388
0389
0390 pcm990_init_irq();
0391
0392 #ifndef CONFIG_PCM990_DISPLAY_NONE
0393 pxa_set_fb_info(NULL, &pcm990_fbinfo);
0394 #endif
0395 pwm_add_table(pcm990_pwm_lookup, ARRAY_SIZE(pcm990_pwm_lookup));
0396 platform_device_register(&pcm990_backlight_device);
0397
0398
0399 pxa_set_mci_info(&pcm990_mci_platform_data);
0400
0401
0402 pxa_set_ohci_info(&pcm990_ohci_platform_data);
0403
0404 pxa_set_i2c_info(NULL);
0405 pxa_set_ac97_info(NULL);
0406
0407 printk(KERN_INFO "PCM-990 Evaluation baseboard initialized\n");
0408 }