Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  linux/arch/arm/mach-pxa/idp.c
0004  *
0005  *  Copyright (c) 2001 Cliff Brake, Accelent Systems Inc.
0006  *
0007  *  2001-09-13: Cliff Brake <cbrake@accelent.com>
0008  *              Initial code
0009  *
0010  *  2005-02-15: Cliff Brake <cliff.brake@gmail.com>
0011  *          <http://www.vibren.com> <http://bec-systems.com>
0012  *              Updated for 2.6 kernel
0013  */
0014 
0015 #include <linux/init.h>
0016 #include <linux/interrupt.h>
0017 #include <linux/irq.h>
0018 #include <linux/leds.h>
0019 #include <linux/platform_device.h>
0020 #include <linux/fb.h>
0021 
0022 #include <asm/setup.h>
0023 #include <asm/memory.h>
0024 #include <asm/mach-types.h>
0025 #include <asm/irq.h>
0026 
0027 #include <asm/mach/arch.h>
0028 #include <asm/mach/map.h>
0029 
0030 #include "pxa25x.h"
0031 #include "idp.h"
0032 #include <linux/platform_data/video-pxafb.h>
0033 #include <linux/platform_data/mmc-pxamci.h>
0034 #include <linux/smc91x.h>
0035 
0036 #include "generic.h"
0037 #include "devices.h"
0038 
0039 /* TODO:
0040  * - add pxa2xx_audio_ops_t device structure
0041  * - Ethernet interrupt
0042  */
0043 
0044 static unsigned long idp_pin_config[] __initdata = {
0045     /* LCD */
0046     GPIOxx_LCD_DSTN_16BPP,
0047 
0048     /* BTUART */
0049     GPIO42_BTUART_RXD,
0050     GPIO43_BTUART_TXD,
0051     GPIO44_BTUART_CTS,
0052     GPIO45_BTUART_RTS,
0053 
0054     /* STUART */
0055     GPIO46_STUART_RXD,
0056     GPIO47_STUART_TXD,
0057 
0058     /* MMC */
0059     GPIO6_MMC_CLK,
0060     GPIO8_MMC_CS0,
0061 
0062     /* Ethernet */
0063     GPIO33_nCS_5,   /* Ethernet CS */
0064     GPIO4_GPIO, /* Ethernet IRQ */
0065 };
0066 
0067 static struct resource smc91x_resources[] = {
0068     [0] = {
0069         .start  = (IDP_ETH_PHYS + 0x300),
0070         .end    = (IDP_ETH_PHYS + 0xfffff),
0071         .flags  = IORESOURCE_MEM,
0072     },
0073     [1] = {
0074         .start  = PXA_GPIO_TO_IRQ(4),
0075         .end    = PXA_GPIO_TO_IRQ(4),
0076         .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
0077     }
0078 };
0079 
0080 static struct smc91x_platdata smc91x_platdata = {
0081     .flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT |
0082          SMC91X_USE_DMA | SMC91X_NOWAIT,
0083     .pxa_u16_align4 = true,
0084 };
0085 
0086 static struct platform_device smc91x_device = {
0087     .name       = "smc91x",
0088     .id     = 0,
0089     .num_resources  = ARRAY_SIZE(smc91x_resources),
0090     .resource   = smc91x_resources,
0091     .dev.platform_data = &smc91x_platdata,
0092 };
0093 
0094 static void idp_backlight_power(int on)
0095 {
0096     if (on) {
0097         IDP_CPLD_LCD |= (1<<1);
0098     } else {
0099         IDP_CPLD_LCD &= ~(1<<1);
0100     }
0101 }
0102 
0103 static void idp_vlcd(int on)
0104 {
0105     if (on) {
0106         IDP_CPLD_LCD |= (1<<2);
0107     } else {
0108         IDP_CPLD_LCD &= ~(1<<2);
0109     }
0110 }
0111 
0112 static void idp_lcd_power(int on, struct fb_var_screeninfo *var)
0113 {
0114     if (on) {
0115         IDP_CPLD_LCD |= (1<<0);
0116     } else {
0117         IDP_CPLD_LCD &= ~(1<<0);
0118     }
0119 
0120     /* call idp_vlcd for now as core driver does not support
0121      * both power and vlcd hooks.  Note, this is not technically
0122      * the correct sequence, but seems to work.  Disclaimer:
0123      * this may eventually damage the display.
0124      */
0125 
0126     idp_vlcd(on);
0127 }
0128 
0129 static struct pxafb_mode_info sharp_lm8v31_mode = {
0130     .pixclock   = 270000,
0131     .xres       = 640,
0132     .yres       = 480,
0133     .bpp        = 16,
0134     .hsync_len  = 1,
0135     .left_margin    = 3,
0136     .right_margin   = 3,
0137     .vsync_len  = 1,
0138     .upper_margin   = 0,
0139     .lower_margin   = 0,
0140     .sync       = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0141     .cmap_greyscale = 0,
0142 };
0143 
0144 static struct pxafb_mach_info sharp_lm8v31 = {
0145     .modes          = &sharp_lm8v31_mode,
0146     .num_modes      = 1,
0147     .cmap_inverse   = 0,
0148     .cmap_static    = 0,
0149     .lcd_conn   = LCD_COLOR_DSTN_16BPP | LCD_PCLK_EDGE_FALL |
0150               LCD_AC_BIAS_FREQ(255),
0151     .pxafb_backlight_power = &idp_backlight_power,
0152     .pxafb_lcd_power = &idp_lcd_power
0153 };
0154 
0155 static struct pxamci_platform_data idp_mci_platform_data = {
0156     .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
0157 };
0158 
0159 static void __init idp_init(void)
0160 {
0161     printk("idp_init()\n");
0162 
0163     pxa2xx_mfp_config(ARRAY_AND_SIZE(idp_pin_config));
0164     pxa_set_ffuart_info(NULL);
0165     pxa_set_btuart_info(NULL);
0166     pxa_set_stuart_info(NULL);
0167 
0168     platform_device_register(&smc91x_device);
0169     //platform_device_register(&mst_audio_device);
0170     pxa_set_fb_info(NULL, &sharp_lm8v31);
0171     pxa_set_mci_info(&idp_mci_platform_data);
0172 }
0173 
0174 static struct map_desc idp_io_desc[] __initdata = {
0175     {
0176         .virtual    =  IDP_COREVOLT_VIRT,
0177         .pfn        = __phys_to_pfn(IDP_COREVOLT_PHYS),
0178         .length     = IDP_COREVOLT_SIZE,
0179         .type       = MT_DEVICE
0180     }, {
0181         .virtual    =  IDP_CPLD_VIRT,
0182         .pfn        = __phys_to_pfn(IDP_CPLD_PHYS),
0183         .length     = IDP_CPLD_SIZE,
0184         .type       = MT_DEVICE
0185     }
0186 };
0187 
0188 static void __init idp_map_io(void)
0189 {
0190     pxa25x_map_io();
0191     iotable_init(idp_io_desc, ARRAY_SIZE(idp_io_desc));
0192 }
0193 
0194 /* LEDs */
0195 #if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
0196 struct idp_led {
0197     struct led_classdev     cdev;
0198     u8                      mask;
0199 };
0200 
0201 /*
0202  * The triggers lines up below will only be used if the
0203  * LED triggers are compiled in.
0204  */
0205 static const struct {
0206     const char *name;
0207     const char *trigger;
0208 } idp_leds[] = {
0209     { "idp:green", "heartbeat", },
0210     { "idp:red", "cpu0", },
0211 };
0212 
0213 static void idp_led_set(struct led_classdev *cdev,
0214         enum led_brightness b)
0215 {
0216     struct idp_led *led = container_of(cdev,
0217             struct idp_led, cdev);
0218     u32 reg = IDP_CPLD_LED_CONTROL;
0219 
0220     if (b != LED_OFF)
0221         reg &= ~led->mask;
0222     else
0223         reg |= led->mask;
0224 
0225     IDP_CPLD_LED_CONTROL = reg;
0226 }
0227 
0228 static enum led_brightness idp_led_get(struct led_classdev *cdev)
0229 {
0230     struct idp_led *led = container_of(cdev,
0231             struct idp_led, cdev);
0232 
0233     return (IDP_CPLD_LED_CONTROL & led->mask) ? LED_OFF : LED_FULL;
0234 }
0235 
0236 static int __init idp_leds_init(void)
0237 {
0238     int i;
0239 
0240     if (!machine_is_pxa_idp())
0241         return -ENODEV;
0242 
0243     for (i = 0; i < ARRAY_SIZE(idp_leds); i++) {
0244         struct idp_led *led;
0245 
0246         led = kzalloc(sizeof(*led), GFP_KERNEL);
0247         if (!led)
0248             break;
0249 
0250         led->cdev.name = idp_leds[i].name;
0251         led->cdev.brightness_set = idp_led_set;
0252         led->cdev.brightness_get = idp_led_get;
0253         led->cdev.default_trigger = idp_leds[i].trigger;
0254 
0255         if (i == 0)
0256             led->mask = IDP_HB_LED;
0257         else
0258             led->mask = IDP_BUSY_LED;
0259 
0260         if (led_classdev_register(NULL, &led->cdev) < 0) {
0261             kfree(led);
0262             break;
0263         }
0264     }
0265 
0266     return 0;
0267 }
0268 
0269 /*
0270  * Since we may have triggers on any subsystem, defer registration
0271  * until after subsystem_init.
0272  */
0273 fs_initcall(idp_leds_init);
0274 #endif
0275 
0276 MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")
0277     /* Maintainer: Vibren Technologies */
0278     .map_io     = idp_map_io,
0279     .nr_irqs    = PXA_NR_IRQS,
0280     .init_irq   = pxa25x_init_irq,
0281     .handle_irq = pxa25x_handle_irq,
0282     .init_time  = pxa_timer_init,
0283     .init_machine   = idp_init,
0284     .restart    = pxa_restart,
0285 MACHINE_END