2 * linux/arch/arm/mach-sa1100/jornada720.c
5 #include <linux/init.h>
6 #include <linux/kernel.h>
8 #include <linux/delay.h>
9 #include <linux/platform_device.h>
10 #include <linux/ioport.h>
11 #include <linux/mtd/mtd.h>
12 #include <linux/mtd/partitions.h>
14 #include <asm/hardware.h>
15 #include <asm/hardware/sa1111.h>
17 #include <asm/mach-types.h>
18 #include <asm/setup.h>
19 #include <asm/arch/jornada720.h>
22 #include <asm/mach/arch.h>
23 #include <asm/mach/flash.h>
24 #include <asm/mach/map.h>
25 #include <asm/mach/serial_sa1100.h>
26 #include <asm/mach/flash.h>
27 #include <asm/mach/irda.h>
29 #include <linux/lcd.h>
30 #include <linux/backlight.h>
35 #ifdef CONFIG_SA1100_JORNADA720_FLASH
36 static unsigned char *pRegs
= REGISTER_OFFSET
;
37 void e1356fb_init_hardware(void);
40 /***********************************
42 * Jornada 720 mcu functions *
44 ***********************************/
46 static char mcu_invert
[256];
48 void jornada720_init_ser(void)
58 while (Ser4SSSR
& SSSR_RNE
)
62 int mcu_byte(int arg_data
)
66 while ((Ser4SSSR
& SSSR_TNF
) == 0);
68 while ((GPLR
& 0x400) && i
++ < 400000)
71 printk("mcu_byte: timed out\n");
74 Ser4SSDR
= mcu_invert
[arg_data
] << 8;
76 while ((Ser4SSSR
& SSSR_RNE
) == 0);
79 printk("mcu_byte: read %x\n", i
);
80 return mcu_invert
[ i
& 0xff ] & 0xff;
83 int mcu_start(int arg_data
)
87 jornada720_mcu_init();
88 GPCR
= GPIO_GPIO25
; /* clear -> enable */
90 i
= mcu_byte(arg_data
);
93 printk("mcu_start: sent %x got %x\n", arg_data
, i
);
94 for (i
= 0; i
< 256; i
++)
97 jornada720_init_ser();
106 GPSR
= GPIO_GPIO25
; /* set */
109 void jornada720_mcu_init(void)
112 static int initialized
= 0;
121 /* Take the MCU out of reset mode */
124 for (i
= 0; i
<= 255; i
++)
125 mcu_invert
[i
] = ( ((0x80 & i
) >> 7) | ((0x40 & i
) >> 5)
126 | ((0x20 & i
) >> 3) | ((0x10 & i
) >> 1) | ((0x08 & i
) << 1)
127 | ((0x04 & i
) << 3) | ((0x02 & i
) << 5) | ((0x01 & i
) << 7) );
129 GPSR
= GPIO_GPIO25
; /* set */
130 GPDR
|= GPIO_GPIO25
; /* GPIO(25) low -> enable MCU */
133 Ser4SSSR
= 0; /* remove any rcv overrun errors */
137 while (Ser4SSSR
& SSSR_RNE
)
138 i
= Ser4SSDR
; /* drain any data already there */
141 /***********************************
143 * Jornada 720 screen controls *
145 ***********************************/
147 static int jornada720_lcd_set_power(struct lcd_device
*ld
, int state
)
159 static int jornada720_lcd_get_contrast(struct lcd_device
*ld
)
162 mcu_start(MCU_GetContrast
);
163 contrast
= mcu_read();
168 static int jornada720_lcd_set_contrast(struct lcd_device
*ld
, int contrast
)
170 mcu_start(MCU_SetContrast
);
176 static int jornada720_backlight_get_brightness (struct backlight_device
*bd
)
179 mcu_start(MCU_GetBrightness
);
180 brightness
= mcu_read();
185 static int jornada720_backlight_set_brightness (struct backlight_device
*bd
, int value
)
187 int brightness
= 255 - value
; /* brightness hack for the user environments */
188 mcu_start(MCU_SetBrightness
);
189 mcu_byte(brightness
); /* range is from 0 (brightest) to 255 (darkest) */
195 static struct backlight_properties jornada720_backlight_properties
= {
196 .owner
= THIS_MODULE
,
197 .get_brightness
= jornada720_backlight_get_brightness
,
198 .set_brightness
= jornada720_backlight_set_brightness
,
199 .max_brightness
= 255,
202 static struct lcd_properties jornada720_lcd_properties
= {
203 .owner
= THIS_MODULE
,
204 .set_power
= jornada720_lcd_set_power
,
205 .set_contrast
= jornada720_lcd_set_contrast
,
206 .get_contrast
= jornada720_lcd_get_contrast
,
210 /***********************************
214 ***********************************/
216 static int jornada720_irda_set_power(struct device
*dev
, unsigned int state
)
228 static struct irda_platform_data jornada720_irda_data
= {
229 .set_power
= jornada720_irda_set_power
,
232 #ifdef CONFIG_SA1100_JORNADA720_FLASH
233 /***********************************
235 * Jornada 720 system flash *
237 ***********************************/
239 static struct mtd_partition jornada720_partitions
[] = {
244 .mask_flags
= MTD_WRITEABLE
,
247 .size
= MTDPART_SIZ_FULL
,
248 .offset
= MTDPART_OFS_APPEND
,
252 static void jornada720_set_vpp(int vpp
)
261 static struct flash_platform_data jornada720_flash_data
= {
262 .map_name
= "cfi_probe",
263 .parts
= jornada720_partitions
,
264 .nr_parts
= ARRAY_SIZE(jornada720_partitions
),
265 .set_vpp
= jornada720_set_vpp
,
268 static struct resource jornada720_flash_resource
= {
269 .start
= SA1100_CS0_PHYS
,
270 .end
= SA1100_CS0_PHYS
+ SZ_32M
- 1,
271 .flags
= IORESOURCE_MEM
,
275 /***********************************
277 * Jornada 720 apm functions *
279 ***********************************/
281 typedef void (*apm_get_power_status_t
)(struct apm_power_info
*);
283 static void jornada720_apm_get_power_status(struct apm_power_info
* info
)
286 mcu_start(MCU_GetBatteryData
);
287 value
[0] = mcu_read();
288 value
[1] = mcu_read();
289 value
[2] = mcu_read();
292 value
[0] |= (value
[2] & 3) << 8; /* main battery value */
293 value
[1] |= (value
[2] & 0xc) << 6; /* backup battery value, unused currently */
295 info
->battery_life
= ((value
[0] - 430) * 10) / 23; /* to get an accurate 100% - 0% range */
297 if (GPLR
& GPIO_GPIO4
) /* AC line status connected to GPIO4; 1 == Battery, 0 == AC */
298 info
->ac_line_status
= APM_AC_OFFLINE
;
300 info
->ac_line_status
= APM_AC_ONLINE
;
302 if (!(GPLR
& GPIO_GPIO26
)) /* Battery status connected to GPIO26; 0 == charging, 1 == not charging */
303 info
->battery_status
= APM_BATTERY_STATUS_CHARGING
;
305 info
->battery_status
= 2 - info
->battery_life
/ 36; /* this fits quite well */
310 int set_apm_get_power_status( apm_get_power_status_t t
)
312 apm_get_power_status
= t
;
316 static int jornada720_probe(struct device
*dev
)
318 #ifdef CONFIG_SA1100_JORNADA720_FLASH
319 sa11x0_set_flash_data(&jornada720_flash_data
, &jornada720_flash_resource
, 1); //set flash data
322 jornada720_mcu_init(); /* initialize the mcu... */
324 jornada720_lcd_set_contrast(0, 115); /* initial contrast setting */
326 backlight_device_register("e1356fb", 0, &jornada720_backlight_properties
);
327 lcd_device_register("e1356fb", 0, &jornada720_lcd_properties
);
329 set_apm_get_power_status(jornada720_apm_get_power_status
); /* apm handler */
331 sa11x0_set_irda_data(&jornada720_irda_data
);
336 #ifdef CONFIG_SA1100_JORNADA720_FLASH
337 struct pm_save_data
{
342 static int jornada720_suspend(struct device
*dev
, u32 state
, u32 level
)
344 struct pm_save_data
*save
;
346 if ( level
!= SUSPEND_DISABLE
)
349 save
= kmalloc(sizeof(struct pm_save_data
), GFP_KERNEL
);
352 dev
->power
.saved_state
= save
;
354 /* disable keyboard and mouse irq as they would kill the whole suspend/resume cycle */
355 disable_irq(GPIO_JORNADA720_KEYBOARD_IRQ
);
356 disable_irq(GPIO_JORNADA720_MOUSE_IRQ
);
358 PPSR
|= PPC_L_FCLK
; /* make sure the mcu is not being reset */
360 /* save current contrast and brightness */
361 save
->contrast
= jornada720_lcd_get_contrast(0);
362 save
->brightness
= jornada720_backlight_get_brightness(0);
364 pRegs
[0x1F0] = 1; /* put framebuffer into zZz */
369 static int jornada720_resume(struct device
*dev
, u32 level
)
371 struct pm_save_data
*save
;
373 if (level
!= RESUME_ENABLE
)
376 save
= (struct pm_save_data
*)dev
->power
.saved_state
;
380 GPSR
= GPIO_GPIO8
; /* reenable the rs232 receiver */
381 e1356fb_init_hardware(); /* wake up the framebuffer */
382 jornada720_init_ser(); /* reinitialize the mcu */
384 /* restore saved contrast and brightness */
385 jornada720_lcd_set_contrast(0,save
->contrast
);
386 jornada720_backlight_set_brightness(0,save
->brightness
);
388 TUCR
= JORTUCR_VAL
; /* this gets lost during zZz */
390 /* now reenable keyboard and mouse irq */
391 enable_irq(GPIO_JORNADA720_KEYBOARD_IRQ
);
392 enable_irq(GPIO_JORNADA720_MOUSE_IRQ
);
397 #define jornada720_suspend NULL
398 #define jornada720_resume NULL
401 static struct device_driver jornada720_driver
= {
402 .name
= "jornada720",
403 .bus
= &platform_bus_type
,
404 .probe
= jornada720_probe
,
405 .suspend
= jornada720_suspend
,
406 .resume
= jornada720_resume
,
409 /***********************************
411 * Jornada 720 system functions *
413 ***********************************/
415 static struct platform_device jornada720_device
= {
416 .name
= "jornada720",
420 static struct resource sa1111_resources
[] = {
424 .flags
= IORESOURCE_MEM
,
429 .flags
= IORESOURCE_IRQ
,
433 static u64 sa1111_dmamask
= 0xffffffffUL
;
435 static struct platform_device sa1111_device
= {
439 .dma_mask
= &sa1111_dmamask
,
440 .coherent_dma_mask
= 0xffffffff,
442 .num_resources
= ARRAY_SIZE(sa1111_resources
),
443 .resource
= sa1111_resources
,
446 static struct platform_device
*devices
[] __initdata
= {
451 static void __init
jornada720_init(void)
454 if (machine_is_jornada720()) {
456 TUCR
= JORTUCR_VAL
; /* set the oscillator out to the SA-1101 */
465 platform_add_devices(devices
, ARRAY_SIZE(devices
));
467 driver_register(&jornada720_driver
);
471 static struct map_desc jornada720_io_desc
[] __initdata
= {
472 { /* Epson registers */
473 .virtual = 0xf0000000,
474 .pfn
= __phys_to_pfn(0x48000000),
475 .length
= 0x00100000,
477 }, { /* Epson frame buffer */
478 .virtual = 0xf1000000,
479 .pfn
= __phys_to_pfn(0x48200000),
480 .length
= 0x00100000,
483 .virtual = 0xf4000000,
484 .pfn
= __phys_to_pfn(0x40000000),
485 .length
= 0x00100000,
490 static void __init
jornada720_map_io(void)
493 iotable_init(jornada720_io_desc
, ARRAY_SIZE(jornada720_io_desc
));
495 sa1100_register_uart(0, 3);
496 sa1100_register_uart(1, 1);
498 /* configure suspend conditions */
504 PGSR
|= GPIO_GPIO20
; /* preserve GPIO for the sa1111 */
505 PWER
|= GPIO_JORNADA720_KEYBOARD
| PWER_RTC
;
507 PSDR
|= PPC_L_FCLK
; /* make sure not to reset the mcu */
510 MACHINE_START(JORNADA720
, "HP Jornada 720")
511 /* Maintainer: Alex Lange - chicken@handhelds.org */
512 .phys_ram
= 0xc0000000,
513 .phys_io
= 0x80000000,
514 .io_pg_offst
= ((0xf8000000) >> 18) & 0xfffc,
515 .boot_params
= 0xc0000100,
516 .map_io
= jornada720_map_io
,
517 .init_irq
= sa1100_init_irq
,
518 .timer
= &sa1100_timer
,
519 .init_machine
= jornada720_init
,