diff --git a/arch/arm/config.in b/arch/arm/config.in index 1aae024f83f0b330bab9ce9cfac7b98bec11229a..635874b18bfc2aee98caed4bf12e3fc27d3e560c 100644 --- a/arch/arm/config.in +++ b/arch/arm/config.in @@ -335,6 +335,16 @@ hex 'Compressed ROM boot loader BSS address' CONFIG_ZBOOT_ROM_BSS 0 if [ "$CONFIG_ARCH_SA1100" = "y" -o \ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then dep_bool 'Support CPU clock change (EXPERIMENTAL)' CONFIG_CPU_FREQ $CONFIG_EXPERIMENTAL +else + define_bool CONFIG_CPU_FREQ n +fi + +if [ "$CONFIG_CPU_FREQ" = "y" ]; then + define_bool CONFIG_CPU_FREQ_24_API y + define_bool CONFIG_CPU_FREQ_26_API y +else + define_bool CONFIG_CPU_FREQ_24_API n + define_bool CONFIG_CPU_FREQ_26_API n fi source drivers/pci/Config.in diff --git a/arch/arm/kernel/compat.c b/arch/arm/kernel/compat.c index 8fd9632d0c08cf601abb295de53dd949d741df32..7195add42e74cab407e4478743993246b04a62ee 100644 --- a/arch/arm/kernel/compat.c +++ b/arch/arm/kernel/compat.c @@ -95,13 +95,14 @@ static void __init build_tag_list(struct param_struct *params, void *taglist) { struct tag *tag = taglist; - printk(KERN_DEBUG "Converting old-style param struct to taglist\n"); - if (params->u1.s.page_size != PAGE_SIZE) { printk(KERN_WARNING "Warning: bad configuration page, " "trying to continue\n"); return; } + + printk(KERN_DEBUG "Converting old-style param struct to taglist\n"); + #ifdef CONFIG_ARCH_NETWINDER if (params->u1.s.nr_pages != 0x02000 && params->u1.s.nr_pages != 0x04000 && diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 73a253c6fe6ec10a156e5c16d24857ae087ab978..399d81bf412a36fa6b2a7d743d7c09e77104cc8f 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -569,7 +569,7 @@ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *) * On a shared IRQ the caller must ensure the interrupt is disabled * on the card it drives before calling this function. * - * This function may be called from interrupt context. + * This function must not be called from interrupt context. */ void free_irq(unsigned int irq, void *dev_id) { @@ -591,15 +591,19 @@ void free_irq(unsigned int irq, void *dev_id) /* Found it - now free it */ *p = action->next; - kfree(action); - goto out; + break; } - printk(KERN_ERR "Trying to free free IRQ%d\n",irq); + spin_unlock_irqrestore(&irq_controller_lock, flags); + + if (!action) { + printk(KERN_ERR "Trying to free free IRQ%d\n",irq); #ifdef CONFIG_DEBUG_ERRORS - __backtrace(); + __backtrace(); #endif -out: - spin_unlock_irqrestore(&irq_controller_lock, flags); + } else { + synchronize_irq(irq); + kfree(action); + } } /* Start the interrupt probing. Unlike other architectures, diff --git a/arch/arm/mach-sa1100/adsbitsy.c b/arch/arm/mach-sa1100/adsbitsy.c index b0c97a9b7b8e87aab0e5c06ea336cb93f119ff08..d5eb9b67744921cafee1f25842269a2833304cb2 100644 --- a/arch/arm/mach-sa1100/adsbitsy.c +++ b/arch/arm/mach-sa1100/adsbitsy.c @@ -28,7 +28,6 @@ #include <asm/mach/serial_sa1100.h> #include "generic.h" -#include "sa1111.h" static int __init adsbitsy_init(void) { @@ -53,7 +52,7 @@ static int __init adsbitsy_init(void) /* * Probe for SA1111. */ - ret = sa1111_init(NULL, 0x18000000, IRQ_GPIO0); + ret = sa1111_init(0x18000000, IRQ_GPIO0); if (ret < 0) return ret; diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c index aace82ac1870b40e8c70a36a560ff01f17c22369..6136ee54c4730ca8ecd2ed628c9d33817daa39c3 100644 --- a/arch/arm/mach-sa1100/badge4.c +++ b/arch/arm/mach-sa1100/badge4.c @@ -32,7 +32,6 @@ #include <asm/mach/serial_sa1100.h> #include "generic.h" -#include "sa1111.h" static int __init badge4_sa1111_init(void) { @@ -45,7 +44,7 @@ static int __init badge4_sa1111_init(void) /* * Probe for SA1111. */ - return sa1111_init(NULL, BADGE4_SA1111_BASE, BADGE4_IRQ_GPIO_SA1111); + return sa1111_init(BADGE4_SA1111_BASE, BADGE4_IRQ_GPIO_SA1111); } static int __init badge4_init(void) diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c index e587cf543608119a0fea1a7c13af3e1861d23632..64295a0fbe562bc0cb3762c454cf436416f2d70c 100644 --- a/arch/arm/mach-sa1100/cpu-sa1100.c +++ b/arch/arm/mach-sa1100/cpu-sa1100.c @@ -90,9 +90,7 @@ #include <asm/hardware.h> -extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz); -extern unsigned int sa11x0_validatespeed(unsigned int cpu, unsigned int khz); -extern unsigned int sa11x0_getspeed(void); +#include "generic.h" typedef struct { int speed; @@ -107,7 +105,7 @@ typedef struct { static sa1100_dram_regs_t sa1100_dram_settings[] = { - /* { mdcnfg, mdcas0, mdcas1, mdcas2 } */ /* clock frequency */ + /* speed, mdcnfg, mdcas0, mdcas1, mdcas2 clock frequency */ { 59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 59.0 MHz */ { 73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 73.7 MHz */ { 88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 88.5 MHz */ @@ -127,28 +125,25 @@ static sa1100_dram_regs_t sa1100_dram_settings[] = { 0, 0, 0, 0, 0 } /* last entry */ }; - - - static void sa1100_update_dram_timings(int current_speed, int new_speed) { sa1100_dram_regs_t *settings = sa1100_dram_settings; /* find speed */ - while(settings->speed != 0) { + while (settings->speed != 0) { if(new_speed == settings->speed) break; settings++; } - if(settings->speed == 0) { + if (settings->speed == 0) { panic("%s: couldn't find dram setting for speed %d\n", __FUNCTION__, new_speed); } /* No risk, no fun: run with interrupts on! */ - if(new_speed > current_speed) { + if (new_speed > current_speed) { /* We're going FASTER, so first relax the memory * timings before changing the core frequency */ @@ -181,60 +176,39 @@ static void sa1100_update_dram_timings(int current_speed, int new_speed) } } - - - -static int sa1100_dram_notifier(struct notifier_block *nb, - unsigned long val, void *data) +static void sa1100_setspeed(struct cpufreq_policy *policy) { - struct cpufreq_freqs *ci = data; - - switch(val) { - case CPUFREQ_MINMAX: - cpufreq_updateminmax(data, sa1100_dram_settings->speed, -1); - break; + unsigned int cur = sa11x0_getspeed(); + struct cpufreq_freqs freqs; - case CPUFREQ_PRECHANGE: - if(ci->new > ci->cur) - sa1100_update_dram_timings(ci->cur, ci->new); - break; + freqs.old = cur; + freqs.new = policy->max; + freqs.cpu = CPUFREQ_ALL_CPUS; - case CPUFREQ_POSTCHANGE: - if(ci->new < ci->cur) - sa1100_update_dram_timings(ci->cur, ci->new); - break; - - default: - printk(KERN_INFO "%s: ignoring unknown notifier type (%ld)\n", - __FUNCTION__, val); - } - - return 0; -} + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + if (policy->max > cur) + sa1100_update_dram_timings(cur, policy->max); + PPCR = sa11x0_freq_to_ppcr(policy->max); + if (policy->max < cur) + sa1100_update_dram_timings(cur, policy->max); -static struct notifier_block sa1100_dram_block = { - .notifier_call = sa1100_dram_notifier, -}; - - -static void sa1100_setspeed(unsigned int cpu, unsigned int khz) -{ - PPCR = sa11x0_freq_to_ppcr(khz); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); } -static struct cpufreq_freqs sa1100_freqs = { - .min = 59000, - .max = 287000, +static struct cpufreq_policy sa1100_policy = { + .cpu = 0, + .policy = CPUFREQ_POLICY_POWERSAVE, + .max_cpu_freq = 287000, }; static struct cpufreq_driver sa1100_driver = { - .freq = &sa1100_freqs, - .validate = sa11x0_validatespeed, - .setspeed = sa1100_setspeed, - .sync = 1, + .verify = sa11x0_verify_speed, + .setpolicy = sa1100_setspeed, + .policy = &sa1100_policy, + .cpu_min_freq = 59000, }; static int __init sa1100_dram_init(void) @@ -242,11 +216,9 @@ static int __init sa1100_dram_init(void) int ret = -ENODEV; if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID) { - ret = cpufreq_register_notifier(&sa1100_dram_block); - if (ret) - return ret; - - sa1100_freqs.cur = sa11x0_getspeed(); + sa1100_driver.cpu_curr_freq[0] = + sa1100_policy.min = + sa1100_policy.max = sa11x0_getspeed(); ret = cpufreq_register(&sa1100_driver); } diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c index 0a9777f732d0892df175382f5d1db3b01cca7421..ee0b097fc2a839674737338cc1449a62b1897008 100644 --- a/arch/arm/mach-sa1100/cpu-sa1110.c +++ b/arch/arm/mach-sa1100/cpu-sa1110.c @@ -28,11 +28,9 @@ #include <asm/io.h> #include <asm/system.h> -#undef DEBUG +#include "generic.h" -extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz); -extern unsigned int sa11x0_validatespeed(unsigned int cpu, unsigned int khz); -extern unsigned int sa11x0_getspeed(void); +#undef DEBUG struct sdram_params { u_char rows; /* bits */ @@ -214,15 +212,16 @@ sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram) * above, we can match for an exact frequency. If we don't find * an exact match, we will to set the lowest frequency to be safe. */ -static void sa1110_setspeed(unsigned int cpu, unsigned int khz) +static void sa1110_setspeed(struct cpufreq_policy *policy) { struct sdram_params *sdram = &sdram_params; + struct cpufreq_freqs freqs; struct sdram_info sd; unsigned long flags; unsigned int ppcr, unused; - ppcr = sa11x0_freq_to_ppcr(khz); - sdram_calculate_timing(&sd, khz, sdram); + ppcr = sa11x0_freq_to_ppcr(policy->max); + sdram_calculate_timing(&sd, policy->max, sdram); #if 0 /* @@ -230,7 +229,7 @@ static void sa1110_setspeed(unsigned int cpu, unsigned int khz) * and errata, but they seem to work. Need to get a storage * scope on to the SDRAM signals to work out why. */ - if (khz < 147500) { + if (policy->max < 147500) { sd.mdrefr |= MDREFR_K1DB2; sd.mdcas[0] = 0xaaaaaa7f; } else { @@ -240,6 +239,13 @@ static void sa1110_setspeed(unsigned int cpu, unsigned int khz) sd.mdcas[1] = 0xaaaaaaaa; sd.mdcas[2] = 0xaaaaaaaa; #endif + + freqs.old = sa11x0_getspeed(); + freqs.new = policy->max; + freqs.cpu = CPUFREQ_ALL_CPUS; + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + /* * The clock could be going away for some time. Set the SDRAMs * to refresh rapidly (every 64 memory clock cycles). To get @@ -257,7 +263,7 @@ static void sa1110_setspeed(unsigned int cpu, unsigned int khz) * the programming. */ local_irq_save(flags); - asm("mcr p15, 0, %0, c10, c4" : : "r" (0)); + asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); udelay(10); __asm__ __volatile__(" b 2f @@ -282,19 +288,22 @@ static void sa1110_setspeed(unsigned int cpu, unsigned int khz) /* * Now, return the SDRAM refresh back to normal. */ - sdram_update_refresh(khz, sdram); + sdram_update_refresh(policy->max, sdram); + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); } -static struct cpufreq_freqs sa1110_freqs = { - .min = 59000, - .max = 287000, +static struct cpufreq_policy sa1110_policy = { + .cpu = 0, + .policy = CPUFREQ_POLICY_POWERSAVE, + .max_cpu_freq = 287000, }; static struct cpufreq_driver sa1110_driver = { - .freq = &sa1110_freqs, - .validate = sa11x0_validatespeed, - .setspeed = sa1110_setspeed, - .sync = 1, + .verify = sa11x0_verify_speed, + .setpolicy = sa1110_setspeed, + .policy = &sa1110_policy, + .cpu_min_freq = 59000, }; static int __init sa1110_clk_init(void) @@ -318,8 +327,11 @@ static int __init sa1110_clk_init(void) memcpy(&sdram_params, sdram, sizeof(sdram_params)); - sa1110_freqs.cur = sa11x0_getspeed(); - sa1110_setspeed(0, sa1110_freqs.cur); + sa1110_driver.cpu_cur_freq[0] = + sa1110_policy.min = + sa1110_policy.max = sa11x0_getspeed(); + + sa1110_setspeed(&sa1110_policy); return cpufreq_register(&sa1110_driver); } diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index ad06a06c84f520b27138c42096fb3325fabb0372..45eae6434f6849f8107b0283b58dc950fc8857e2 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -55,20 +55,26 @@ unsigned int sa11x0_freq_to_ppcr(unsigned int khz) khz /= 100; - for (i = NR_FREQS - 1; i > 0; i--) - if (cclk_frequency_100khz[i] <= khz) + for (i = 0; i < ARRAY_SIZE(cclk_frequency_100khz); i--) + if (cclk_frequency_100khz[i] >= khz) break; return i; } /* - * Validate the speed in khz. If we can't generate the precise - * frequency requested, round it down (to be on the safe side). + * Validate the policy. We aren't able to do any fancy in-kernel + * scaling, so we force min=max, and set the policy to "performance". + * If we can't generate the precise frequency requested, round it up. */ -unsigned int sa11x0_validatespeed(unsigned int cpu, unsigned int khz) +void sa11x0_verify_speed(struct cpufreq_policy *policy) { - return cclk_frequency_100khz[sa11x0_freq_to_ppcr(khz)] * 100; + if (policy->max > policy->max_cpu_freq) + policy->max = policy->max_cpu_freq; + + policy->max = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->max)] * 100; + policy->min = policy->max; + policy->policy = CPUFREQ_POLICY_POWERSAVE; } unsigned int sa11x0_getspeed(void) diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h index abb28817b275017f22fdd3003e139dbe35eb3d26..6a27b9b7e715ab71ce349e54e6686b9b27b0ee45 100644 --- a/arch/arm/mach-sa1100/generic.h +++ b/arch/arm/mach-sa1100/generic.h @@ -17,3 +17,9 @@ extern void (*sa1100fb_lcd_power)(int on); extern void sa1110_mb_enable(void); extern void sa1110_mb_disable(void); + +struct cpufreq_policy; + +extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz); +extern void sa11x0_verify_speed(struct cpufreq_policy *policy); +extern unsigned int sa11x0_getspeed(void); diff --git a/arch/arm/mach-sa1100/graphicsmaster.c b/arch/arm/mach-sa1100/graphicsmaster.c index 9600b3e620b5c824b8dddbbd45218bb3dc8c08c7..d3eddf63205e00db84d6b2cf95fdcfd346d4e145 100644 --- a/arch/arm/mach-sa1100/graphicsmaster.c +++ b/arch/arm/mach-sa1100/graphicsmaster.c @@ -25,7 +25,6 @@ #include <asm/mach/serial_sa1100.h> #include "generic.h" -#include "sa1111.h" static int __init graphicsmaster_init(void) { @@ -43,7 +42,7 @@ static int __init graphicsmaster_init(void) /* * Probe for SA1111. */ - ret = sa1111_init(NULL, 0x18000000, ADS_EXT_IRQ(0)); + ret = sa1111_init(0x18000000, ADS_EXT_IRQ(0)); if (ret < 0) return ret; diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c index 0881cc01ad2551ef83fe9f18459e744dd78292b2..41e19e37d0c06f6cf22493808a8fc5d45c34f500 100644 --- a/arch/arm/mach-sa1100/h3600.c +++ b/arch/arm/mach-sa1100/h3600.c @@ -24,65 +24,171 @@ #include <linux/kernel.h> #include <linux/tty.h> #include <linux/sched.h> +#include <linux/pm.h> +#include <linux/serial_core.h> #include <asm/irq.h> #include <asm/hardware.h> #include <asm/mach-types.h> #include <asm/setup.h> +#include <asm/mach/irq.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/serial_sa1100.h> -#include <linux/serial_core.h> + +#include <asm/arch/h3600.h> + +#if defined (CONFIG_SA1100_H3600) || defined (CONFIG_SA1100_H3100) #include <asm/arch/h3600_gpio.h> +#endif + +#ifdef CONFIG_SA1100_H3800 +#include <asm/arch/h3600_asic.h> +#endif #include "generic.h" +struct ipaq_model_ops ipaq_model_ops; +EXPORT_SYMBOL(ipaq_model_ops); + +static void msleep(unsigned int msec) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((msec * HZ + 999) / 1000); +} + /* - * H3600 has extended, write-only memory-mapped GPIO's - * H3100 has 1/2 extended, write-only GPIO and 1/2 on - * regular GPIO lines. - * H3800 has memory-mapped GPIO through ASIC1 & 2 + * low-level UART features */ -#define H3600_EGPIO (*(volatile unsigned int *)H3600_EGPIO_VIRT) +static void h3600_uart_set_mctrl(struct uart_port *port, u_int mctrl) +{ + if (port->mapbase == _Ser3UTCR0) { + if (mctrl & TIOCM_RTS) + GPCR = GPIO_H3600_COM_RTS; + else + GPSR = GPIO_H3600_COM_RTS; + } +} -static unsigned int h3600_egpio; +static u_int h3600_uart_get_mctrl(struct uart_port *port) +{ + u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR; -/************************* H3100 *************************/ + if (port->mapbase == _Ser3UTCR0) { + int gplr = GPLR; + /* DCD and CTS bits are inverted in GPLR by RS232 transceiver */ + if (gplr & GPIO_H3600_COM_DCD) + ret &= ~TIOCM_CD; + if (gplr & GPIO_H3600_COM_CTS) + ret &= ~TIOCM_CTS; + } -#define H3100_DIRECT_EGPIO (GPIO_H3100_BT_ON \ - | GPIO_H3100_GPIO3 \ - | GPIO_H3100_QMUTE \ - | GPIO_H3100_LCD_3V_ON \ - | GPIO_H3100_AUD_ON \ - | GPIO_H3100_AUD_PWR_ON \ - | GPIO_H3100_IR_ON \ - | GPIO_H3100_IR_FSEL) + return ret; +} -static void h3100_init_egpio( void ) +static void h3600_uart_pm(struct uart_port *port, u_int state, u_int oldstate) { - GPDR |= H3100_DIRECT_EGPIO; - GPCR = H3100_DIRECT_EGPIO; /* Initially all off */ + if (port->mapbase == _Ser2UTCR0) { /* TODO: REMOVE THIS */ + assign_h3600_egpio(IPAQ_EGPIO_IR_ON, !state); + } else if (port->mapbase == _Ser3UTCR0) { + assign_h3600_egpio(IPAQ_EGPIO_RS232_ON, !state); + } +} - /* Older bootldrs put GPIO2-9 in alternate mode on the - assumption that they are used for video */ - GAFR &= ~H3100_DIRECT_EGPIO; +/* + * Enable/Disable wake up events for this serial port. + * Obviously, we only support this on the normal COM port. + */ +static int h3600_uart_set_wake(struct uart_port *port, u_int enable) +{ + int err = -EINVAL; + + if (port->mapbase == _Ser3UTCR0) { + if (enable) + PWER |= PWER_GPIO23 | PWER_GPIO25; /* DCD and CTS */ + else + PWER &= ~(PWER_GPIO23 | PWER_GPIO25); /* DCD and CTS */ + err = 0; + } + return err; +} + +static struct sa1100_port_fns h3600_port_fns __initdata = { + .set_mctrl = h3600_uart_set_mctrl, + .get_mctrl = h3600_uart_get_mctrl, + .pm = h3600_uart_pm, + .set_wake = h3600_uart_set_wake, +}; + +/* + * helper for sa1100fb + */ +static void h3xxx_lcd_power(int enable) +{ + assign_h3600_egpio(IPAQ_EGPIO_LCD_POWER, enable); +} + +static struct map_desc h3600_io_desc[] __initdata = { + /* virtual physical length type */ + { H3600_BANK_2_VIRT, SA1100_CS2_PHYS, 0x02800000, MT_DEVICE }, /* static memory bank 2 CS#2 */ + { H3600_BANK_4_VIRT, SA1100_CS4_PHYS, 0x00800000, MT_DEVICE }, /* static memory bank 4 CS#4 */ + { H3600_EGPIO_VIRT, H3600_EGPIO_PHYS, 0x01000000, MT_DEVICE }, /* EGPIO 0 CS#5 */ +}; + +/* + * Common map_io initialization + */ + +static void __init h3xxx_map_io(void) +{ + sa1100_map_io(); + iotable_init(h3600_io_desc, ARRAY_SIZE(h3600_io_desc)); + + sa1100_register_uart_fns(&h3600_port_fns); + sa1100_register_uart(0, 3); /* Common serial port */ +// sa1100_register_uart(1, 1); /* Microcontroller on 3100/3600 */ + + /* Ensure those pins are outputs and driving low */ + PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; + PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); + + /* Configure suspend conditions */ + PGSR = 0; + PWER = PWER_GPIO0 | PWER_RTC; + PCFR = PCFR_OPDE; + PSDR = 0; + + sa1100fb_lcd_power = h3xxx_lcd_power; +} - h3600_egpio = EGPIO_H3600_RS232_ON; - H3600_EGPIO = h3600_egpio; +static __inline__ void do_blank(int setp) +{ + if (ipaq_model_ops.blank_callback) + ipaq_model_ops.blank_callback(1-setp); } -static void h3100_control_egpio( enum ipaq_egpio_type x, int setp ) +/************************* H3100 *************************/ + +#ifdef CONFIG_SA1100_H3100 + +#define H3100_EGPIO (*(volatile unsigned int *)H3600_EGPIO_VIRT) +static unsigned int h3100_egpio = 0; + +static void h3100_control_egpio(enum ipaq_egpio_type x, int setp) { unsigned int egpio = 0; long gpio = 0; unsigned long flags; switch (x) { - case IPAQ_EGPIO_LCD_ON: + case IPAQ_EGPIO_LCD_POWER: egpio |= EGPIO_H3600_LCD_ON; gpio |= GPIO_H3100_LCD_3V_ON; + do_blank(setp); + break; + case IPAQ_EGPIO_LCD_ENABLE: break; case IPAQ_EGPIO_CODEC_NRESET: egpio |= EGPIO_H3600_CODEC_NRESET; @@ -120,66 +226,104 @@ static void h3100_control_egpio( enum ipaq_egpio_type x, int setp ) break; } - local_irq_save(flags); - if ( setp ) { - h3600_egpio |= egpio; - GPSR = gpio; - } else { - h3600_egpio &= ~egpio; - GPCR = gpio; - } - H3600_EGPIO = h3600_egpio; - local_irq_restore(flags); - - /* - if ( x != IPAQ_EGPIO_VPP_ON ) { - printk("%s: type=%d (%s) gpio=0x%x (0x%x) egpio=0x%x (0x%x) setp=%d\n", - __FUNCTION__, - x, egpio_names[x], GPLR, gpio, h3600_egpio, egpio, setp ); + if (egpio || gpio) { + local_irq_save(flags); + if (setp) { + h3100_egpio |= egpio; + GPSR = gpio; + } else { + h3100_egpio &= ~egpio; + GPCR = gpio; + } + H3100_EGPIO = h3100_egpio; + local_irq_restore(flags); } - */ } -static unsigned long h3100_read_egpio( void ) +static unsigned long h3100_read_egpio(void) { - return h3600_egpio; + return h3100_egpio; +} + +static int h3100_pm_callback(int req) +{ + if (ipaq_model_ops.pm_callback_aux) + return ipaq_model_ops.pm_callback_aux(req); + return 0; } static struct ipaq_model_ops h3100_model_ops __initdata = { - model : IPAQ_H3100, - generic_name : "3100", - initialize : h3100_init_egpio, - control : h3100_control_egpio, - read : h3100_read_egpio + .generic_name = "3100", + .control = h3100_control_egpio, + .read = h3100_read_egpio, + .pm_callback = h3100_pm_callback }; +#define H3100_DIRECT_EGPIO (GPIO_H3100_BT_ON \ + | GPIO_H3100_GPIO3 \ + | GPIO_H3100_QMUTE \ + | GPIO_H3100_LCD_3V_ON \ + | GPIO_H3100_AUD_ON \ + | GPIO_H3100_AUD_PWR_ON \ + | GPIO_H3100_IR_ON \ + | GPIO_H3100_IR_FSEL) -/************************* H3600 *************************/ - -static void h3600_init_egpio( void ) +static void __init h3100_map_io(void) { - h3600_egpio = EGPIO_H3600_RS232_ON; - H3600_EGPIO = h3600_egpio; + h3xxx_map_io(); + + /* Initialize h3100-specific values here */ + GPCR = 0x0fffffff; /* All outputs are set low by default */ + GPDR = GPIO_H3600_COM_RTS | GPIO_H3600_L3_CLOCK | + GPIO_H3600_L3_MODE | GPIO_H3600_L3_DATA | + GPIO_H3600_CLK_SET1 | GPIO_H3600_CLK_SET0 | + H3100_DIRECT_EGPIO; + + /* Older bootldrs put GPIO2-9 in alternate mode on the + assumption that they are used for video */ + GAFR &= ~H3100_DIRECT_EGPIO; + + H3100_EGPIO = h3100_egpio; + ipaq_model_ops = h3100_model_ops; } -static void h3600_control_egpio( enum ipaq_egpio_type x, int setp ) +MACHINE_START(H3100, "Compaq iPAQ H3100") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + BOOT_PARAMS(0xc0000100) + MAPIO(h3100_map_io) + INITIRQ(sa1100_init_irq) +MACHINE_END + +#endif /* CONFIG_SA1100_H3100 */ + +/************************* H3600 *************************/ + +#ifdef CONFIG_SA1100_H3600 + +#define H3600_EGPIO (*(volatile unsigned int *)H3600_EGPIO_VIRT) +static unsigned int h3600_egpio = EGPIO_H3600_RS232_ON; + +static void h3600_control_egpio(enum ipaq_egpio_type x, int setp) { unsigned int egpio = 0; unsigned long flags; switch (x) { - case IPAQ_EGPIO_LCD_ON: + case IPAQ_EGPIO_LCD_POWER: egpio |= EGPIO_H3600_LCD_ON | EGPIO_H3600_LCD_PCI | EGPIO_H3600_LCD_5V_ON | EGPIO_H3600_LVDD_ON; + do_blank(setp); + break; + case IPAQ_EGPIO_LCD_ENABLE: break; case IPAQ_EGPIO_CODEC_NRESET: egpio |= EGPIO_H3600_CODEC_NRESET; break; case IPAQ_EGPIO_AUDIO_ON: egpio |= EGPIO_H3600_AUD_AMP_ON | - EGPIO_H3600_AUD_PWR_ON; + EGPIO_H3600_AUD_PWR_ON; break; case IPAQ_EGPIO_QMUTE: egpio |= EGPIO_H3600_QMUTE; @@ -210,288 +354,441 @@ static void h3600_control_egpio( enum ipaq_egpio_type x, int setp ) break; } - local_irq_save(flags); - if ( setp ) - h3600_egpio |= egpio; - else - h3600_egpio &= ~egpio; - H3600_EGPIO = h3600_egpio; - local_irq_restore(flags); + if (egpio) { + local_irq_save(flags); + if (setp) + h3600_egpio |= egpio; + else + h3600_egpio &= ~egpio; + H3600_EGPIO = h3600_egpio; + local_irq_restore(flags); + } } -static unsigned long h3600_read_egpio( void ) +static unsigned long h3600_read_egpio(void) { return h3600_egpio; } +static int h3600_pm_callback(int req) +{ + if (ipaq_model_ops.pm_callback_aux) + return ipaq_model_ops.pm_callback_aux(req); + return 0; +} + static struct ipaq_model_ops h3600_model_ops __initdata = { - model : IPAQ_H3600, - generic_name : "3600", - initialize : h3600_init_egpio, - control : h3600_control_egpio, - read : h3600_read_egpio + .generic_name = "3600", + .control = h3600_control_egpio, + .read = h3600_read_egpio, + .pm_callback = h3600_pm_callback }; -/************************* H3800 *************************/ +static void __init h3600_map_io(void) +{ + h3xxx_map_io(); -#define ASIC1_OUTPUTS 0x7fff /* First 15 bits are used */ + /* Initialize h3600-specific values here */ -static unsigned int h3800_asic1_gpio; -static unsigned int h3800_asic2_gpio; + GPCR = 0x0fffffff; /* All outputs are set low by default */ + GPDR = GPIO_H3600_COM_RTS | GPIO_H3600_L3_CLOCK | + GPIO_H3600_L3_MODE | GPIO_H3600_L3_DATA | + GPIO_H3600_CLK_SET1 | GPIO_H3600_CLK_SET0 | + GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 | + GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8; -static void h3800_init_egpio(void) -{ - /* Set up ASIC #1 */ - H3800_ASIC1_GPIO_Direction = ASIC1_OUTPUTS; /* All outputs */ - H3800_ASIC1_GPIO_Mask = ASIC1_OUTPUTS; /* No interrupts */ - H3800_ASIC1_GPIO_SleepMask = ASIC1_OUTPUTS; - H3800_ASIC1_GPIO_SleepDir = ASIC1_OUTPUTS; - H3800_ASIC1_GPIO_SleepOut = GPIO_H3800_ASIC1_EAR_ON_N; - H3800_ASIC1_GPIO_BattFaultDir = ASIC1_OUTPUTS; - H3800_ASIC1_GPIO_BattFaultOut = GPIO_H3800_ASIC1_EAR_ON_N; + H3600_EGPIO = h3600_egpio; /* Maintains across sleep? */ + ipaq_model_ops = h3600_model_ops; +} + +MACHINE_START(H3600, "Compaq iPAQ H3600") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + BOOT_PARAMS(0xc0000100) + MAPIO(h3600_map_io) + INITIRQ(sa1100_init_irq) +MACHINE_END - h3800_asic1_gpio = GPIO_H3800_ASIC1_IR_ON_N /* TODO: Check IR level */ - | GPIO_H3800_ASIC1_RS232_ON - | GPIO_H3800_ASIC1_EAR_ON_N; +#endif /* CONFIG_SA1100_H3600 */ - H3800_ASIC1_GPIO_Out = h3800_asic1_gpio; +#ifdef CONFIG_SA1100_H3800 - /* Set up ASIC #2 */ - H3800_ASIC2_GPIO_Direction = GPIO_H3800_ASIC2_PEN_IRQ - | GPIO_H3800_ASIC2_SD_DETECT - | GPIO_H3800_ASIC2_EAR_IN_N - | GPIO_H3800_ASIC2_USB_DETECT_N - | GPIO_H3800_ASIC2_SD_CON_SLT; +#define SET_ASIC1(x) \ + do {if (setp) { H3800_ASIC1_GPIO_OUT |= (x); } else { H3800_ASIC1_GPIO_OUT &= ~(x); }} while(0) - h3800_asic2_gpio = GPIO_H3800_ASIC2_IN_Y1_N | GPIO_H3800_ASIC2_IN_X1_N; - H3800_ASIC2_GPIO_Data = h3800_asic2_gpio; - H3800_ASIC2_GPIO_BattFaultOut = h3800_asic2_gpio; +#define SET_ASIC2(x) \ + do {if (setp) { H3800_ASIC2_GPIOPIOD |= (x); } else { H3800_ASIC2_GPIOPIOD &= ~(x); }} while(0) - /* TODO : Set sleep states & battery fault states */ +#define CLEAR_ASIC1(x) \ + do {if (setp) { H3800_ASIC1_GPIO_OUT &= ~(x); } else { H3800_ASIC1_GPIO_OUT |= (x); }} while(0) - /* Clear VPP Enable */ - H3800_ASIC1_FlashWP_VPP_ON = 0; +#define CLEAR_ASIC2(x) \ + do {if (setp) { H3800_ASIC2_GPIOPIOD &= ~(x); } else { H3800_ASIC2_GPIOPIOD |= (x); }} while(0) + + +/* + On screen enable, we get + + h3800_video_power_on(1) + LCD controller starts + h3800_video_lcd_enable(1) + + On screen disable, we get + + h3800_video_lcd_enable(0) + LCD controller stops + h3800_video_power_on(0) +*/ + + +static void h3800_video_power_on(int setp) +{ + if (setp) { + H3800_ASIC1_GPIO_OUT |= GPIO1_LCD_ON; + msleep(30); + H3800_ASIC1_GPIO_OUT |= GPIO1_VGL_ON; + msleep(5); + H3800_ASIC1_GPIO_OUT |= GPIO1_VGH_ON; + msleep(50); + H3800_ASIC1_GPIO_OUT |= GPIO1_LCD_5V_ON; + msleep(5); + } else { + msleep(5); + H3800_ASIC1_GPIO_OUT &= ~GPIO1_LCD_5V_ON; + msleep(50); + H3800_ASIC1_GPIO_OUT &= ~GPIO1_VGL_ON; + msleep(5); + H3800_ASIC1_GPIO_OUT &= ~GPIO1_VGH_ON; + msleep(100); + H3800_ASIC1_GPIO_OUT &= ~GPIO1_LCD_ON; + } } -static void h3800_control_egpio( enum ipaq_egpio_type x, int setp ) +static void h3800_video_lcd_enable(int setp) { - unsigned int set_asic1_egpio = 0; - unsigned int clear_asic1_egpio = 0; - unsigned long flags; + if (setp) { + msleep(17); // Wait one from before turning on + H3800_ASIC1_GPIO_OUT |= GPIO1_LCD_PCI; + } else { + H3800_ASIC1_GPIO_OUT &= ~GPIO1_LCD_PCI; + msleep(30); // Wait before turning off + } +} + +static void h3800_control_egpio(enum ipaq_egpio_type x, int setp) +{ switch (x) { - case IPAQ_EGPIO_LCD_ON: - set_asic1_egpio |= GPIO_H3800_ASIC1_LCD_5V_ON - | GPIO_H3800_ASIC1_LCD_ON - | GPIO_H3800_ASIC1_LCD_PCI - | GPIO_H3800_ASIC1_VGH_ON - | GPIO_H3800_ASIC1_VGL_ON; + case IPAQ_EGPIO_LCD_POWER: + h3800_video_power_on(setp); break; - case IPAQ_EGPIO_CODEC_NRESET: + case IPAQ_EGPIO_LCD_ENABLE: + h3800_video_lcd_enable(setp); break; + case IPAQ_EGPIO_CODEC_NRESET: case IPAQ_EGPIO_AUDIO_ON: - break; case IPAQ_EGPIO_QMUTE: + printk(__FUNCTION__ ": error - should not be called\n"); break; case IPAQ_EGPIO_OPT_NVRAM_ON: + SET_ASIC2(GPIO2_OPT_ON_NVRAM); break; case IPAQ_EGPIO_OPT_ON: + SET_ASIC2(GPIO2_OPT_ON); break; case IPAQ_EGPIO_CARD_RESET: + SET_ASIC2(GPIO2_OPT_PCM_RESET); break; case IPAQ_EGPIO_OPT_RESET: + SET_ASIC2(GPIO2_OPT_RESET); break; case IPAQ_EGPIO_IR_ON: - clear_asic1_egpio |= GPIO_H3800_ASIC1_IR_ON_N; /* TODO : This is backwards? */ + CLEAR_ASIC1(GPIO1_IR_ON_N); break; case IPAQ_EGPIO_IR_FSEL: break; case IPAQ_EGPIO_RS232_ON: - set_asic1_egpio |= GPIO_H3800_ASIC1_RS232_ON; + SET_ASIC1(GPIO1_RS232_ON); break; case IPAQ_EGPIO_VPP_ON: - H3800_ASIC1_FlashWP_VPP_ON = setp; + H3800_ASIC2_FlashWP_VPP_ON = setp; break; } +} - local_irq_save(flags); - if ( setp ) { - h3800_asic1_gpio |= set_asic1_egpio; - h3800_asic1_gpio &= ~clear_asic1_egpio; - } - else { - h3800_asic1_gpio &= ~set_asic1_egpio; - h3800_asic1_gpio |= clear_asic1_egpio; - } - H3800_ASIC1_GPIO_Out = h3800_asic1_gpio; - local_irq_restore(flags); +static unsigned long h3800_read_egpio(void) +{ + return H3800_ASIC1_GPIO_OUT | (H3800_ASIC2_GPIOPIOD << 16); } -static unsigned long h3800_read_egpio( void ) +/* We need to fix ASIC2 GPIO over suspend/resume. At the moment, + it doesn't appear that ASIC1 GPIO has the same problem */ + +static int h3800_pm_callback(int req) { - return h3800_asic1_gpio | (h3800_asic2_gpio << 16); + static u16 asic1_data; + static u16 asic2_data; + int result = 0; + + printk(__FUNCTION__ " %d\n", req); + + switch (req) { + case PM_RESUME: + MSC2 = (MSC2 & 0x0000ffff) | 0xE4510000; /* Set MSC2 correctly */ + + H3800_ASIC2_GPIOPIOD = asic2_data; + H3800_ASIC2_GPIODIR = GPIO2_PEN_IRQ + | GPIO2_SD_DETECT + | GPIO2_EAR_IN_N + | GPIO2_USB_DETECT_N + | GPIO2_SD_CON_SLT; + + H3800_ASIC1_GPIO_OUT = asic1_data; + + if (ipaq_model_ops.pm_callback_aux) + result = ipaq_model_ops.pm_callback_aux(req); + break; + + case PM_SUSPEND: + if (ipaq_model_ops.pm_callback_aux && + ((result = ipaq_model_ops.pm_callback_aux(req)) != 0)) + return result; + + asic1_data = H3800_ASIC1_GPIO_OUT; + asic2_data = H3800_ASIC2_GPIOPIOD; + break; + default: + printk(__FUNCTION__ ": unrecognized PM callback\n"); + break; + } + return result; } static struct ipaq_model_ops h3800_model_ops __initdata = { - model : IPAQ_H3800, - generic_name : "3800", - initialize : h3800_init_egpio, - control : h3800_control_egpio, - read : h3800_read_egpio + .generic_name = "3800", + .control = h3800_control_egpio, + .read = h3800_read_egpio, + .pm_callback = h3800_pm_callback }; +#define MAX_ASIC_ISR_LOOPS 20 + +/* The order of these is important - see #include <asm/arch/irqs.h> */ +static u32 kpio_irq_mask[] = { + KPIO_KEY_ALL, + KPIO_SPI_INT, + KPIO_OWM_INT, + KPIO_ADC_INT, + KPIO_UART_0_INT, + KPIO_UART_1_INT, + KPIO_TIMER_0_INT, + KPIO_TIMER_1_INT, + KPIO_TIMER_2_INT +}; + +static u32 gpio_irq_mask[] = { + GPIO2_PEN_IRQ, + GPIO2_SD_DETECT, + GPIO2_EAR_IN_N, + GPIO2_USB_DETECT_N, + GPIO2_SD_CON_SLT, +}; -static void h3600_lcd_power(int on) +static void h3800_IRQ_demux(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { - if (on) - set_h3600_egpio(IPAQ_EGPIO_LCD_ON); - else - clr_h3600_egpio(IPAQ_EGPIO_LCD_ON); -} + int i; + if (0) printk(__FUNCTION__ ": interrupt received\n"); -struct ipaq_model_ops ipaq_model_ops; -EXPORT_SYMBOL(ipaq_model_ops); + desc->chip->ack(irq); -static int __init h3600_init_model_ops(void) -{ - if (machine_is_h3xxx()) { - sa1100fb_lcd_power = h3600_lcd_power; - - if (machine_is_h3100()) { - ipaq_model_ops = h3100_model_ops; - } else if (machine_is_h3600()) { - ipaq_model_ops = h3600_model_ops; - } else if (machine_is_h3800()) { - ipaq_model_ops = h3800_model_ops; - } - init_h3600_egpio(); + for (i = 0; i < MAX_ASIC_ISR_LOOPS && (GPLR & GPIO_H3800_ASIC); i++) { + u32 irq; + int j; + + /* KPIO */ + irq = H3800_ASIC2_KPIINTFLAG; + if (0) printk(__FUNCTION__" KPIO 0x%08X\n", irq); + for (j = 0; j < H3800_KPIO_IRQ_COUNT; j++) + if (irq & kpio_irq_mask[j]) + do_edge_IRQ(H3800_KPIO_IRQ_COUNT + j, irq_desc + H3800_KPIO_IRQ_COUNT + j, regs); + + /* GPIO2 */ + irq = H3800_ASIC2_GPIINTFLAG; + if (0) printk(__FUNCTION__" GPIO 0x%08X\n", irq); + for (j = 0; j < H3800_GPIO_IRQ_COUNT; j++) + if (irq & gpio_irq_mask[j]) + do_edge_IRQ(H3800_GPIO_IRQ_COUNT + j, irq_desc + H3800_GPIO_IRQ_COUNT + j , regs); } - return 0; + + if (i >= MAX_ASIC_ISR_LOOPS) + printk(__FUNCTION__ ": interrupt processing overrun\n"); + + /* For level-based interrupts */ + desc->chip->unmask(irq); + } -__initcall(h3600_init_model_ops); +static struct irqaction h3800_irq = { + .name = "h3800_asic", + .handler = h3800_IRQ_demux, + .flags = SA_INTERRUPT, +}; + +u32 kpio_int_shadow = 0; -/* - * low-level UART features + +/* mask_ack <- IRQ is first serviced. + mask <- IRQ is disabled. + unmask <- IRQ is enabled + + The INTCLR registers are poorly documented. I believe that writing + a "1" to the register clears the specific interrupt, but the documentation + indicates writing a "0" clears the interrupt. In any case, they shouldn't + be read (that's the INTFLAG register) */ -static void h3600_uart_set_mctrl(struct uart_port *port, u_int mctrl) +static void h3800_mask_ack_kpio_irq(unsigned int irq) { - if (port->mapbase == _Ser3UTCR0) { - if (mctrl & TIOCM_RTS) - GPCR = GPIO_H3600_COM_RTS; - else - GPSR = GPIO_H3600_COM_RTS; - } + u32 mask = kpio_irq_mask[irq - H3800_KPIO_IRQ_START]; + kpio_int_shadow &= ~mask; + H3800_ASIC2_KPIINTSTAT = kpio_int_shadow; + H3800_ASIC2_KPIINTCLR = mask; } -static u_int h3600_uart_get_mctrl(struct uart_port *port) +static void h3800_mask_kpio_irq(unsigned int irq) { - u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR; + u32 mask = kpio_irq_mask[irq - H3800_KPIO_IRQ_START]; + kpio_int_shadow &= ~mask; + H3800_ASIC2_KPIINTSTAT = kpio_int_shadow; +} - if (port->mapbase == _Ser3UTCR0) { - int gplr = GPLR; - if (gplr & GPIO_H3600_COM_DCD) - ret &= ~TIOCM_CD; - if (gplr & GPIO_H3600_COM_CTS) - ret &= ~TIOCM_CTS; - } +static void h3800_unmask_kpio_irq(unsigned int irq) +{ + u32 mask = kpio_irq_mask[irq - H3800_KPIO_IRQ_START]; + kpio_int_shadow |= mask; + H3800_ASIC2_KPIINTSTAT = kpio_int_shadow; +} - return ret; +static void h3800_mask_ack_gpio_irq(unsigned int irq) +{ + u32 mask = gpio_irq_mask[irq - H3800_GPIO_IRQ_START]; + H3800_ASIC2_GPIINTSTAT &= ~mask; + H3800_ASIC2_GPIINTCLR = mask; } -static void h3600_uart_pm(struct uart_port *port, u_int state, u_int oldstate) +static void h3800_mask_gpio_irq(unsigned int irq) { - if (port->mapbase == _Ser2UTCR0) { - assign_h3600_egpio( IPAQ_EGPIO_IR_ON, !state ); - } else if (port->mapbase == _Ser3UTCR0) { - assign_h3600_egpio( IPAQ_EGPIO_RS232_ON, !state ); + u32 mask = gpio_irq_mask[irq - H3800_GPIO_IRQ_START]; + H3800_ASIC2_GPIINTSTAT &= ~mask; } + +static void h3800_unmask_gpio_irq(unsigned int irq) +{ + u32 mask = gpio_irq_mask[irq - H3800_GPIO_IRQ_START]; + H3800_ASIC2_GPIINTSTAT |= mask; } -/* - * Enable/Disable wake up events for this serial port. - * Obviously, we only support this on the normal COM port. - */ -static int h3600_uart_set_wake(struct uart_port *port, u_int enable) +static void __init h3800_init_irq(void) { - int err = -EINVAL; + int i; - if (port->mapbase == _Ser3UTCR0) { - if (enable) - PWER |= PWER_GPIO23 | PWER_GPIO25 ; /* DCD and CTS */ - else - PWER &= ~(PWER_GPIO23 | PWER_GPIO25); /* DCD and CTS */ - err = 0; + /* Initialize standard IRQs */ + sa1100_init_irq(); + + /* Disable all IRQs and set up clock */ + H3800_ASIC2_KPIINTSTAT = 0; /* Disable all interrupts */ + H3800_ASIC2_GPIINTSTAT = 0; + + H3800_ASIC2_KPIINTCLR = 0; /* Clear all KPIO interrupts */ + H3800_ASIC2_GPIINTCLR = 0; /* Clear all GPIO interrupts */ + +// H3800_ASIC2_KPIINTCLR = 0xffff; /* Clear all KPIO interrupts */ +// H3800_ASIC2_GPIINTCLR = 0xffff; /* Clear all GPIO interrupts */ + + H3800_ASIC2_CLOCK_Enable |= ASIC2_CLOCK_EX0; /* 32 kHZ crystal on */ + H3800_ASIC2_INTR_ClockPrescale |= ASIC2_INTCPS_SET; + H3800_ASIC2_INTR_ClockPrescale = ASIC2_INTCPS_CPS(0x0e) | ASIC2_INTCPS_SET; + H3800_ASIC2_INTR_TimerSet = 1; + +#if 0 + for (i = 0; i < H3800_KPIO_IRQ_COUNT; i++) { + int irq = i + H3800_KPIO_IRQ_START; + irq_desc[irq].valid = 1; + irq_desc[irq].probe_ok = 1; + set_irq_chip(irq, &h3800_kpio_irqchip); } - return err; + + for (i = 0; i < H3800_GPIO_IRQ_COUNT; i++) { + int irq = i + H3800_GPIO_IRQ_START; + irq_desc[irq].valid = 1; + irq_desc[irq].probe_ok = 1; + set_irq_chip(irq, &h3800_gpio_irqchip); + } +#endif + set_irq_type(IRQ_GPIO_H3800_ASIC, IRQT_RISING); + set_irq_chained_handler(IRQ_GPIO_H3800_ASIC, &h3800_IRQ_demux); } -static struct sa1100_port_fns h3600_port_fns __initdata = { - .set_mctrl = h3600_uart_set_mctrl, - .get_mctrl = h3600_uart_get_mctrl, - .pm = h3600_uart_pm, - .set_wake = h3600_uart_set_wake, -}; -static struct map_desc h3600_io_desc[] __initdata = { - /* virtual physical length type */ - { H3600_EGPIO_VIRT, 0x49000000, 0x01000000, MT_DEVICE }, /* EGPIO 0 CS#5 */ - { H3600_BANK_2_VIRT, 0x10000000, 0x02800000, MT_DEVICE }, /* static memory bank 2 CS#2 */ - { H3600_BANK_4_VIRT, 0x40000000, 0x00800000, MT_DEVICE } /* static memory bank 4 CS#4 */ -}; +#define ASIC1_OUTPUTS 0x7fff /* First 15 bits are used */ -static void __init h3600_map_io(void) +static void __init h3800_map_io(void) { - sa1100_map_io(); - iotable_init(h3600_io_desc, ARRAY_SIZE(h3600_io_desc)); + h3xxx_map_io(); + + /* Add wakeup on AC plug/unplug */ + PWER |= PWER_GPIO12; + + /* Initialize h3800-specific values here */ + GPCR = 0x0fffffff; /* All outputs are set low by default */ + GAFR = GPIO_H3800_CLK_OUT | + GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 | + GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8; + GPDR = GPIO_H3800_CLK_OUT | + GPIO_H3600_COM_RTS | GPIO_H3600_L3_CLOCK | + GPIO_H3600_L3_MODE | GPIO_H3600_L3_DATA | + GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 | + GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8; + TUCR = TUCR_3_6864MHz; /* Seems to be used only for the Bluetooth UART */ + + /* Fix the memory bus */ + MSC2 = (MSC2 & 0x0000ffff) | 0xE4510000; - sa1100_register_uart_fns(&h3600_port_fns); - sa1100_register_uart(0, 3); - sa1100_register_uart(1, 1); /* isn't this one driven elsewhere? */ - - /* - * Default GPIO settings. Should be set by machine - */ - GPCR = 0x0fffffff; -// GPDR = 0x0401f3fc; - GPDR = GPIO_H3600_COM_RTS | GPIO_H3600_L3_CLOCK | - GPIO_H3600_L3_MODE | GPIO_H3600_L3_DATA | - GPIO_H3600_CLK_SET1 | GPIO_H3600_CLK_SET0 | - GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 | - GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8; + /* Set up ASIC #1 */ + H3800_ASIC1_GPIO_DIR = ASIC1_OUTPUTS; /* All outputs */ + H3800_ASIC1_GPIO_MASK = ASIC1_OUTPUTS; /* No interrupts */ + H3800_ASIC1_GPIO_SLEEP_MASK = ASIC1_OUTPUTS; + H3800_ASIC1_GPIO_SLEEP_DIR = ASIC1_OUTPUTS; + H3800_ASIC1_GPIO_SLEEP_OUT = GPIO1_EAR_ON_N; + H3800_ASIC1_GPIO_BATT_FAULT_DIR = ASIC1_OUTPUTS; + H3800_ASIC1_GPIO_BATT_FAULT_OUT = GPIO1_EAR_ON_N; + + H3800_ASIC1_GPIO_OUT = GPIO1_IR_ON_N + | GPIO1_RS232_ON + | GPIO1_EAR_ON_N; - init_h3600_egpio(); + /* Set up ASIC #2 */ + H3800_ASIC2_GPIOPIOD = GPIO2_IN_Y1_N | GPIO2_IN_X1_N; + H3800_ASIC2_GPOBFSTAT = GPIO2_IN_Y1_N | GPIO2_IN_X1_N; - /* - * Ensure those pins are outputs and driving low. - */ - PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM; - PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM); + H3800_ASIC2_GPIODIR = GPIO2_PEN_IRQ + | GPIO2_SD_DETECT + | GPIO2_EAR_IN_N + | GPIO2_USB_DETECT_N + | GPIO2_SD_CON_SLT; - /* Configure suspend conditions */ - PGSR = 0; - PWER = PWER_GPIO0 | PWER_RTC; - PCFR = PCFR_OPDE; - PSDR = 0; + /* TODO : Set sleep states & battery fault states */ + + /* Clear VPP Enable */ + H3800_ASIC2_FlashWP_VPP_ON = 0; + ipaq_model_ops = h3800_model_ops; } -MACHINE_START(H3600, "Compaq iPAQ H3600") - BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - BOOT_PARAMS(0xc0000100) - MAPIO(h3600_map_io) - INITIRQ(sa1100_init_irq) -MACHINE_END -MACHINE_START(H3100, "Compaq iPAQ H3100") - BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) - BOOT_PARAMS(0xc0000100) - MAPIO(h3600_map_io) - INITIRQ(sa1100_init_irq) -MACHINE_END MACHINE_START(H3800, "Compaq iPAQ H3800") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) BOOT_PARAMS(0xc0000100) - MAPIO(h3600_map_io) - INITIRQ(sa1100_init_irq) + MAPIO(h3800_map_io) + INITIRQ(h3800_init_irq) MACHINE_END + +#endif /* CONFIG_SA1100_H3800 */ diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c index 3ff0f6999a2f621eacbcdd55e2bbe37c27a8a98b..a735626790258791f3feed102b20cc846ddb8440 100644 --- a/arch/arm/mach-sa1100/jornada720.c +++ b/arch/arm/mach-sa1100/jornada720.c @@ -16,7 +16,6 @@ #include <asm/mach/serial_sa1100.h> #include "generic.h" -#include "sa1111.h" #define JORTUCR_VAL 0x20000400 @@ -46,11 +45,7 @@ static int __init jornada720_init(void) PPSR &= ~(PPC_LDD3 | PPC_LDD4); PPDR |= PPC_LDD3 | PPC_LDD4; - /* initialize extra IRQs */ - set_GPIO_IRQ_edge(GPIO_GPIO1, GPIO_RISING_EDGE); - sa1111_init_irq(IRQ_GPIO1); /* chained on GPIO 1 */ - - return 0; + return sa1111_init(0x40000000, IRQ_GPIO1); } arch_initcall(jornada720_init); diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c index ef95e6c45f84bd529b3dcca01b878f110c40f128..9d3a939de4ae896adcf34aa3e6716060caeed674 100644 --- a/arch/arm/mach-sa1100/neponset.c +++ b/arch/arm/mach-sa1100/neponset.c @@ -11,6 +11,7 @@ #include <linux/ioport.h> #include <linux/serial_core.h> #include <linux/device.h> +#include <linux/slab.h> #include <asm/hardware.h> #include <asm/mach-types.h> @@ -23,13 +24,6 @@ #include <asm/hardware/sa1111.h> #include <asm/sizes.h> -#include "sa1111.h" - -static struct device neponset_device = { - .name = "Neponset", - .bus_id = "nep_bus", -}; - /* * Install handler for Neponset IRQ. Note that we have to loop here * since the ETHERNET and USAR IRQs are level based, and we need to @@ -163,6 +157,52 @@ static struct sa1100_port_fns neponset_port_fns __initdata = { .get_mctrl = neponset_get_mctrl, }; +/* + * LDM power management. + */ +static int neponset_suspend(struct device *dev, u32 state, u32 level) +{ + /* + * Save state. + */ + if (level == SUSPEND_SAVE_STATE || + level == SUSPEND_DISABLE || + level == SUSPEND_POWER_DOWN) { + if (!dev->saved_state) + dev->saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL); + if (!dev->saved_state) + return -ENOMEM; + + *(unsigned int *)dev->saved_state = NCR_0; + } + + return 0; +} + +static int neponset_resume(struct device *dev, u32 level) +{ + if (level == RESUME_RESTORE_STATE || level == RESUME_ENABLE) { + if (dev->saved_state) { + NCR_0 = *(unsigned int *)dev->saved_state; + kfree(dev->saved_state); + dev->saved_state = NULL; + } + } + + return 0; +} + +static struct device_driver neponset_device_driver = { + .suspend = neponset_suspend, + .resume = neponset_resume, +}; + +static struct device neponset_device = { + .name = "Neponset", + .bus_id = "neponset", + .driver = &neponset_device_driver, +}; + static int __init neponset_init(void) { int ret; @@ -191,7 +231,7 @@ static int __init neponset_init(void) return -ENODEV; } - ret = device_register(&neponset_device); + ret = register_sys_device(&neponset_device); if (ret) return ret; @@ -213,7 +253,7 @@ static int __init neponset_init(void) /* * Probe and initialise the SA1111. */ - return sa1111_init(&neponset_device, 0x40000000, IRQ_NEPONSET_SA1111); + return sa1111_init(0x40000000, IRQ_NEPONSET_SA1111); } arch_initcall(neponset_init); diff --git a/arch/arm/mach-sa1100/pfs168.c b/arch/arm/mach-sa1100/pfs168.c index 2b62878b4e7c431c1cdacd8fc36a086bcd0feb85..d17c1a79e7857247c9f950dee083aafa46043ed3 100644 --- a/arch/arm/mach-sa1100/pfs168.c +++ b/arch/arm/mach-sa1100/pfs168.c @@ -17,7 +17,6 @@ #include <asm/mach/serial_sa1100.h> #include "generic.h" -#include "sa1111.h" static int __init pfs168_init(void) @@ -36,7 +35,7 @@ static int __init pfs168_init(void) /* * Probe for SA1111. */ - return sa1111_init(NULL, 0x40000000, IRQ_GPIO25); + return sa1111_init(0x40000000, IRQ_GPIO25); } arch_initcall(pfs168_init); diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c index 1a7cebd8d28c994705eadd8ebc3cca24845f9de9..76e0da5b973efa6c6f166efddd1ff01363dc9591 100644 --- a/arch/arm/mach-sa1100/pm.c +++ b/arch/arm/mach-sa1100/pm.c @@ -30,6 +30,7 @@ #include <linux/interrupt.h> #include <linux/sysctl.h> #include <linux/errno.h> +#include <linux/device.h> #include <linux/cpufreq.h> #include <asm/hardware.h> @@ -193,11 +194,29 @@ static int sysctl_pm_do_suspend(void) { int retval; + /* + * Suspend "legacy" devices. + */ retval = pm_send_all(PM_SUSPEND, (void *)3); - if (retval == 0) { + /* + * Suspend LDM devices. + */ + device_suspend(4, SUSPEND_NOTIFY); + device_suspend(4, SUSPEND_SAVE_STATE); + device_suspend(4, SUSPEND_DISABLE); + retval = pm_do_suspend(); + /* + * Resume LDM devices. + */ + device_resume(RESUME_RESTORE_STATE); + device_resume(RESUME_ENABLE); + + /* + * Resume "legacy" devices. + */ pm_send_all(PM_RESUME, (void *)0); } diff --git a/arch/arm/mach-sa1100/sa1111.c b/arch/arm/mach-sa1100/sa1111.c index 244dfdc35c591785d94c3eb6544e652bc374944b..9ded8fe5f98e7fbbe770c2b252701107b5cefcc0 100644 --- a/arch/arm/mach-sa1100/sa1111.c +++ b/arch/arm/mach-sa1100/sa1111.c @@ -25,6 +25,7 @@ #include <linux/ioport.h> #include <linux/device.h> #include <linux/slab.h> +#include <linux/spinlock.h> #include <asm/hardware.h> #include <asm/mach-types.h> @@ -34,11 +35,132 @@ #include <asm/hardware/sa1111.h> -#include "sa1111.h" +/* + * We keep the following data for the overall SA1111. Note that the + * struct device and struct resource are "fake"; they should be supplied + * by the bus above us. However, in the interests of getting all SA1111 + * drivers converted over to the device model, we provide this as an + * anchor point for all the other drivers. + */ +struct sa1111 { + struct device dev; + struct resource res; + int irq; + spinlock_t lock; + void *base; +}; + +/* + * We _really_ need to eliminate this. Its only users + * are the PWM and DMA checking code. + */ +static struct sa1111 *g_sa1111; + +static struct sa1111_dev usb_dev = { + .dev = { + .name = "Intel Corporation SA1111 [USB Controller]", + }, + .skpcr_mask = SKPCR_UCLKEN, + .devid = SA1111_DEVID_USB, + .irq = { + IRQ_USBPWR, + IRQ_NHCIM, + IRQ_HCIBUFFACC, + IRQ_HCIRMTWKP, + IRQ_NHCIMFCIR, + IRQ_USB_PORT_RESUME + }, +}; -struct sa1111_device *sa1111; +static struct sa1111_dev sac_dev = { + .dev = { + .name = "Intel Corporation SA1111 [Audio Controller]", + }, + .skpcr_mask = SKPCR_I2SCLKEN | SKPCR_L3CLKEN, + .devid = SA1111_DEVID_SAC, + .irq = { + AUDXMTDMADONEA, + AUDXMTDMADONEB, + AUDRCVDMADONEA, + AUDRCVDMADONEB + }, +}; -EXPORT_SYMBOL(sa1111); +static struct sa1111_dev ssp_dev = { + .dev = { + .name = "Intel Corporation SA1111 [SSP Controller]", + }, + .skpcr_mask = SKPCR_SCLKEN, + .devid = SA1111_DEVID_SSP, +}; + +static struct sa1111_dev kbd_dev = { + .dev = { + .name = "Intel Corporation SA1111 [PS2]", + }, + .skpcr_mask = SKPCR_PTCLKEN, + .devid = SA1111_DEVID_PS2, + .irq = { + IRQ_TPRXINT, + IRQ_TPTXINT + }, +}; + +static struct sa1111_dev mse_dev = { + .dev = { + .name = "Intel Corporation SA1111 [PS2]", + }, + .skpcr_mask = SKPCR_PMCLKEN, + .devid = SA1111_DEVID_PS2, + .irq = { + IRQ_MSRXINT, + IRQ_MSTXINT + }, +}; + +static struct sa1111_dev int_dev = { + .dev = { + .name = "Intel Corporation SA1111 [Interrupt Controller]", + }, + .skpcr_mask = 0, + .devid = SA1111_DEVID_INT, +}; + +static struct sa1111_dev pcmcia_dev = { + .dev = { + .name = "Intel Corporation SA1111 [PCMCIA Controller]", + }, + .skpcr_mask = 0, + .devid = SA1111_DEVID_PCMCIA, + .irq = { + IRQ_S0_READY_NINT, + IRQ_S0_CD_VALID, + IRQ_S0_BVD1_STSCHG, + IRQ_S1_READY_NINT, + IRQ_S1_CD_VALID, + IRQ_S1_BVD1_STSCHG, + }, +}; + +static struct sa1111_dev *devs[] = { + &usb_dev, + &sac_dev, + &ssp_dev, + &kbd_dev, + &mse_dev, + &int_dev, + &pcmcia_dev, +}; + +static unsigned int dev_offset[] = { + SA1111_USB, + 0x0600, + 0x0800, + SA1111_KBD, + SA1111_MSE, + SA1111_INTC, + 0x1800, +}; /* * SA1111 interrupt support. Since clearing an IRQ while there are @@ -50,11 +172,15 @@ sa1111_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { unsigned int stat0, stat1, i; - desc->chip->ack(irq); - stat0 = INTSTATCLR0; stat1 = INTSTATCLR1; + INTSTATCLR0 = stat0; + + desc->chip->ack(irq); + + INTSTATCLR1 = stat1; + if (stat0 == 0 && stat1 == 0) { do_bad_IRQ(irq, desc, regs); return; @@ -75,9 +201,8 @@ sa1111_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) #define SA1111_IRQMASK_LO(x) (1 << (x - IRQ_SA1111_START)) #define SA1111_IRQMASK_HI(x) (1 << (x - IRQ_SA1111_START - 32)) -static void sa1111_ack_lowirq(unsigned int irq) +static void sa1111_ack_irq(unsigned int irq) { - INTSTATCLR0 = SA1111_IRQMASK_LO(irq); } static void sa1111_mask_lowirq(unsigned int irq) @@ -133,18 +258,13 @@ static int sa1111_type_lowirq(unsigned int irq, unsigned int flags) } static struct irqchip sa1111_low_chip = { - .ack = sa1111_ack_lowirq, + .ack = sa1111_ack_irq, .mask = sa1111_mask_lowirq, .unmask = sa1111_unmask_lowirq, .rerun = sa1111_rerun_lowirq, .type = sa1111_type_lowirq, }; -static void sa1111_ack_highirq(unsigned int irq) -{ - INTSTATCLR1 = SA1111_IRQMASK_HI(irq); -} - static void sa1111_mask_highirq(unsigned int irq) { INTEN1 &= ~SA1111_IRQMASK_HI(irq); @@ -198,34 +318,40 @@ static int sa1111_type_highirq(unsigned int irq, unsigned int flags) } static struct irqchip sa1111_high_chip = { - .ack = sa1111_ack_highirq, + .ack = sa1111_ack_irq, .mask = sa1111_mask_highirq, .unmask = sa1111_unmask_highirq, .rerun = sa1111_rerun_highirq, .type = sa1111_type_highirq, }; -static void __init sa1111_init_irq(int irq_nr) +static void __init sa1111_init_irq(struct sa1111_dev *sadev) { unsigned int irq; - request_mem_region(_INTTEST0, 512, "irqs"); + /* + * We're guaranteed that this region hasn't been taken. + */ + request_mem_region(sadev->res.start, 512, "irqs"); /* disable all IRQs */ - INTEN0 = 0; - INTEN1 = 0; + sa1111_writel(0, sadev->mapbase + SA1111_INTEN0); + sa1111_writel(0, sadev->mapbase + SA1111_INTEN1); + sa1111_writel(0, sadev->mapbase + SA1111_WAKEEN0); + sa1111_writel(0, sadev->mapbase + SA1111_WAKEEN1); /* * detect on rising edge. Note: Feb 2001 Errata for SA1111 * specifies that S0ReadyInt and S1ReadyInt should be '1'. */ - INTPOL0 = 0; - INTPOL1 = SA1111_IRQMASK_HI(S0_READY_NINT) | - SA1111_IRQMASK_HI(S1_READY_NINT); + sa1111_writel(0, sadev->mapbase + SA1111_INTPOL0); + sa1111_writel(SA1111_IRQMASK_HI(IRQ_S0_READY_NINT) | + SA1111_IRQMASK_HI(IRQ_S1_READY_NINT), + sadev->mapbase + SA1111_INTPOL1); /* clear all IRQs */ - INTSTATCLR0 = ~0; - INTSTATCLR1 = ~0; + sa1111_writel(~0, sadev->mapbase + SA1111_INTSTATCLR0); + sa1111_writel(~0, sadev->mapbase + SA1111_INTSTATCLR1); for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) { set_irq_chip(irq, &sa1111_low_chip); @@ -233,7 +359,7 @@ static void __init sa1111_init_irq(int irq_nr) set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } - for (irq = AUDXMTDMADONEA; irq <= S1_BVD1_STSCHG; irq++) { + for (irq = AUDXMTDMADONEA; irq <= IRQ_S1_BVD1_STSCHG; irq++) { set_irq_chip(irq, &sa1111_high_chip); set_irq_handler(irq, do_edge_IRQ); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); @@ -242,24 +368,11 @@ static void __init sa1111_init_irq(int irq_nr) /* * Register SA1111 interrupt */ - set_irq_type(irq_nr, IRQT_RISING); - set_irq_chained_handler(irq_nr, sa1111_irq_handler); -} - -static int sa1111_suspend(struct device *dev, u32 state, u32 level) -{ - return 0; + set_irq_type(sadev->irq[0], IRQT_RISING); + set_irq_chained_handler(sadev->irq[0], sa1111_irq_handler); } -static int sa1111_resume(struct device *dev, u32 level) -{ - return 0; -} - -static struct device_driver sa1111_device_driver = { - .suspend = sa1111_suspend, - .resume = sa1111_resume, -}; +static struct device_driver sa1111_device_driver; /** * sa1111_probe - probe for a single SA1111 chip. @@ -274,30 +387,38 @@ static struct device_driver sa1111_device_driver = { * %0 successful. */ static int __init -sa1111_probe(struct device *parent, unsigned long phys_addr) +sa1111_probe(unsigned long phys_addr, int irq) { - struct sa1111_device *sa; + struct sa1111 *sachip; unsigned long id; - int ret = -ENODEV; + unsigned int has_devs; + int i, ret = -ENODEV; - sa = kmalloc(sizeof(struct sa1111_device), GFP_KERNEL); - if (!sa) + sachip = kmalloc(sizeof(struct sa1111), GFP_KERNEL); + if (!sachip) return -ENOMEM; - memset(sa, 0, sizeof(struct sa1111_device)); + memset(sachip, 0, sizeof(struct sa1111)); + + spin_lock_init(&sachip->lock); - sa->resource.name = "SA1111"; - sa->resource.start = phys_addr; - sa->resource.end = phys_addr + 0x2000; + strncpy(sachip->dev.name, "Intel Corporation SA1111", sizeof(sachip->dev.name)); + snprintf(sachip->dev.bus_id, sizeof(sachip->dev.bus_id), "%8.8lx", phys_addr); + sachip->dev.driver = &sa1111_device_driver; + sachip->dev.driver_data = sachip; - if (request_resource(&iomem_resource, &sa->resource)) { + sachip->res.name = sachip->dev.name; + sachip->res.start = phys_addr; + sachip->res.end = phys_addr + 0x2000; + sachip->irq = irq; + + if (request_resource(&iomem_resource, &sachip->res)) { ret = -EBUSY; goto out; } - /* eventually ioremap... */ - sa->base = (void *)0xf4000000; - if (!sa->base) { + sachip->base = ioremap(phys_addr, PAGE_SIZE * 2); + if (!sachip->base) { ret = -ENOMEM; goto release; } @@ -305,7 +426,7 @@ sa1111_probe(struct device *parent, unsigned long phys_addr) /* * Probe for the chip. Only touch the SBI registers. */ - id = sa1111_readl(sa->base + SA1111_SKID); + id = sa1111_readl(sachip->base + SA1111_SKID); if ((id & SKID_ID_MASK) != SKID_SA1111_ID) { printk(KERN_DEBUG "SA1111 not detected: ID = %08lx\n", id); ret = -ENODEV; @@ -315,12 +436,7 @@ sa1111_probe(struct device *parent, unsigned long phys_addr) /* * We found the chip. */ - strcpy(sa->dev.name, "SA1111"); - sprintf(sa->dev.bus_id, "%8.8lx", phys_addr); - sa->dev.parent = parent; - sa->dev.driver = &sa1111_device_driver; - - ret = device_register(&sa->dev); + ret = register_sys_device(&sachip->dev); if (ret) printk("sa1111 device_register failed: %d\n", ret); @@ -328,19 +444,64 @@ sa1111_probe(struct device *parent, unsigned long phys_addr) "silicon revision %lx, metal revision %lx\n", (id & SKID_SIREV_MASK)>>4, (id & SKID_MTREV_MASK)); - sa1111 = sa; + g_sa1111 = sachip; + + has_devs = ~0; + if (machine_is_assabet() || machine_is_jornada720() || + machine_is_badge4()) + has_devs &= ~(1 << 4); + else + has_devs &= ~(1 << 1); + + for (i = 0; i < ARRAY_SIZE(devs); i++) { + if (!(has_devs & (1 << i))) + continue; + + snprintf(devs[i]->dev.bus_id, sizeof(devs[i]->dev.bus_id), + "%4.4x", dev_offset[i]); + + devs[i]->dev.parent = &sachip->dev; + devs[i]->dev.bus = &sa1111_bus_type; + devs[i]->res.start = sachip->res.start + dev_offset[i]; + devs[i]->res.end = devs[i]->res.start + 511; + devs[i]->res.name = devs[i]->dev.name; + devs[i]->res.flags = IORESOURCE_MEM; + devs[i]->mapbase = sachip->base + dev_offset[i]; + + if (request_resource(&sachip->res, &devs[i]->res)) { + printk("SA1111: failed to allocate resource for %s\n", + devs[i]->res.name); + continue; + } + + device_register(&devs[i]->dev); + } return 0; unmap: -// iounmap(sa->base); + iounmap(sachip->base); release: - release_resource(&sa->resource); + release_resource(&sachip->res); out: - kfree(sa); + kfree(sachip); return ret; } +static void __sa1111_remove(struct sa1111 *sachip) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(devs); i++) { + put_device(&devs[i]->dev); + release_resource(&devs[i]->res); + } + + iounmap(sachip->base); + release_resource(&sachip->res); + kfree(sachip); +} + /* * Bring the SA1111 out of reset. This requires a set procedure: * 1. nRESET asserted (by hardware) @@ -355,12 +516,11 @@ sa1111_probe(struct device *parent, unsigned long phys_addr) * SBI_SMCR * SBI_SKID */ -void sa1111_wake(void) +static void sa1111_wake(struct sa1111 *sachip) { - struct sa1111_device *sa = sa1111; unsigned long flags, r; - local_irq_save(flags); + spin_lock_irqsave(&sachip->lock, flags); /* * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111: @@ -373,11 +533,11 @@ void sa1111_wake(void) /* * Turn VCO on, and disable PLL Bypass. */ - r = sa1111_readl(sa->base + SA1111_SKCR); + r = sa1111_readl(sachip->base + SA1111_SKCR); r &= ~SKCR_VCO_OFF; - sa1111_writel(r, sa->base + SA1111_SKCR); + sa1111_writel(r, sachip->base + SA1111_SKCR); r |= SKCR_PLL_BYPASS | SKCR_OE_EN; - sa1111_writel(r, sa->base + SA1111_SKCR); + sa1111_writel(r, sachip->base + SA1111_SKCR); /* * Wait lock time. SA1111 manual _doesn't_ @@ -389,7 +549,7 @@ void sa1111_wake(void) * Enable RCLK. We also ensure that RDYEN is set. */ r |= SKCR_RCLKEN | SKCR_RDYEN; - sa1111_writel(r, sa->base + SA1111_SKCR); + sa1111_writel(r, sachip->base + SA1111_SKCR); /* * Wait 14 RCLK cycles for the chip to finish coming out @@ -400,76 +560,31 @@ void sa1111_wake(void) /* * Ensure all clocks are initially off. */ - sa1111_writel(0, sa->base + SA1111_SKPCR); + sa1111_writel(0, sachip->base + SA1111_SKPCR); - local_irq_restore(flags); -} - -void sa1111_doze(void) -{ - struct sa1111_device *sa = sa1111; - unsigned long flags; - unsigned int val; - - local_irq_save(flags); - - if (sa1111_readl(sa->base + SA1111_SKPCR) & SKPCR_UCLKEN) { - local_irq_restore(flags); - printk("SA1111 doze mode refused\n"); - return; - } - - val = sa1111_readl(sa->base + SA1111_SKCR); - sa1111_writel(val & ~SKCR_RCLKEN, sa->base + SA1111_SKCR); - local_irq_restore(flags); + spin_unlock_irqrestore(&sachip->lock, flags); } /* * Configure the SA1111 shared memory controller. */ -void sa1111_configure_smc(int sdram, unsigned int drac, unsigned int cas_latency) +void +sa1111_configure_smc(struct sa1111 *sachip, int sdram, unsigned int drac, + unsigned int cas_latency) { - struct sa1111_device *sa = sa1111; unsigned int smcr = SMCR_DTIM | SMCR_MBGE | FInsrt(drac, SMCR_DRAC); if (cas_latency == 3) smcr |= SMCR_CLAT; - sa1111_writel(smcr, sa->base + SA1111_SMCR); + sa1111_writel(smcr, sachip->base + SA1111_SMCR); } -EXPORT_SYMBOL(sa1111_wake); -EXPORT_SYMBOL(sa1111_doze); - -void sa1111_enable_device(unsigned int mask) -{ - struct sa1111_device *sa = sa1111; - unsigned int val; - - preempt_disable(); - val = sa1111_readl(sa->base + SA1111_SKPCR); - sa1111_writel(val | mask, sa->base + SA1111_SKPCR); - preempt_enable(); -} - -void sa1111_disable_device(unsigned int mask) -{ - struct sa1111_device *sa = sa1111; - unsigned int val; - - preempt_disable(); - val = sa1111_readl(sa->base + SA1111_SKPCR); - sa1111_writel(val & ~mask, sa->base + SA1111_SKPCR); - preempt_enable(); -} - -EXPORT_SYMBOL(sa1111_enable_device); -EXPORT_SYMBOL(sa1111_disable_device); - -/* According to the "Intel StrongARM SA-1111 Microprocessor Companion +/* + * According to the "Intel StrongARM SA-1111 Microprocessor Companion * Chip Specification Update" (June 2000), erratum #7, there is a - * significant bug in Serial Audio Controller DMA. If the SAC is - * accessing a region of memory above 1MB relative to the bank base, + * significant bug in the SA1111 SDRAM shared memory controller. If + * an access to a region of memory above 1MB relative to the bank base, * it is important that address bit 10 _NOT_ be asserted. Depending * on the configuration of the RAM, bit 10 may correspond to one * of several different (processor-relative) address bits. @@ -479,7 +594,9 @@ EXPORT_SYMBOL(sa1111_disable_device); */ int sa1111_check_dma_bug(dma_addr_t addr) { - unsigned int physaddr=SA1111_DMA_ADDR((unsigned int)addr); + struct sa1111 *sachip = g_sa1111; + unsigned int physaddr = SA1111_DMA_ADDR((unsigned int)addr); + unsigned int smcr; /* Section 4.6 of the "Intel StrongARM SA-1111 Development Module * User's Guide" mentions that jumpers R51 and R52 control the @@ -494,9 +611,10 @@ int sa1111_check_dma_bug(dma_addr_t addr) * above the start of the target bank: */ if (physaddr<(1<<20)) - return 0; + return 0; - switch (FExtr(SBI_SMCR, SMCR_DRAC)) { + smcr = sa1111_readl(sachip->base + SA1111_SMCR); + switch (FExtr(smcr, SMCR_DRAC)) { case 01: /* 10 row + bank address bits, A<20> must not be set */ if (physaddr & (1<<20)) return -1; @@ -523,27 +641,26 @@ int sa1111_check_dma_bug(dma_addr_t addr) break; default: printk(KERN_ERR "%s(): invalid SMCR DRAC value 0%lo\n", - __FUNCTION__, FExtr(SBI_SMCR, SMCR_DRAC)); + __FUNCTION__, FExtr(smcr, SMCR_DRAC)); return -1; } return 0; } -EXPORT_SYMBOL(sa1111_check_dma_bug); - -int sa1111_init(struct device *parent, unsigned long phys, unsigned int irq) +int sa1111_init(unsigned long phys, unsigned int irq) { + unsigned int val; int ret; - ret = sa1111_probe(parent, phys); + ret = sa1111_probe(phys, irq); if (ret < 0) return ret; /* * We found it. Wake the chip up. */ - sa1111_wake(); + sa1111_wake(g_sa1111); /* * The SDRAM configuration of the SA1110 and the SA1111 must @@ -552,7 +669,7 @@ int sa1111_init(struct device *parent, unsigned long phys, unsigned int irq) * MBGNT signal, so we must have called sa1110_mb_disable() * beforehand. */ - sa1111_configure_smc(1, + sa1111_configure_smc(g_sa1111, 1, FExtr(MDCNFG, MDCNFG_SA1110_DRAC0), FExtr(MDCNFG, MDCNFG_SA1110_TDL0)); @@ -560,7 +677,8 @@ int sa1111_init(struct device *parent, unsigned long phys, unsigned int irq) * We only need to turn on DCLK whenever we want to use the * DMA. It can otherwise be held firmly in the off position. */ - sa1111_enable_device(SKPCR_DCLKEN); + val = sa1111_readl(g_sa1111->base + SA1111_SKPCR); + sa1111_writel(val | SKPCR_DCLKEN, g_sa1111->base + SA1111_SKPCR); /* * Enable the SA1110 memory bus request and grant signals. @@ -570,7 +688,341 @@ int sa1111_init(struct device *parent, unsigned long phys, unsigned int irq) /* * Initialise SA1111 IRQs */ - sa1111_init_irq(irq); + int_dev.irq[0] = irq; + sa1111_init_irq(&int_dev); + + return 0; +} + +struct sa1111_save_data { + unsigned int skcr; + unsigned int skpcr; + unsigned int skcdr; + unsigned char skaud; + unsigned char skpwm0; + unsigned char skpwm1; + + /* + * Interrupt controller + */ + unsigned int intpol0; + unsigned int intpol1; + unsigned int inten0; + unsigned int inten1; + unsigned int wakepol0; + unsigned int wakepol1; + unsigned int wakeen0; + unsigned int wakeen1; +}; + +static int sa1111_suspend(struct device *dev, u32 state, u32 level) +{ + struct sa1111 *sachip = dev->driver_data; + unsigned long flags; + char *base; + + /* + * Save state. + */ + if (level == SUSPEND_SAVE_STATE || + level == SUSPEND_DISABLE || + level == SUSPEND_POWER_DOWN) { + struct sa1111_save_data *save; + + if (!dev->saved_state) + dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL); + if (!dev->saved_state) + return -ENOMEM; + + save = (struct sa1111_save_data *)dev->saved_state; + + spin_lock_irqsave(&sachip->lock, flags); + base = sachip->base; + save->skcr = sa1111_readl(base + SA1111_SKCR); + save->skpcr = sa1111_readl(base + SA1111_SKPCR); + save->skcdr = sa1111_readl(base + SA1111_SKCDR); + save->skaud = sa1111_readl(base + SA1111_SKAUD); + save->skpwm0 = sa1111_readl(base + SA1111_SKPWM0); + save->skpwm1 = sa1111_readl(base + SA1111_SKPWM1); + + base = sachip->base + SA1111_INTC; + save->intpol0 = sa1111_readl(base + SA1111_INTPOL0); + save->intpol1 = sa1111_readl(base + SA1111_INTPOL1); + save->inten0 = sa1111_readl(base + SA1111_INTEN0); + save->inten1 = sa1111_readl(base + SA1111_INTEN1); + save->wakepol0 = sa1111_readl(base + SA1111_WAKEPOL0); + save->wakepol1 = sa1111_readl(base + SA1111_WAKEPOL1); + save->wakeen0 = sa1111_readl(base + SA1111_WAKEEN0); + save->wakeen1 = sa1111_readl(base + SA1111_WAKEEN1); + spin_unlock_irqrestore(&sachip->lock, flags); + } + + /* + * Disable. + */ + if (level == SUSPEND_DISABLE && state == 4) { + unsigned int val; + + spin_lock_irqsave(&sachip->lock, flags); + base = sachip->base; + + sa1111_writel(0, base + SA1111_SKPWM0); + sa1111_writel(0, base + SA1111_SKPWM1); + val = sa1111_readl(base + SA1111_SKCR); + sa1111_writel(val | SKCR_SLEEP, base + SA1111_SKCR); + + spin_unlock_irqrestore(&sachip->lock, flags); + } return 0; } + +/* + * sa1111_resume - Restore the SA1111 device state. + * @dev: device to restore + * @level: resume level + * + * Restore the general state of the SA1111; clock control and + * interrupt controller. Other parts of the SA1111 must be + * restored by their respective drivers, and must be called + * via LDM after this function. + */ +static int sa1111_resume(struct device *dev, u32 level) +{ + struct sa1111 *sachip = dev->driver_data; + struct sa1111_save_data *save; + unsigned long flags, id; + char *base; + + if (level != RESUME_RESTORE_STATE && level != RESUME_ENABLE) + return 0; + + save = (struct sa1111_save_data *)dev->saved_state; + if (!save) + return 0; + + dev->saved_state = NULL; + + /* + * Ensure that the SA1111 is still here. + */ + id = sa1111_readl(sachip->base + SA1111_SKID); + if ((id & SKID_ID_MASK) != SKID_SA1111_ID) { + __sa1111_remove(sachip); + kfree(save); + return 0; + } + + spin_lock_irqsave(&sachip->lock, flags); + sa1111_wake(sachip); + + base = sachip->base; + sa1111_writel(save->skcr, base + SA1111_SKCR); + sa1111_writel(save->skpcr, base + SA1111_SKPCR); + sa1111_writel(save->skcdr, base + SA1111_SKCDR); + sa1111_writel(save->skaud, base + SA1111_SKAUD); + sa1111_writel(save->skpwm0, base + SA1111_SKPWM0); + sa1111_writel(save->skpwm1, base + SA1111_SKPWM1); + + base = sachip->base + SA1111_INTC; + sa1111_writel(save->intpol0, base + SA1111_INTPOL0); + sa1111_writel(save->intpol1, base + SA1111_INTPOL1); + sa1111_writel(save->inten0, base + SA1111_INTEN0); + sa1111_writel(save->inten1, base + SA1111_INTEN1); + sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0); + sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1); + sa1111_writel(save->wakeen0, base + SA1111_WAKEEN0); + sa1111_writel(save->wakeen1, base + SA1111_WAKEEN1); + spin_unlock_irqrestore(&sachip->lock, flags); + + kfree(save); + + return 0; +} + +static struct device_driver sa1111_device_driver = { + .suspend = sa1111_suspend, + .resume = sa1111_resume, +}; + +/* + * Get the parent device driver (us) structure + * from a child function device + */ +static inline struct sa1111 *sa1111_chip_driver(struct sa1111_dev *sadev) +{ + return (struct sa1111 *)sadev->dev.parent->driver_data; +} + +/* + * The bits in the opdiv field are non-linear. + */ +static unsigned char opdiv_table[] = { 1, 4, 2, 8 }; + +static unsigned int __sa1111_pll_clock(struct sa1111 *sachip) +{ + unsigned int skcdr, fbdiv, ipdiv, opdiv; + + skcdr = sa1111_readl(sachip->base + SA1111_SKCDR); + + fbdiv = (skcdr & 0x007f) + 2; + ipdiv = ((skcdr & 0x0f80) >> 7) + 2; + opdiv = opdiv_table[(skcdr & 0x3000) >> 12]; + + return 3686400 * fbdiv / (ipdiv * opdiv); +} + +/** + * sa1111_pll_clock - return the current PLL clock frequency. + * @sadev: SA1111 function block + * + * BUG: we should look at SKCR. We also blindly believe that + * the chip is being fed with the 3.6864MHz clock. + * + * Returns the PLL clock in Hz. + */ +unsigned int sa1111_pll_clock(struct sa1111_dev *sadev) +{ + struct sa1111 *sachip = sa1111_chip_driver(sadev); + + return __sa1111_pll_clock(sachip); +} + +/** + * sa1111_select_audio_mode - select I2S or AC link mode + * @sadev: SA1111 function block + * @mode: One of %SA1111_AUDIO_ACLINK or %SA1111_AUDIO_I2S + * + * Frob the SKCR to select AC Link mode or I2S mode for + * the audio block. + */ +void sa1111_select_audio_mode(struct sa1111_dev *sadev, int mode) +{ + struct sa1111 *sachip = sa1111_chip_driver(sadev); + unsigned long flags; + unsigned int val; + + spin_lock_irqsave(&sachip->lock, flags); + + val = sa1111_readl(sachip->base + SA1111_SKCR); + if (mode == SA1111_AUDIO_I2S) { + val &= ~SKCR_SELAC; + } else { + val |= SKCR_SELAC; + } + sa1111_writel(val, sachip->base + SA1111_SKCR); + + spin_unlock_irqrestore(&sachip->lock, flags); +} + +/** + * sa1111_set_audio_rate - set the audio sample rate + * @sadev: SA1111 SAC function block + * @rate: sample rate to select + */ +int sa1111_set_audio_rate(struct sa1111_dev *sadev, int rate) +{ + struct sa1111 *sachip = sa1111_chip_driver(sadev); + unsigned int div; + + if (sadev->devid != SA1111_DEVID_SAC) + return -EINVAL; + + div = (__sa1111_pll_clock(sachip) / 256 + rate / 2) / rate; + if (div == 0) + div = 1; + if (div > 128) + div = 128; + + sa1111_writel(div - 1, sachip->base + SA1111_SKAUD); + + return 0; +} + +/** + * sa1111_get_audio_rate - get the audio sample rate + * @sadev: SA1111 SAC function block device + */ +int sa1111_get_audio_rate(struct sa1111_dev *sadev) +{ + struct sa1111 *sachip = sa1111_chip_driver(sadev); + unsigned long div; + + if (sadev->devid != SA1111_DEVID_SAC) + return -EINVAL; + + div = sa1111_readl(sachip->base + SA1111_SKAUD) + 1; + + return __sa1111_pll_clock(sachip) / (256 * div); +} + +/* + * Individual device operations. + */ + +/** + * sa1111_enable_device - enable an on-chip SA1111 function block + * @sadev: SA1111 function block device to enable + */ +void sa1111_enable_device(struct sa1111_dev *sadev) +{ + struct sa1111 *sachip = sa1111_chip_driver(sadev); + unsigned long flags; + unsigned int val; + + spin_lock_irqsave(&sachip->lock, flags); + val = sa1111_readl(sachip->base + SA1111_SKPCR); + sa1111_writel(val | sadev->skpcr_mask, sachip->base + SA1111_SKPCR); + spin_unlock_irqrestore(&sachip->lock, flags); +} + +/** + * sa1111_disable_device - disable an on-chip SA1111 function block + * @sadev: SA1111 function block device to disable + */ +void sa1111_disable_device(struct sa1111_dev *sadev) +{ + struct sa1111 *sachip = sa1111_chip_driver(sadev); + unsigned long flags; + unsigned int val; + + spin_lock_irqsave(&sachip->lock, flags); + val = sa1111_readl(sachip->base + SA1111_SKPCR); + sa1111_writel(val & ~sadev->skpcr_mask, sachip->base + SA1111_SKPCR); + spin_unlock_irqrestore(&sachip->lock, flags); +} + +/* + * SA1111 "Register Access Bus." + * + * We model this as a regular bus type, and hang devices directly + * off this. + */ +static int sa1111_match(struct device *_dev, struct device_driver *_drv) +{ + struct sa1111_dev *dev = SA1111_DEV(_dev); + struct sa1111_driver *drv = SA1111_DRV(_drv); + + return dev->devid == drv->devid; +} + +struct bus_type sa1111_bus_type = { + .name = "RAB", + .match = sa1111_match, +}; + +static int sa1111_rab_bus_init(void) +{ + return bus_register(&sa1111_bus_type); +} + +postcore_initcall(sa1111_rab_bus_init); + +EXPORT_SYMBOL(sa1111_check_dma_bug); +EXPORT_SYMBOL(sa1111_select_audio_mode); +EXPORT_SYMBOL(sa1111_set_audio_rate); +EXPORT_SYMBOL(sa1111_get_audio_rate); +EXPORT_SYMBOL(sa1111_enable_device); +EXPORT_SYMBOL(sa1111_disable_device); +EXPORT_SYMBOL(sa1111_pll_clock); +EXPORT_SYMBOL(sa1111_bus_type); diff --git a/arch/arm/mach-sa1100/sa1111.h b/arch/arm/mach-sa1100/sa1111.h deleted file mode 100644 index e3a13f66dd13ec33b66c0f542b0d65f2eba8ea07..0000000000000000000000000000000000000000 --- a/arch/arm/mach-sa1100/sa1111.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * linux/arch/arm/mach-sa1100/sa1111.h - */ -struct device; - -/* - * Probe for a SA1111 chip. - */ -extern int -sa1111_init(struct device *parent, unsigned long phys, unsigned int irq); - -/* - * Wake up a SA1111 chip. - */ -extern void sa1111_wake(void); - -/* - * Doze the SA1111 chip. - */ -extern void sa1111_doze(void); diff --git a/arch/arm/mach-sa1100/stork.c b/arch/arm/mach-sa1100/stork.c index 677be2dfb5ed443234cdb5494694fd7dba3bdbe4..703a513a94d0a0129ed1339e8e7a5b36a8389b59 100644 --- a/arch/arm/mach-sa1100/stork.c +++ b/arch/arm/mach-sa1100/stork.c @@ -284,6 +284,17 @@ storkInitTSandDtoA(void) storkClockShortToDtoA(0x0A00); /* turn on the brightness */ } +static void stork_lcd_power(int on) +{ + if (on) { + storkSetLCDCPLD(0, 1); + storkSetLatchA(STORK_LCD_BACKLIGHT_INVERTER_ON); + } else { + storkSetLCDCPLD(0, 0); + storkClearLatchA(STORK_LCD_BACKLIGHT_INVERTER_ON); + } +} + struct map_desc stork_io_desc[] __initdata = { /* virtual physical length type */ { STORK_VM_BASE_CS1, STORK_VM_OFF_CS1, 0x01000000, MT_DEVICE }, /* EGPIO 0 */ @@ -312,6 +323,8 @@ stork_map_io(void) storkInitTSandDtoA(); + sa1100fb_lcd_power = stork_lcd_power; + return 0; } diff --git a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c index 0629aa5420ce30cb711f76b70c3ac573a93ec092..d0dc614b0b875438d48df8a47e4f0466e48d2584 100644 --- a/arch/arm/mach-sa1100/system3.c +++ b/arch/arm/mach-sa1100/system3.c @@ -56,7 +56,6 @@ #include <linux/serial_core.h> #include "generic.h" -#include "sa1111.h" #include <asm/hardware/sa1111.h> #define DEBUG 1 @@ -401,7 +400,7 @@ static int __init system3_init(void) /* * Probe for a SA1111. */ - ret = sa1111_init(NULL, PT_SA1111_BASE, IRQ_SYSTEM3_SA1111); + ret = sa1111_init(PT_SA1111_BASE, IRQ_SYSTEM3_SA1111); if (ret < 0) { printk( KERN_WARNING"PT Digital Board: no SA1111 found!\n" ); goto DONE; diff --git a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c index 2feafb6d40dc60d8038f09bf650c672398486eb4..4099f44532b94d9ae2605859e25869124963bfc1 100644 --- a/arch/arm/mm/fault-common.c +++ b/arch/arm/mm/fault-common.c @@ -35,7 +35,7 @@ #else /* * "code" is actually the FSR register. Bit 11 set means the - * isntruction was performing a write. + * instruction was performing a write. */ #define DO_COW(code) ((code) & (1 << 11)) #define READ_FAULT(code) (!DO_COW(code)) @@ -54,7 +54,7 @@ void show_pte(struct mm_struct *mm, unsigned long addr) printk(KERN_ALERT "pgd = %p\n", mm->pgd); pgd = pgd_offset(mm, addr); - printk(KERN_ALERT "*pgd=%08lx", pgd_val(*pgd)); + printk(KERN_ALERT "[%08lx] *pgd=%08lx", addr, pgd_val(*pgd)); do { pmd_t *pmd; diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 39e28f1969189a38d1efbfe67393b22a66286498..9b8c9551fb87c923ddd6027cd3832cf7fc7b3d09 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -6,7 +6,7 @@ # To add an entry into this database, please see Documentation/arm/README, # or contact rmk@arm.linux.org.uk # -# Last update: Sat Jul 27 09:56:53 2002 +# Last update: Sat Sep 21 13:39:13 2002 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -214,3 +214,31 @@ emailphone SA1100_EMAILPHONE EMAILPHONE 202 h3900 ARCH_H3900 H3900 203 pxa1 ARCH_PXA1 PXA1 204 koan369 SA1100_KOAN369 KOAN369 205 +cogent ARCH_COGENT COGENT 206 +esl_simputer ARCH_ESL_SIMPUTER ESL_SIMPUTER 207 +esl_simputer_clr ARCH_ESL_SIMPUTER_CLR ESL_SIMPUTER_CLR 208 +esl_simputer_bw ARCH_ESL_SIMPUTER_BW ESL_SIMPUTER_BW 209 +hhp_cradle ARCH_HHP_CRADLE HHP_CRADLE 210 +he500 ARCH_HE500 HE500 211 +inhandelf2 SA1100_INHANDELF2 INHANDELF2 212 +inhandftip SA1100_INHANDFTIP INHANDFTIP 213 +dnp1110 SA1100_DNP1110 DNP1110 214 +pnp1110 SA1100_PNP1110 PNP1110 215 +csb226 ARCH_CSB226 CSB226 216 +arnold SA1100_ARNOLD ARNOLD 217 +psiboard SA1100_PSIBOARD PSIBOARD 218 +jz8028 ARCH_JZ8028 JZ8028 219 +ipaq3 ARCH_IPAQ3 IPAQ3 220 +forte SA1100_FORTE FORTE 221 +acam SA1100_ACAM ACAM 222 +abox SA1100_ABOX ABOX 223 +atmel ARCH_ATMEL ATMEL 224 +sitsang ARCH_SITSANG SITSANG 225 +cpu1110lcdnet SA1100_CPU1110LCDNET CPU1110LCDNET 226 +mpl_vcma9 ARCH_MPL_VCMA9 MPL_VCMA9 227 +opus_a1 ARCH_OPUS_A1 OPUS_A1 228 +daytona ARCH_DAYTONA DAYTONA 229 +killbear SA1100_KILLBEAR KILLBEAR 230 +yoho ARCH_YOHO YOHO 231 +jasper ARCH_JASPER JASPER 232 +dsc25 ARCH_DSC25 DSC25 233 diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index da568810512865ed2d2fade7fedc5758e2423840..502d3c90b86428d150e53b57abc0ea590c664e69 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c @@ -15,20 +15,26 @@ #include <linux/ioport.h> #include <linux/delay.h> #include <linux/device.h> +#include <linux/slab.h> +#include <linux/spinlock.h> -#include <asm/hardware/sa1111.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/system.h> +#include <asm/hardware/sa1111.h> + extern struct pt_regs *kbd_pt_regs; struct ps2if { - struct serio io; - struct resource *res; - unsigned long base; - unsigned int irq; - unsigned int skpcr_mask; + struct serio io; + struct sa1111_dev *dev; + unsigned long base; + unsigned int open; + spinlock_t lock; + unsigned int head; + unsigned int tail; + unsigned char buf[4]; }; /* @@ -36,104 +42,150 @@ struct ps2if { * at the most one, but we loop for safety. If there was a * framing error, we have to manually clear the status. */ -static void ps2_int(int irq, void *dev_id, struct pt_regs *regs) +static void ps2_rxint(int irq, void *dev_id, struct pt_regs *regs) { - struct ps2if *sa = dev_id; + struct ps2if *ps2if = dev_id; unsigned int scancode, flag, status; kbd_pt_regs = regs; - status = sa1111_readl(sa->base + SA1111_PS2STAT); + status = sa1111_readl(ps2if->base + SA1111_PS2STAT); while (status & PS2STAT_RXF) { if (status & PS2STAT_STP) - sa1111_writel(PS2STAT_STP, sa->base + SA1111_PS2STAT); + sa1111_writel(PS2STAT_STP, ps2if->base + SA1111_PS2STAT); flag = (status & PS2STAT_STP ? SERIO_FRAME : 0) | (status & PS2STAT_RXP ? 0 : SERIO_PARITY); - scancode = sa1111_readl(sa->base + SA1111_PS2DATA) & 0xff; + scancode = sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff; if (hweight8(scancode) & 1) flag ^= SERIO_PARITY; - serio_interrupt(&sa->io, scancode, flag); + serio_interrupt(&ps2if->io, scancode, flag); - status = sa1111_readl(sa->base + SA1111_PS2STAT); + status = sa1111_readl(ps2if->base + SA1111_PS2STAT); } } +/* + * Completion of ps2 write + */ +static void ps2_txint(int irq, void *dev_id, struct pt_regs *regs) +{ + struct ps2if *ps2if = dev_id; + unsigned int status; + + spin_lock(&ps2if->lock); + status = sa1111_readl(ps2if->base + SA1111_PS2STAT); + if (ps2if->head == ps2if->tail) { + disable_irq(irq); + /* done */ + } else if (status & PS2STAT_TXE) { + sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + SA1111_PS2DATA); + ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1); + } + spin_unlock(&ps2if->lock); +} + /* * Write a byte to the PS2 port. We have to wait for the * port to indicate that the transmitter is empty. */ static int ps2_write(struct serio *io, unsigned char val) { - struct ps2if *sa = io->driver; - unsigned int timeleft = 10000; /* timeout in 100ms */ + struct ps2if *ps2if = io->driver; + unsigned long flags; + unsigned int head; - while ((sa1111_readl(sa->base + SA1111_PS2STAT) & PS2STAT_TXE) == 0 && - timeleft--) - udelay(10); + spin_lock_irqsave(&ps2if->lock, flags); - if (timeleft) - sa1111_writel(val, sa->base + SA1111_PS2DATA); + /* + * If the TX register is empty, we can go straight out. + */ + if (sa1111_readl(ps2if->base + SA1111_PS2STAT) & PS2STAT_TXE) { + sa1111_writel(val, ps2if->base + SA1111_PS2DATA); + } else { + if (ps2if->head == ps2if->tail) + enable_irq(ps2if->dev->irq[1]); + head = (ps2if->head + 1) & (sizeof(ps2if->buf) - 1); + if (head != ps2if->tail) { + ps2if->buf[ps2if->head] = val; + ps2if->head = head; + } + } - return timeleft ? 0 : SERIO_TIMEOUT; + spin_unlock_irqrestore(&ps2if->lock, flags); + return 0; } static int ps2_open(struct serio *io) { - struct ps2if *sa = io->driver; + struct ps2if *ps2if = io->driver; int ret; - sa1111_enable_device(sa->skpcr_mask); + sa1111_enable_device(ps2if->dev); - ret = request_irq(sa->irq, ps2_int, 0, "ps2", sa); + ret = request_irq(ps2if->dev->irq[0], ps2_rxint, 0, + SA1111_DRIVER_NAME(ps2if->dev), ps2if); if (ret) { printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n", - sa->irq, ret); + ps2if->dev->irq[0], ret); return ret; } - sa1111_writel(PS2CR_ENA, sa->base + SA1111_PS2CR); + ret = request_irq(ps2if->dev->irq[1], ps2_txint, 0, + SA1111_DRIVER_NAME(ps2if->dev), ps2if); + if (ret) { + printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n", + ps2if->dev->irq[1], ret); + free_irq(ps2if->dev->irq[0], ps2if); + return ret; + } + ps2if->open = 1; + + sa1111_writel(PS2CR_ENA, ps2if->base + SA1111_PS2CR); return 0; } static void ps2_close(struct serio *io) { - struct ps2if *sa = io->driver; + struct ps2if *ps2if = io->driver; + + sa1111_writel(0, ps2if->base + SA1111_PS2CR); - sa1111_writel(0, sa->base + SA1111_PS2CR); + ps2if->open = 0; - free_irq(sa->irq, sa); + free_irq(ps2if->dev->irq[1], ps2if); + free_irq(ps2if->dev->irq[0], ps2if); - sa1111_disable_device(sa->skpcr_mask); + sa1111_disable_device(ps2if->dev); } /* * Clear the input buffer. */ -static void __init ps2_clear_input(struct ps2if *sa) +static void __init ps2_clear_input(struct ps2if *ps2if) { int maxread = 100; while (maxread--) { - if ((sa1111_readl(sa->base + SA1111_PS2DATA) & 0xff) == 0xff) + if ((sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff) == 0xff) break; } } static inline unsigned int -ps2_test_one(struct ps2if *sa, unsigned int mask) +ps2_test_one(struct ps2if *ps2if, unsigned int mask) { unsigned int val; - sa1111_writel(PS2CR_ENA | mask, sa->base + SA1111_PS2CR); + sa1111_writel(PS2CR_ENA | mask, ps2if->base + SA1111_PS2CR); udelay(2); - val = sa1111_readl(sa->base + SA1111_PS2STAT); + val = sa1111_readl(ps2if->base + SA1111_PS2STAT); return val & (PS2STAT_KBC | PS2STAT_KBD); } @@ -141,141 +193,168 @@ ps2_test_one(struct ps2if *sa, unsigned int mask) * Test the keyboard interface. We basically check to make sure that * we can drive each line to the keyboard independently of each other. */ -static int __init ps2_test(struct ps2if *sa) +static int __init ps2_test(struct ps2if *ps2if) { unsigned int stat; int ret = 0; - stat = ps2_test_one(sa, PS2CR_FKC); + stat = ps2_test_one(ps2if, PS2CR_FKC); if (stat != PS2STAT_KBD) { - printk("Keyboard interface test failed[1]: %02x\n", stat); + printk("PS/2 interface test failed[1]: %02x\n", stat); ret = -ENODEV; } - stat = ps2_test_one(sa, 0); + stat = ps2_test_one(ps2if, 0); if (stat != (PS2STAT_KBC | PS2STAT_KBD)) { - printk("Keyboard interface test failed[2]: %02x\n", stat); + printk("PS/2 interface test failed[2]: %02x\n", stat); ret = -ENODEV; } - stat = ps2_test_one(sa, PS2CR_FKD); + stat = ps2_test_one(ps2if, PS2CR_FKD); if (stat != PS2STAT_KBC) { - printk("Keyboard interface test failed[3]: %02x\n", stat); + printk("PS/2 interface test failed[3]: %02x\n", stat); ret = -ENODEV; } - sa1111_writel(0, sa->base + SA1111_PS2CR); + sa1111_writel(0, ps2if->base + SA1111_PS2CR); return ret; } /* - * Initialise one PS/2 port. + * Add one device to this driver. */ -static int __init ps2_init_one(struct sa1111_device *dev, struct ps2if *sa) +static int ps2_probe(struct device *dev) { + struct sa1111_dev *sadev = SA1111_DEV(dev); + struct ps2if *ps2if; int ret; + ps2if = kmalloc(sizeof(struct ps2if), GFP_KERNEL); + if (!ps2if) { + return -ENOMEM; + } + + memset(ps2if, 0, sizeof(struct ps2if)); + + ps2if->io.type = SERIO_8042; + ps2if->io.write = ps2_write; + ps2if->io.open = ps2_open; + ps2if->io.close = ps2_close; + ps2if->io.name = dev->name; + ps2if->io.phys = dev->bus_id; + ps2if->io.driver = ps2if; + ps2if->dev = sadev; + dev->driver_data = ps2if; + + spin_lock_init(&ps2if->lock); + /* * Request the physical region for this PS2 port. */ - sa->res = request_mem_region(_SA1111(sa->base), 512, "ps2"); - if (!sa->res) - return -EBUSY; + if (!request_mem_region(sadev->res.start, + sadev->res.end - sadev->res.start + 1, + SA1111_DRIVER_NAME(sadev))) { + ret = -EBUSY; + goto free; + } /* - * Convert the chip offset to virtual address. + * Our parent device has already mapped the region. */ - sa->base += (unsigned long)dev->base; + ps2if->base = (unsigned long)sadev->mapbase; - sa1111_enable_device(sa->skpcr_mask); + sa1111_enable_device(ps2if->dev); /* Incoming clock is 8MHz */ - sa1111_writel(0, sa->base + SA1111_PS2CLKDIV); - sa1111_writel(127, sa->base + SA1111_PS2PRECNT); + sa1111_writel(0, ps2if->base + SA1111_PS2CLKDIV); + sa1111_writel(127, ps2if->base + SA1111_PS2PRECNT); /* * Flush any pending input. */ - ps2_clear_input(sa); + ps2_clear_input(ps2if); /* * Test the keyboard interface. */ - ret = ps2_test(sa); + ret = ps2_test(ps2if); if (ret) goto out; /* * Flush any pending input. */ - ps2_clear_input(sa); - sa1111_disable_device(sa->skpcr_mask); + ps2_clear_input(ps2if); - serio_register_port(&sa->io); + sa1111_disable_device(ps2if->dev); + serio_register_port(&ps2if->io); return 0; out: - sa1111_disable_device(sa->skpcr_mask); - release_resource(sa->res); + sa1111_disable_device(ps2if->dev); + release_mem_region(sadev->res.start, + sadev->res.end - sadev->res.start + 1); + free: + dev->driver_data = NULL; + kfree(ps2if); return ret; } /* - * Remove one PS/2 port. + * Remove one device from this driver. */ -static void __exit ps2_remove_one(struct ps2if *sa) +static int ps2_remove(struct device *dev) { - serio_unregister_port(&sa->io); - release_resource(sa->res); + struct ps2if *ps2if = dev->driver_data; + struct sa1111_dev *sadev = SA1111_DEV(dev); + + serio_unregister_port(&ps2if->io); + release_mem_region(sadev->res.start, + sadev->res.end - sadev->res.start + 1); + kfree(ps2if); + + dev->driver_data = NULL; + + return 0; } -static struct ps2if ps2_kbd_port = +/* + * We should probably do something here, but what? + */ +static int ps2_suspend(struct device *dev, u32 state, u32 level) { - io: { - type: SERIO_8042, - write: ps2_write, - open: ps2_open, - close: ps2_close, - name: "SA1111 PS/2 kbd port", - phys: "sa1111/serio0", - driver: &ps2_kbd_port, - }, - base: SA1111_KBD, - irq: IRQ_TPRXINT, - skpcr_mask: SKPCR_PTCLKEN, -}; + return 0; +} -static struct ps2if ps2_mse_port = +static int ps2_resume(struct device *dev, u32 level) { - io: { - type: SERIO_8042, - write: ps2_write, - open: ps2_open, - close: ps2_close, - name: "SA1111 PS/2 mouse port", - phys: "sa1111/serio1", - driver: &ps2_mse_port, + return 0; +} + +/* + * Our device driver structure + */ +static struct sa1111_driver ps2_driver = { + .drv = { + .name = "SA1111 PS2", + .bus = &sa1111_bus_type, + .probe = ps2_probe, + .remove = ps2_remove, + .suspend = ps2_suspend, + .resume = ps2_resume, }, - base: SA1111_MSE, - irq: IRQ_MSRXINT, - skpcr_mask: SKPCR_PMCLKEN, + .devid = SA1111_DEVID_PS2, }; static int __init ps2_init(void) { - int ret = -ENODEV; - - if (sa1111) { - ret = ps2_init_one(sa1111, &ps2_kbd_port); - } - - return ret; + return driver_register(&ps2_driver.drv); } static void __exit ps2_exit(void) { - ps2_remove_one(&ps2_kbd_port); + remove_driver(&ps2_driver.drv); } module_init(ps2_init); diff --git a/drivers/pcmcia/Config.in b/drivers/pcmcia/Config.in index 56866d225c48eeba30dd8b6b71ee7ff3710748a0..4f8bfb54642450cf9e0c19f66bb815568616c3d5 100644 --- a/drivers/pcmcia/Config.in +++ b/drivers/pcmcia/Config.in @@ -20,6 +20,7 @@ if [ "$CONFIG_PCMCIA" != "n" ]; then fi if [ "$CONFIG_ARM" = "y" ]; then dep_tristate ' SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_PCMCIA + dep_tristate ' SA1111 support' CONFIG_PCMCIA_SA1111 $CONFIG_PCMCIA_SA1100 $CONFIG_SA1111 $CONFIG_PCMCIA fi fi diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 497523e5f7b1c6743f7d71322311435bebfcb04f..734b5a5cec438bae5d710dd16a2df275a9371fbc 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_I82092) += i82092.o obj-$(CONFIG_TCIC) += tcic.o obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o +obj-$(CONFIG_PCMCIA_SA1111) += sa1111_cs.o yenta_socket-objs := pci_socket.o yenta.o @@ -21,26 +22,29 @@ pcmcia_core-objs-y := cistpl.o rsrc_mgr.o bulkmem.o cs.o pcmcia_core-objs-$(CONFIG_CARDBUS) += cardbus.o pcmcia_core-objs := $(pcmcia_core-objs-y) +sa1111_cs-objs-y := sa1111_generic.o +sa1111_cs-objs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o +sa1111_cs-objs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o +sa1111_cs-objs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o +sa1111_cs-objs-$(CONFIG_SA1100_GRAPHICSMASTER) += sa1100_graphicsmaster.o +sa1111_cs-objs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o +sa1111_cs-objs-$(CONFIG_SA1100_PFS168) += sa1100_pfs168.o +sa1111_cs-objs-$(CONFIG_SA1100_PT_SYSTEM3) += sa1100_system3.o +sa1111_cs-objs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o +sa1111_cs-objs := $(sa1111_cs-objs-y) + sa1100_cs-objs-y := sa1100_generic.o -sa1100_cs-objs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o sa1111_generic.o sa1100_cs-objs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o -sa1100_cs-objs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o sa1111_generic.o -sa1100_cs-objs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o sa1111_generic.o sa1100_cs-objs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o sa1100_cs-objs-$(CONFIG_SA1100_FLEXANET) += sa1100_flexanet.o sa1100_cs-objs-$(CONFIG_SA1100_FREEBIRD) += sa1100_freebird.o -sa1100_cs-objs-$(CONFIG_SA1100_GRAPHICSMASTER) += sa1100_graphicsmaster.o sa1111_generic.o sa1100_cs-objs-$(CONFIG_SA1100_GRAPHICSCLIENT) += sa1100_graphicsclient.o sa1100_cs-objs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o -sa1100_cs-objs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o sa1111_generic.o sa1100_cs-objs-$(CONFIG_SA1100_PANGOLIN) += sa1100_pangolin.o -sa1100_cs-objs-$(CONFIG_SA1100_PFS168) += sa1100_pfs168.o sa1111_generic.o -sa1100_cs-objs-$(CONFIG_SA1100_PT_SYSTEM3) += sa1100_system3.o sa1111_generic.o sa1100_cs-objs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o sa1100_cs-objs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o sa1100_cs-objs-$(CONFIG_SA1100_STORK) += sa1100_stork.o sa1100_cs-objs-$(CONFIG_SA1100_TRIZEPS) += sa1100_trizeps.o -sa1100_cs-objs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o sa1111_generic.o sa1100_cs-objs-$(CONFIG_SA1100_YOPY) += sa1100_yopy.o sa1100_cs-objs := $(sa1100_cs-objs-y) diff --git a/drivers/pcmcia/sa1100_adsbitsy.c b/drivers/pcmcia/sa1100_adsbitsy.c index 17d87ab2e2a4ca7e14f582d2bf212040723715f4..202524e4c354d9328c095557cc753836b2195eba 100644 --- a/drivers/pcmcia/sa1100_adsbitsy.c +++ b/drivers/pcmcia/sa1100_adsbitsy.c @@ -14,6 +14,7 @@ #include <linux/init.h> #include <asm/hardware.h> +#include <asm/mach-types.h> #include "sa1100_generic.h" #include "sa1111_generic.h" diff --git a/drivers/pcmcia/sa1100_badge4.c b/drivers/pcmcia/sa1100_badge4.c index 546ec5d95102725062d5907780177f3f4339594d..77174645d6c1155d38d6478624d3e30f0758f0ae 100644 --- a/drivers/pcmcia/sa1100_badge4.c +++ b/drivers/pcmcia/sa1100_badge4.c @@ -19,6 +19,7 @@ #include <linux/init.h> #include <asm/hardware.h> +#include <asm/mach-types.h> #include <asm/arch/badge4.h> #include <asm/hardware/sa1111.h> diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c index 12dc9270e402757e05189c7748cf9b19229e1ff4..47f364fbc97b0988b8e950c261ecaa12f7fba9d2 100644 --- a/drivers/pcmcia/sa1100_generic.c +++ b/drivers/pcmcia/sa1100_generic.c @@ -110,12 +110,11 @@ sa1100_pcmcia_default_mecr_timing(unsigned int sock, unsigned int cpu_speed, * Call board specific BS value calculation to allow boards * to tweak the BS values. */ -static int sa1100_pcmcia_set_mecr(int sock) +static int sa1100_pcmcia_set_mecr(int sock, unsigned int cpu_clock) { struct sa1100_pcmcia_socket *skt; u32 mecr; - int clock; - long flags; + unsigned long flags; unsigned int bs; if (sock < 0 || sock > SA1100_PCMCIA_MAX_SOCK) @@ -125,8 +124,7 @@ static int sa1100_pcmcia_set_mecr(int sock) local_irq_save(flags); - clock = cpufreq_get(0); - bs = pcmcia_low_level->socket_get_timing(sock, clock, skt->speed_io); + bs = pcmcia_low_level->socket_get_timing(sock, cpu_clock, skt->speed_io); mecr = MECR; MECR_FAST_SET(mecr, sock, 0); @@ -652,7 +650,7 @@ sa1100_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map) if ( map->speed == 0) map->speed = SA1100_PCMCIA_IO_ACCESS; - sa1100_pcmcia_set_mecr( sock ); + sa1100_pcmcia_set_mecr(sock, cpufreq_get(0)); } if (map->stop == 1) @@ -741,7 +739,7 @@ sa1100_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map) map->speed = SA1100_PCMCIA_5V_MEM_ACCESS; } - sa1100_pcmcia_set_mecr( sock ); + sa1100_pcmcia_set_mecr(sock, cpufreq_get(0)); } @@ -885,9 +883,8 @@ static void sa1100_pcmcia_update_mecr(unsigned int clock) { unsigned int sock; - for (sock = 0; sock < SA1100_PCMCIA_MAX_SOCK; ++sock) { - sa1100_pcmcia_set_mecr(sock); - } + for (sock = 0; sock < SA1100_PCMCIA_MAX_SOCK; ++sock) + sa1100_pcmcia_set_mecr(sock, clock); } /* sa1100_pcmcia_notifier() @@ -904,31 +901,31 @@ static int sa1100_pcmcia_notifier(struct notifier_block *nb, unsigned long val, void *data) { - struct cpufreq_info *ci = data; - - switch (val) { - case CPUFREQ_PRECHANGE: - if (ci->new_freq > ci->old_freq) { - DEBUG(2, "%s(): new frequency %u.%uMHz > %u.%uMHz, pre-updating\n", - __FUNCTION__, - ci->new_freq / 1000, (ci->new_freq / 100) % 10, - ci->old_freq / 1000, (ci->old_freq / 100) % 10); - sa1100_pcmcia_update_mecr(ci->new_freq); - } - break; - - case CPUFREQ_POSTCHANGE: - if (ci->new_freq < ci->old_freq) { - DEBUG(2, "%s(): new frequency %u.%uMHz < %u.%uMHz, post-updating\n", - __FUNCTION__, - ci->new_freq / 1000, (ci->new_freq / 100) % 10, - ci->old_freq / 1000, (ci->old_freq / 100) % 10); - sa1100_pcmcia_update_mecr(ci->new_freq); - } - break; - } + struct cpufreq_freqs *freqs = data; + + switch (val) { + case CPUFREQ_PRECHANGE: + if (freqs->new > freqs->old) { + DEBUG(2, "%s(): new frequency %u.%uMHz > %u.%uMHz, " + "pre-updating\n", __FUNCTION__, + freqs->new / 1000, (freqs->new / 100) % 10, + freqs->old / 1000, (freqs->old / 100) % 10); + sa1100_pcmcia_update_mecr(freqs->new); + } + break; + + case CPUFREQ_POSTCHANGE: + if (freqs->new < freqs->old) { + DEBUG(2, "%s(): new frequency %u.%uMHz < %u.%uMHz, " + "post-updating\n", __FUNCTION__, + freqs->new / 1000, (freqs->new / 100) % 10, + freqs->old / 1000, (freqs->old / 100) % 10); + sa1100_pcmcia_update_mecr(freqs->new); + } + break; + } - return 0; + return 0; } static struct notifier_block sa1100_pcmcia_notifier_block = { @@ -946,7 +943,7 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops) struct pcmcia_init pcmcia_init; struct pcmcia_state state[SA1100_PCMCIA_MAX_SOCK]; struct pcmcia_state_array state_array; - unsigned int i; + unsigned int i, cpu_clock; int ret; /* @@ -986,6 +983,8 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops) goto shutdown; } + cpu_clock = cpufreq_get(0); + /* * We initialize the MECR to default values here, because we are * not guaranteed to see a SetIOMap operation at runtime. @@ -1019,7 +1018,7 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops) goto out_err; } - sa1100_pcmcia_set_mecr( i ); + sa1100_pcmcia_set_mecr(i, cpu_clock); } @@ -1110,7 +1109,7 @@ static int __init sa1100_pcmcia_init(void) servinfo_t info; int ret, i; - printk(KERN_INFO "SA-1100 PCMCIA (CS release %s)\n", CS_RELEASE); + printk(KERN_INFO "SA11x0 PCMCIA (CS release %s)\n", CS_RELEASE); CardServices(GetCardServicesInfo, &info); if (info.Revision != CS_RELEASE_CODE) { @@ -1127,7 +1126,8 @@ static int __init sa1100_pcmcia_init(void) } #ifdef CONFIG_CPU_FREQ - ret = cpufreq_register_notifier(&sa1100_pcmcia_notifier_block); + ret = cpufreq_register_notifier(&sa1100_pcmcia_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); if (ret < 0) { printk(KERN_ERR "Unable to register CPU frequency change " "notifier (%d)\n", ret); @@ -1135,15 +1135,9 @@ static int __init sa1100_pcmcia_init(void) } #endif -#ifdef CONFIG_SA1100_ADSBITSY - pcmcia_adsbitsy_init(); -#endif #ifdef CONFIG_SA1100_ASSABET pcmcia_assabet_init(); #endif -#ifdef CONFIG_SA1100_BADGE4 - pcmcia_badge4_init(); -#endif #ifdef CONFIG_SA1100_CERF pcmcia_cerf_init(); #endif @@ -1156,24 +1150,9 @@ static int __init sa1100_pcmcia_init(void) #ifdef CONFIG_SA1100_GRAPHICSCLIENT pcmcia_gcplus_init(); #endif -#ifdef CONFIG_SA1100_GRAPHICSMASTER - pcmcia_graphicsmaster_init(); -#endif -#ifdef CONFIG_SA1100_JORNADA720 - pcmcia_jornada720_init(); -#endif -#ifdef CONFIG_ASSABET_NEPONSET - pcmcia_neponset_init(); -#endif #ifdef CONFIG_SA1100_PANGOLIN pcmcia_pangolin_init(); #endif -#ifdef CONFIG_SA1100_PFS168 - pcmcia_pfs_init(); -#endif -#ifdef CONFIG_SA1100_PT_SYSTEM3 - pcmcia_system3_init(); -#endif #ifdef CONFIG_SA1100_SHANNON pcmcia_shannon_init(); #endif @@ -1186,9 +1165,6 @@ static int __init sa1100_pcmcia_init(void) #ifdef CONFIG_SA1100_TRIZEPS pcmcia_trizeps_init(); #endif -#ifdef CONFIG_SA1100_XP860 - pcmcia_xp860_init(); -#endif #ifdef CONFIG_SA1100_YOPY pcmcia_yopy_init(); #endif @@ -1203,15 +1179,9 @@ static int __init sa1100_pcmcia_init(void) */ static void __exit sa1100_pcmcia_exit(void) { -#ifdef CONFIG_SA1100_ADSBITSY - pcmcia_adsbitsy_exit(); -#endif #ifdef CONFIG_SA1100_ASSABET pcmcia_assabet_exit(); #endif -#ifdef CONFIG_SA1100_BADGE4 - pcmcia_badge4_exit(); -#endif #ifdef CONFIG_SA1100_CERF pcmcia_cerf_exit(); #endif @@ -1224,21 +1194,9 @@ static void __exit sa1100_pcmcia_exit(void) #ifdef CONFIG_SA1100_GRAPHICSCLIENT pcmcia_gcplus_exit(); #endif -#ifdef CONFIG_SA1100_GRAPHICSMASTER - pcmcia_graphicsmaster_exit(); -#endif -#ifdef CONFIG_SA1100_JORNADA720 - pcmcia_jornada720_exit(); -#endif -#ifdef CONFIG_ASSABET_NEPONSET - pcmcia_neponset_exit(); -#endif #ifdef CONFIG_SA1100_PANGOLIN pcmcia_pangolin_exit(); #endif -#ifdef CONFIG_SA1100_PFS168 - pcmcia_pfs_exit(); -#endif #ifdef CONFIG_SA1100_SHANNON pcmcia_shannon_exit(); #endif @@ -1248,9 +1206,6 @@ static void __exit sa1100_pcmcia_exit(void) #ifdef CONFIG_SA1100_STORK pcmcia_stork_exit(); #endif -#ifdef CONFIG_SA1100_XP860 - pcmcia_xp860_exit(); -#endif #ifdef CONFIG_SA1100_YOPY pcmcia_yopy_exit(); #endif @@ -1261,7 +1216,7 @@ static void __exit sa1100_pcmcia_exit(void) } #ifdef CONFIG_CPU_FREQ - cpufreq_unregister_notifier(&sa1100_pcmcia_notifier_block); + cpufreq_unregister_notifier(&sa1100_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); #endif } diff --git a/drivers/pcmcia/sa1100_graphicsmaster.c b/drivers/pcmcia/sa1100_graphicsmaster.c index 8aeafa167cffa12ee6136612fd43024f776ef43e..9552dfa55816753ff20d1f0571df12cf1f438035 100644 --- a/drivers/pcmcia/sa1100_graphicsmaster.c +++ b/drivers/pcmcia/sa1100_graphicsmaster.c @@ -13,6 +13,7 @@ #include <linux/init.h> #include <asm/hardware.h> +#include <asm/mach-types.h> #include "sa1100_generic.h" #include "sa1111_generic.h" diff --git a/drivers/pcmcia/sa1100_jornada720.c b/drivers/pcmcia/sa1100_jornada720.c index a5d07781929a5b27b2659b5f4bc1fee5d3d038f6..d15f51eedba68bbfda2a974b4b9f76ced133fc5c 100644 --- a/drivers/pcmcia/sa1100_jornada720.c +++ b/drivers/pcmcia/sa1100_jornada720.c @@ -9,6 +9,7 @@ #include <linux/init.h> #include <asm/hardware.h> +#include <asm/mach-types.h> #include "sa1100_generic.h" #include "sa1111_generic.h" diff --git a/drivers/pcmcia/sa1100_neponset.c b/drivers/pcmcia/sa1100_neponset.c index d8e09192bacc15116532dead9eee20cf64a4c068..12d6c5c662f967f3d9431970ee92a64477c1cb91 100644 --- a/drivers/pcmcia/sa1100_neponset.c +++ b/drivers/pcmcia/sa1100_neponset.c @@ -10,21 +10,50 @@ #include <linux/init.h> #include <asm/hardware.h> -#include <asm/arch/assabet.h> +#include <asm/mach-types.h> +#include <asm/arch/neponset.h> #include <asm/hardware/sa1111.h> #include "sa1100_generic.h" #include "sa1111_generic.h" +/* + * Neponset uses the Maxim MAX1600, with the following connections: + * + * MAX1600 Neponset + * + * A0VCC SA-1111 GPIO A<1> + * A1VCC SA-1111 GPIO A<0> + * A0VPP CPLD NCR A0VPP + * A1VPP CPLD NCR A1VPP + * B0VCC SA-1111 GPIO A<2> + * B1VCC SA-1111 GPIO A<3> + * B0VPP ground (slot B is CF) + * B1VPP ground (slot B is CF) + * + * VX VCC (5V) + * VY VCC3_3 (3.3V) + * 12INA 12V + * 12INB ground (slot B is CF) + * + * The MAX1600 CODE pin is tied to ground, placing the device in + * "Standard Intel code" mode. Refer to the Maxim data sheet for + * the corresponding truth table. + */ + static int neponset_pcmcia_init(struct pcmcia_init *init) { - /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */ - PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3); - - /* MAX1600 to standby mode: */ - PA_DWR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3); NCR_0 &= ~(NCR_A0VPP | NCR_A1VPP); + /* + * Set GPIO_A<3:0> to be outputs for the MAX1600, + * and switch to standby mode. + */ + PA_DDR = 0; + PA_SDR = 0; + PA_DWR = 0; + PA_SSR = 0; + return sa1111_pcmcia_init(init); } @@ -35,29 +64,6 @@ neponset_pcmcia_configure_socket(const struct pcmcia_configure *conf) unsigned int ncr_set, pa_dwr_set; int ret; - /* Neponset uses the Maxim MAX1600, with the following connections: - - * MAX1600 Neponset - * - * A0VCC SA-1111 GPIO A<1> - * A1VCC SA-1111 GPIO A<0> - * A0VPP CPLD NCR A0VPP - * A1VPP CPLD NCR A1VPP - * B0VCC SA-1111 GPIO A<2> - * B1VCC SA-1111 GPIO A<3> - * B0VPP ground (slot B is CF) - * B1VPP ground (slot B is CF) - * - * VX VCC (5V) - * VY VCC3_3 (3.3V) - * 12INA 12V - * 12INB ground (slot B is CF) - * - * The MAX1600 CODE pin is tied to ground, placing the device in - * "Standard Intel code" mode. Refer to the Maxim data sheet for - * the corresponding truth table. - */ - switch (conf->sock) { case 0: pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1; @@ -135,13 +141,13 @@ int __init pcmcia_neponset_init(void) { int ret = -ENODEV; - if (machine_is_assabet() && sa1111) + if (machine_is_assabet()) ret = sa1100_register_pcmcia(&neponset_pcmcia_ops); return ret; } -void __exit pcmcia_neponset_exit(void) +void __devexit pcmcia_neponset_exit(void) { sa1100_unregister_pcmcia(&neponset_pcmcia_ops); } diff --git a/drivers/pcmcia/sa1100_pfs168.c b/drivers/pcmcia/sa1100_pfs168.c index af028d61b6822fb40494c3cac5450e00299eceb4..511afebb38a38dad07d00e47cd92829bbcbcf134 100644 --- a/drivers/pcmcia/sa1100_pfs168.c +++ b/drivers/pcmcia/sa1100_pfs168.c @@ -7,10 +7,11 @@ */ #include <linux/kernel.h> #include <linux/sched.h> +#include <linux/delay.h> #include <linux/init.h> -#include <asm/delay.h> #include <asm/hardware.h> +#include <asm/mach-types.h> #include <asm/irq.h> #include "sa1100_generic.h" diff --git a/drivers/pcmcia/sa1100_system3.c b/drivers/pcmcia/sa1100_system3.c index fc4bed07c4a32747acc3c3f3723a8b422b36f54c..2ab0d4537d0dcd8227dd6e8e73e3bd050a156cfa 100644 --- a/drivers/pcmcia/sa1100_system3.c +++ b/drivers/pcmcia/sa1100_system3.c @@ -31,6 +31,7 @@ #include <linux/ioport.h> #include <asm/hardware.h> +#include <asm/mach-types.h> #include <asm/irq.h> #include <asm/hardware/sa1111.h> diff --git a/drivers/pcmcia/sa1100_xp860.c b/drivers/pcmcia/sa1100_xp860.c index 84c315a97cdd82fd45d997f4943f947dc24d6208..69d3f3ddaaccefb7f43bab5d4e257ad83d3c2b74 100644 --- a/drivers/pcmcia/sa1100_xp860.c +++ b/drivers/pcmcia/sa1100_xp860.c @@ -10,6 +10,7 @@ #include <linux/init.h> #include <asm/hardware.h> +#include <asm/mach-types.h> #include <asm/irq.h> #include "sa1100_generic.h" diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c index ef5a8b0bf153a1e1d906895f91443aa4cfd8256f..9bf1a6c392d46bf3e48e9d9d8ef99a59b3af5b57 100644 --- a/drivers/pcmcia/sa1111_generic.c +++ b/drivers/pcmcia/sa1111_generic.c @@ -5,10 +5,12 @@ * basically means we handle everything except controlling the * power. Power is machine specific... */ +#include <linux/module.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/ioport.h> #include <linux/device.h> +#include <linux/init.h> #include <asm/hardware.h> #include <asm/hardware/sa1111.h> @@ -21,19 +23,18 @@ static struct irqs { int irq; const char *str; } irqs[] = { - { S0_CD_VALID, "SA1111 PCMCIA card detect" }, - { S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1" }, - { S1_CD_VALID, "SA1111 CF card detect" }, - { S1_BVD1_STSCHG, "SA1111 CF BVD1" }, + { IRQ_S0_CD_VALID, "SA1111 PCMCIA card detect" }, + { IRQ_S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1" }, + { IRQ_S1_CD_VALID, "SA1111 CF card detect" }, + { IRQ_S1_BVD1_STSCHG, "SA1111 CF BVD1" }, }; +static struct sa1111_dev *pcmcia; + int sa1111_pcmcia_init(struct pcmcia_init *init) { int i, ret; - if (!request_mem_region(_PCCR, 512, "PCMCIA")) - return -1; - for (i = ret = 0; i < ARRAY_SIZE(irqs); i++) { set_irq_type(irqs[i].irq, IRQT_FALLING); ret = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT, @@ -47,8 +48,6 @@ int sa1111_pcmcia_init(struct pcmcia_init *init) irqs[i].irq, ret); while (i--) free_irq(irqs[i].irq, NULL); - - release_mem_region(_PCCR, 16); } return ret ? -1 : 2; @@ -61,8 +60,6 @@ int sa1111_pcmcia_shutdown(void) for (i = 0; i < ARRAY_SIZE(irqs); i++) free_irq(irqs[i].irq, NULL); - release_mem_region(_PCCR, 512); - return 0; } @@ -73,7 +70,7 @@ int sa1111_pcmcia_socket_state(struct pcmcia_state_array *state) if (state->size < 2) return -1; - status = PCSR; + status = sa1111_readl(pcmcia->mapbase + SA1111_PCSR); state->state[0].detect = status & PCSR_S0_DETECT ? 0 : 1; state->state[0].ready = status & PCSR_S0_READY ? 1 : 0; @@ -99,8 +96,8 @@ int sa1111_pcmcia_get_irq_info(struct pcmcia_irq_info *info) int ret = 0; switch (info->sock) { - case 0: info->irq = S0_READY_NINT; break; - case 1: info->irq = S1_READY_NINT; break; + case 0: info->irq = IRQ_S0_READY_NINT; break; + case 1: info->irq = IRQ_S1_READY_NINT; break; default: ret = 1; } @@ -109,7 +106,7 @@ int sa1111_pcmcia_get_irq_info(struct pcmcia_irq_info *info) int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *conf) { - unsigned int rst, flt, wait, pse, irq, pccr_mask; + unsigned int rst, flt, wait, pse, irq, pccr_mask, val; unsigned long flags; switch (conf->sock) { @@ -118,7 +115,7 @@ int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *conf) flt = PCCR_S0_FLT; wait = PCCR_S0_PWAITEN; pse = PCCR_S0_PSE; - irq = S0_READY_NINT; + irq = IRQ_S0_READY_NINT; break; case 1: @@ -126,7 +123,7 @@ int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *conf) flt = PCCR_S1_FLT; wait = PCCR_S1_PWAITEN; pse = PCCR_S1_PSE; - irq = S1_READY_NINT; + irq = IRQ_S1_READY_NINT; break; default: @@ -159,7 +156,9 @@ int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *conf) pccr_mask |= flt; local_irq_save(flags); - PCCR = (PCCR & ~(pse | flt | wait | rst)) | pccr_mask; + val = sa1111_readl(pcmcia->mapbase + SA1111_PCCR); + val = (val & ~(pse | flt | wait | rst)) | pccr_mask; + sa1111_writel(val, pcmcia->mapbase + SA1111_PCCR); local_irq_restore(flags); if (conf->irq) @@ -179,3 +178,130 @@ int sa1111_pcmcia_socket_suspend(int sock) { return 0; } + +static int pcmcia_probe(struct device *dev) +{ + struct sa1111_dev *sadev = SA1111_DEV(dev); + unsigned long flags; + char *base; + + local_irq_save(flags); + if (pcmcia) { + local_irq_restore(flags); + return -EBUSY; + } + + pcmcia = sadev; + local_irq_restore(flags); + + if (!request_mem_region(sadev->res.start, 512, + SA1111_DRIVER_NAME(sadev))) + return -EBUSY; + + base = sadev->mapbase; + + /* + * Initialise the suspend state. + */ + sa1111_writel(PCSSR_S0_SLEEP | PCSSR_S1_SLEEP, base + SA1111_PCSSR); + sa1111_writel(PCCR_S0_FLT | PCCR_S1_FLT, base + SA1111_PCCR); + +#ifdef CONFIG_SA1100_ADSBITSY + pcmcia_adsbitsy_init(); +#endif +#ifdef CONFIG_SA1100_BADGE4 + pcmcia_badge4_init(); +#endif +#ifdef CONFIG_SA1100_GRAPHICSMASTER + pcmcia_graphicsmaster_init(); +#endif +#ifdef CONFIG_SA1100_JORNADA720 + pcmcia_jornada720_init(); +#endif +#ifdef CONFIG_ASSABET_NEPONSET + pcmcia_neponset_init(); +#endif +#ifdef CONFIG_SA1100_PFS168 + pcmcia_pfs_init(); +#endif +#ifdef CONFIG_SA1100_PT_SYSTEM3 + pcmcia_system3_init(); +#endif +#ifdef CONFIG_SA1100_XP860 + pcmcia_xp860_init(); +#endif + return 0; +} + +static int __devexit pcmcia_remove(struct device *dev) +{ + struct sa1111_dev *sadev = SA1111_DEV(dev); + +#ifdef CONFIG_SA1100_ADSBITSY + pcmcia_adsbitsy_exit(); +#endif +#ifdef CONFIG_SA1100_BADGE4 + pcmcia_badge4_exit(); +#endif +#ifdef CONFIG_SA1100_GRAPHICSMASTER + pcmcia_graphicsmaster_exit(); +#endif +#ifdef CONFIG_SA1100_JORNADA720 + pcmcia_jornada720_exit(); +#endif +#ifdef CONFIG_ASSABET_NEPONSET + pcmcia_neponset_exit(); +#endif +#ifdef CONFIG_SA1100_PFS168 + pcmcia_pfs_exit(); +#endif +#ifdef CONFIG_SA1100_PT_SYSTEM3 + pcmcia_system3_exit(); +#endif +#ifdef CONFIG_SA1100_XP860 + pcmcia_xp860_exit(); +#endif + + release_mem_region(sadev->res.start, 512); + pcmcia = NULL; + + return 0; +} + +static int pcmcia_suspend(struct device *dev, u32 state, u32 level) +{ + return 0; +} + +static int pcmcia_resume(struct device *dev, u32 level) +{ + return 0; +} + +static struct sa1111_driver pcmcia_driver = { + .drv = { + .name = "SA1111 PCMCIA", + .bus = &sa1111_bus_type, + .probe = pcmcia_probe, + .remove = __devexit_p(pcmcia_remove), + .suspend = pcmcia_suspend, + .resume = pcmcia_resume, + }, + .devid = SA1111_DEVID_PCMCIA, +}; + +static int __init sa1111_drv_pcmcia_init(void) +{ + return driver_register(&pcmcia_driver.drv); +} + +static void __exit sa1111_drv_pcmcia_exit(void) +{ + remove_driver(&pcmcia_driver.drv); +} + +module_init(sa1111_drv_pcmcia_init); +module_exit(sa1111_drv_pcmcia_exit); + +MODULE_DESCRIPTION("SA1111 PCMCIA card socket driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c index f7b44577a7a0e4c40cbe6f148bab10dae331093d..a6a34619d4fd930e63a9a58b17f0d9472528c2c3 100644 --- a/drivers/usb/host/ohci-sa1111.c +++ b/drivers/usb/host/ohci-sa1111.c @@ -25,7 +25,7 @@ /*-------------------------------------------------------------------------*/ -static void sa1111_start_hc(void) +static void sa1111_start_hc(struct sa1111_dev *dev) { unsigned int usb_rst = 0; @@ -48,31 +48,35 @@ static void sa1111_start_hc(void) * Configure the power sense and control lines. Place the USB * host controller in reset. */ - USB_RESET = usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET; + sa1111_writel(usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET, + dev->mapbase + SA1111_USB_RESET); /* * Now, carefully enable the USB clock, and take * the USB host controller out of reset. */ - SKPCR |= SKPCR_UCLKEN; + sa1111_enable_device(dev); udelay(11); - USB_RESET = usb_rst; + sa1111_writel(usb_rst, dev->mapbase + SA1111_USB_RESET); } -static void sa1111_stop_hc(void) +static void sa1111_stop_hc(struct sa1111_dev *dev) { + unsigned int usb_rst; printk(KERN_DEBUG __FILE__ ": stopping SA-1111 OHCI USB Controller\n"); /* * Put the USB host controller into reset. */ - USB_RESET |= USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET; + usb_rst = sa1111_readl(dev->mapbase + SA1111_USB_RESET); + sa1111_writel(usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET, + dev->mapbase + SA1111_USB_RESET); /* * Stop the USB clock. */ - SKPCR &= ~SKPCR_UCLKEN; + sa1111_disable_device(dev); #ifdef CONFIG_SA1100_BADGE4 if (machine_is_badge4()) { @@ -86,9 +90,9 @@ static void sa1111_stop_hc(void) /*-------------------------------------------------------------------------*/ #if 0 -static void dump_hci_status(const char *label) +static void dump_hci_status(struct usb_hcd *hcd, const char *label) { - unsigned long status = USB_STATUS; + unsigned long status = sa1111_readl(hcd->regs + SA1111_USB_STATUS); dbg ("%s USB_STATUS = { %s%s%s%s%s}", label, ((status & USB_STATUS_IRQHCIRMTWKUP) ? "IRQHCIRMTWKUP " : ""), @@ -101,11 +105,14 @@ static void dump_hci_status(const char *label) static void usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r) { - //dump_hci_status("irq"); + struct usb_hcd *hcd = __hcd; +// unsigned long status = sa1111_readl(hcd->regs + SA1111_USB_STATUS); + + //dump_hci_status(hcd, "irq"); #if 0 /* may work better this way -- need to investigate further */ - if (USB_STATUS & USB_STATUS_NIRQHCIM) { + if (status & USB_STATUS_NIRQHCIM) { //dbg ("not normal HC interrupt; ignoring"); return; } @@ -116,7 +123,7 @@ static void usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r) /*-------------------------------------------------------------------------*/ -void usb_hcd_sa1111_remove (struct usb_hcd *); +void usb_hcd_sa1111_remove (struct usb_hcd *, struct sa1111_dev *); /* configure so an HC device and id are always provided */ /* always called with process context; sleeping is OK */ @@ -132,21 +139,20 @@ void usb_hcd_sa1111_remove (struct usb_hcd *); * * Store this function in the HCD's struct pci_driver as probe(). */ -int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_out) +int usb_hcd_sa1111_probe (const struct hc_driver *driver, + struct usb_hcd **hcd_out, + struct sa1111_dev *dev) { int retval; struct usb_hcd *hcd = 0; - if (!sa1111) - return -ENODEV; - - if (!request_mem_region(_USB_OHCI_OP_BASE, - _USB_EXTENT, hcd_name)) { + if (!request_mem_region(dev->res.start, + dev->res.end - dev->res.start + 1, hcd_name)) { dbg("request_mem_region failed"); return -EBUSY; } - sa1111_start_hc(); + sa1111_start_hc(dev); hcd = driver->hcd_alloc (); if (hcd == NULL){ @@ -157,9 +163,10 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o hcd->driver = (struct hc_driver *) driver; hcd->description = driver->description; - hcd->irq = NIRQHCIM; - hcd->regs = (void *) &USB_OHCI_OP_BASE; + hcd->irq = dev->irq[1]; + hcd->regs = dev->mapbase; hcd->pdev = SA1111_FAKE_PCIDEV; + hcd->parent = &dev->dev; retval = hcd_buffer_create (hcd); if (retval != 0) { @@ -167,8 +174,8 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o goto err1; } - set_irq_type(NIRQHCIM, IRQT_RISING); - retval = request_irq (NIRQHCIM, usb_hcd_sa1111_hcim_irq, SA_INTERRUPT, + set_irq_type(hcd->irq, IRQT_RISING); + retval = request_irq (hcd->irq, usb_hcd_sa1111_hcim_irq, SA_INTERRUPT, hcd->description, hcd); if (retval != 0) { dbg("request_irq failed"); @@ -191,7 +198,7 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o if ((retval = driver->start (hcd)) < 0) { - usb_hcd_sa1111_remove(hcd); + usb_hcd_sa1111_remove(hcd, dev); return retval; } @@ -202,8 +209,8 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o hcd_buffer_destroy (hcd); if (hcd) driver->hcd_free(hcd); err1: - sa1111_stop_hc(); - release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT); + sa1111_stop_hc(dev); + release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1); return retval; } @@ -221,7 +228,7 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o * context, normally "rmmod", "apmd", or something similar. * */ -void usb_hcd_sa1111_remove (struct usb_hcd *hcd) +void usb_hcd_sa1111_remove (struct usb_hcd *hcd, struct sa1111_dev *dev) { struct usb_device *hub; void *base; @@ -244,13 +251,13 @@ void usb_hcd_sa1111_remove (struct usb_hcd *hcd) usb_deregister_bus (&hcd->self); if (atomic_read (&hcd->self.refcnt) != 1) - err (__FUNCTION__ ": %s, count != 1", hcd->self.bus_name); + err ("%s: %s, count != 1", __FUNCTION__, hcd->self.bus_name); base = hcd->regs; hcd->driver->hcd_free (hcd); - sa1111_stop_hc(); - release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT); + sa1111_stop_hc(dev); + release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1); } /*-------------------------------------------------------------------------*/ @@ -275,7 +282,7 @@ ohci_sa1111_start (struct usb_hcd *hcd) } ohci->regs = hcd->regs; - ohci->parent_dev = &sa1111->dev; + ohci->parent_dev = hcd->parent; if (hc_reset (ohci) < 0) { ohci_stop (hcd); @@ -342,26 +349,67 @@ static const struct hc_driver ohci_sa1111_hc_driver = { /*-------------------------------------------------------------------------*/ -/* Only one SA-1111 ever exists. */ -static struct usb_hcd *the_sa1111_hcd; +static int ohci_hcd_sa1111_drv_probe(struct device *_dev) +{ + struct sa1111_dev *dev = SA1111_DEV(_dev); + struct usb_hcd *hcd = NULL; + int ret; + + ret = usb_hcd_sa1111_probe(&ohci_sa1111_hc_driver, &hcd, dev); + + if (ret == 0) + dev->dev.driver_data = hcd; + + return ret; +} + +static int ohci_hcd_sa1111_drv_remove(struct device *_dev) +{ + struct sa1111_dev *dev = SA1111_DEV(_dev); + struct usb_hcd *hcd = dev->dev.driver_data; + + usb_hcd_sa1111_remove(hcd, dev); + + dev->dev.driver_data = NULL; -static int __init ohci_hcd_sa1111_init (void) + return 0; +} + +static int ohci_hcd_sa1111_drv_suspend(struct device *dev, u32 state, u32 level) +{ + return 0; +} + +static int ohci_hcd_sa1111_drv_resume(struct device *dev, u32 level) +{ + return 0; +} + +static struct sa1111_driver ohci_hcd_sa1111_driver = { + .drv = { + .name = "SA1111 OHCI", + .bus = &sa1111_bus_type, + .probe = ohci_hcd_sa1111_drv_probe, + .remove = ohci_hcd_sa1111_drv_remove, + .suspend = ohci_hcd_sa1111_drv_suspend, + .resume = ohci_hcd_sa1111_drv_resume, + }, + .devid = SA1111_DEVID_USB, +}; + +static int __init ohci_hcd_sa1111_init (void) { dbg (DRIVER_INFO " (SA-1111)"); dbg ("block sizes: ed %d td %d", sizeof (struct ed), sizeof (struct td)); - the_sa1111_hcd = 0; - return usb_hcd_sa1111_probe(&ohci_sa1111_hc_driver, &the_sa1111_hcd); + return driver_register(&ohci_hcd_sa1111_driver.drv); } -module_init (ohci_hcd_sa1111_init); - -static void __exit ohci_hcd_sa1111_cleanup (void) -{ - if (the_sa1111_hcd) { - usb_hcd_sa1111_remove(the_sa1111_hcd); - the_sa1111_hcd = 0; - } +static void __exit ohci_hcd_sa1111_cleanup (void) +{ + remove_driver(&ohci_hcd_sa1111_driver.drv); } + +module_init (ohci_hcd_sa1111_init); module_exit (ohci_hcd_sa1111_cleanup); diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index 6a2683bba658b879e2786528dee9d3a340ff66fe..17b1c02cb38adee3ddb781fbe3e549952ce98136 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -209,17 +209,17 @@ extern void (*sa1100fb_lcd_power)(int on); * IMHO this looks wrong. In 8BPP, length should be 8. */ static struct sa1100fb_rgb rgb_8 = { - red: { offset: 0, length: 4, }, - green: { offset: 0, length: 4, }, - blue: { offset: 0, length: 4, }, - transp: { offset: 0, length: 0, }, + .red = { .offset = 0, .length = 4, }, + .green = { .offset = 0, .length = 4, }, + .blue = { .offset = 0, .length = 4, }, + .transp = { .offset = 0, .length = 0, }, }; static struct sa1100fb_rgb def_rgb_16 = { - red: { offset: 11, length: 5, }, - green: { offset: 5, length: 6, }, - blue: { offset: 0, length: 5, }, - transp: { offset: 0, length: 0, }, + .red = { .offset = 11, .length = 5, }, + .green = { .offset = 5, .length = 6, }, + .blue = { .offset = 0, .length = 5, }, + .transp = { .offset = 0, .length = 0, }, }; #ifdef CONFIG_SA1100_ASSABET @@ -230,155 +230,151 @@ static struct sa1100fb_rgb def_rgb_16 = { * instead (def_rgb_16). */ static struct sa1100fb_mach_info lq039q2ds54_info __initdata = { - pixclock: 171521, bpp: 16, - xres: 320, yres: 240, + .pixclock = 171521, .bpp = 16, + .xres = 320, .yres = 240, - hsync_len: 5, vsync_len: 1, - left_margin: 61, upper_margin: 3, - right_margin: 9, lower_margin: 0, + .hsync_len = 5, .vsync_len = 1, + .left_margin = 61, .upper_margin = 3, + .right_margin = 9, .lower_margin = 0, - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act, - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), + .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, + .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), }; #else static struct sa1100fb_mach_info pal_info __initdata = { - pixclock: 67797, bpp: 16, - xres: 640, yres: 512, + .pixclock = 67797, .bpp = 16, + .xres = 640, .yres = 512, - hsync_len: 64, vsync_len: 6, - left_margin: 125, upper_margin: 70, - right_margin: 115, lower_margin: 36, + .hsync_len = 64, .vsync_len = 6, + .left_margin = 125, .upper_margin = 70, + .right_margin = 115, .lower_margin = 36, - sync: 0, - - lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act, - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512), + .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, + .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512), }; #endif #endif #ifdef CONFIG_SA1100_H3800 static struct sa1100fb_mach_info h3800_info __initdata = { - pixclock: 174757, bpp: 16, - xres: 320, yres: 240, + .pixclock = 174757, .bpp = 16, + .xres = 320, .yres = 240, - hsync_len: 3, vsync_len: 3, - left_margin: 12, upper_margin: 10, - right_margin: 17, lower_margin: 1, + .hsync_len = 3, .vsync_len = 3, + .left_margin = 12, .upper_margin = 10, + .right_margin = 17, .lower_margin = 1, - sync: 0, cmap_static: 1, + .cmap_static = 1, - lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act, - lccr3: LCCR3_ACBsDiv(2) | LCCR3_PixRsEdg | LCCR3_OutEnH | - LCCR3_ACBsCntOff, + .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, + .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), }; #endif #ifdef CONFIG_SA1100_H3600 static struct sa1100fb_mach_info h3600_info __initdata = { - pixclock: 174757, bpp: 16, - xres: 320, yres: 240, + .pixclock = 174757, .bpp = 16, + .xres = 320, .yres = 240, - hsync_len: 3, vsync_len: 3, - left_margin: 12, upper_margin: 10, - right_margin: 17, lower_margin: 1, + .hsync_len = 3, .vsync_len = 3, + .left_margin = 12, .upper_margin = 10, + .right_margin = 17, .lower_margin = 1, - sync: 0, cmap_static: 1, + .cmap_static = 1, - lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act, - lccr3: LCCR3_ACBsDiv(2) | LCCR3_PixRsEdg | LCCR3_OutEnH | - LCCR3_ACBsCntOff, + .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, + .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), }; static struct sa1100fb_rgb h3600_rgb_16 = { - red: { offset: 12, length: 4, }, - green: { offset: 7, length: 4, }, - blue: { offset: 1, length: 4, }, - transp: { offset: 0, length: 0, }, + .red = { .offset = 12, .length = 4, }, + .green = { .offset = 7, .length = 4, }, + .blue = { .offset = 1, .length = 4, }, + .transp = { .offset = 0, .length = 0, }, }; #endif #ifdef CONFIG_SA1100_H3100 static struct sa1100fb_mach_info h3100_info __initdata = { - pixclock: 406977, bpp: 4, - xres: 320, yres: 240, + .pixclock = 406977, .bpp = 4, + .xres = 320, .yres = 240, - hsync_len: 26, vsync_len: 41, - left_margin: 4, upper_margin: 0, - right_margin: 4, lower_margin: 0, + .hsync_len = 26, .vsync_len = 41, + .left_margin = 4, .upper_margin = 0, + .right_margin = 4, .lower_margin = 0, - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - cmap_greyscale: 1, - cmap_inverse: 1, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .cmap_greyscale = 1, + .cmap_inverse = 1, - lccr0: LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas, - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), + .lccr0 = LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas, + .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), }; #endif #ifdef CONFIG_SA1100_BRUTUS static struct sa1100fb_mach_info brutus_info __initdata = { - pixclock: 0, bpp: 8, - xres: 320, yres: 240, + .pixclock = 0, .bpp = 8, + .xres = 320, .yres = 240, - hsync_len: 3, vsync_len: 1, - left_margin: 41, upper_margin: 0, - right_margin: 101, lower_margin: 0, + .hsync_len = 3, .vsync_len = 1, + .left_margin = 41, .upper_margin = 0, + .right_margin = 101, .lower_margin = 0, - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Pas, - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) | - LCCR3_PixClkDiv(44), + .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Pas, + .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) | + LCCR3_PixClkDiv(44), }; #endif #ifdef CONFIG_SA1100_CERF static struct sa1100fb_mach_info cerf_info __initdata = { #if defined(CONFIG_CERF_LCD_72_A) - pixclock: 171521, bpp: 8, - xres: 640, yres: 480, - lccr0: LCCR0_Color | LCCR0_Dual | LCCR0_Pas, - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) | - LCCR3_PixClkDiv(38), + .pixclock = 171521, .bpp = 8, + .xres = 640, .yres = 480, + .lccr0 = LCCR0_Color | LCCR0_Dual | LCCR0_Pas, + .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) | + LCCR3_PixClkDiv(38), #elif defined(CONFIG_CERF_LCD_57_A) - pixclock: 171521, bpp: 8, - xres: 320, yres: 240, - lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Pas, - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) | - LCCR3_PixClkDiv(38), + .pixclock = 171521, .bpp = 8, + .xres = 320, .yres = 240, + .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Pas, + .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) | + LCCR3_PixClkDiv(38), #elif defined(CONFIG_CERF_LCD_38_A) - pixclock: 171521, bpp: 8, - xres: 240, yres: 320, - lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Pas, - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(56) | - LCCR3_PixClkDiv(38), + .pixclock = 171521, .bpp = 8, + .xres = 240, .yres = 320, + .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Pas, + .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(56) | + LCCR3_PixClkDiv(38), #elif defined(CONFIG_CERF_LCD_38_B) - pixclock: 171521, bpp: 4, - xres: 320, yres: 240, - lccr0: LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas, - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(56) | - LCCR3_PixClkDiv(38), + .pixclock = 171521, .bpp = 4, + .xres = 320, .yres = 240, + .lccr0 = LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas, + .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(56) | + LCCR3_PixClkDiv(38), #else #error "Must have a CerfBoard LCD form factor selected" #endif - hsync_len: 5, vsync_len: 1, - left_margin: 61, upper_margin: 3, - right_margin: 9, lower_margin: 0, + .hsync_len = 5, .vsync_len = 1, + .left_margin = 61, .upper_margin = 3, + .right_margin = 9, .lower_margin = 0, - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, }; #if 0 static struct sa1100fb_rgb cerf_rgb_16 = { - red: { offset: 8, length: 4, }, - green: { offset: 4, length: 4, }, - blue: { offset: 0, length: 4, }, - transp: { offset: 0, length: 0, }, + .red = { .offset = 8, .length = 4, }, + .green = { .offset = 4, .length = 4, }, + .blue = { .offset = 0, .length = 4, }, + .transp = { .offset = 0, .length = 0, }, }; #endif #endif @@ -386,56 +382,54 @@ static struct sa1100fb_rgb cerf_rgb_16 = { #ifdef CONFIG_SA1100_FREEBIRD #warning Please check this carefully static struct sa1100fb_mach_info freebird_info __initdata = { - pixclock: 171521, bpp: 16, - xres: 240, yres: 320, + .pixclock = 171521, .bpp = 16, + .xres = 240, .yres = 320, - hsync_len: 3, vsync_len: 2, - left_margin: 2, upper_margin: 0, - right_margin: 2, lower_margin: 0, + .hsync_len = 3, .vsync_len = 2, + .left_margin = 2, .upper_margin = 0, + .right_margin = 2, .lower_margin = 0, - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Pas, - lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(2), + .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Pas, + .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(2), }; static struct sa1100fb_rgb freebird_rgb_16 = { - red: { offset: 8, length: 4, }, - green: { offset: 4, length: 4, }, - blue: { offset: 0, length: 4, }, - transp: { offset: 12, length: 4, }, + .red = { .offset = 8, .length = 4, }, + .green = { .offset = 4, .length = 4, }, + .blue = { .offset = 0, .length = 4, }, + .transp = { .offset = 12, .length = 4, }, }; #endif #ifdef CONFIG_SA1100_GRAPHICSCLIENT static struct sa1100fb_mach_info graphicsclient_info __initdata = { - pixclock: 53500, bpp: 8, - xres: 640, yres: 480, - - hsync_len: 9, vsync_len: 9, - left_margin: 54, upper_margin: 24, - right_margin: 54, lower_margin: 32, + .pixclock = 53500, .bpp = 8, + .xres = 640, .yres = 480, - sync: 0, + .hsync_len = 9, .vsync_len = 9, + .left_margin = 54, .upper_margin = 24, + .right_margin = 54, .lower_margin = 32, - lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act, - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), + .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, + .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), }; #endif #ifdef CONFIG_SA1100_HUW_WEBPANEL static struct sa1100fb_mach_info huw_webpanel_info __initdata = { - pixclock: 0, bpp: 8, - xres: 640, yres: 480, + .pixclock = 0, .bpp = 8, + .xres = 640, .yres = 480, - hsync_len: 3, vsync_len: 1, - left_margin: 41, upper_margin: 0, - right_margin: 101, lower_margin: 0, + .hsync_len = 3, .vsync_len = 1, + .left_margin = 41, .upper_margin = 0, + .right_margin = 101, .lower_margin = 0, - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - lccr0: LCCR0_Color | LCCR0_Dual | LCCR0_Pas, - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) | 8, + .lccr0 = LCCR0_Color | LCCR0_Dual | LCCR0_Pas, + .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) | 8, #error FIXME /* * FIXME: please get rid of the '| 8' in preference to an @@ -446,99 +440,94 @@ static struct sa1100fb_mach_info huw_webpanel_info __initdata = { #ifdef LART_GREY_LCD static struct sa1100fb_mach_info lart_grey_info __initdata = { - pixclock: 150000, bpp: 4, - xres: 320, yres: 240, + .pixclock = 150000, .bpp = 4, + .xres = 320, .yres = 240, - hsync_len: 1, vsync_len: 1, - left_margin: 4, upper_margin: 0, - right_margin: 2, lower_margin: 0, + .hsync_len = 1, .vsync_len = 1, + .left_margin = 4, .upper_margin = 0, + .right_margin = 2, .lower_margin = 0, - cmap_greyscale: 1, - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .cmap_greyscale = 1, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - lccr0: LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_4PixMono, - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512), + .lccr0 = LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_4PixMono, + .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512), }; #endif #ifdef LART_COLOR_LCD static struct sa1100fb_mach_info lart_color_info __initdata = { - pixclock: 150000, bpp: 16, - xres: 320, yres: 240, + .pixclock = 150000, .bpp = 16, + .xres = 320, .yres = 240, - hsync_len: 2, vsync_len: 3, - left_margin: 69, upper_margin: 14, - right_margin: 8, lower_margin: 4, + .hsync_len = 2, .vsync_len = 3, + .left_margin = 69, .upper_margin = 14, + .right_margin = 8, .lower_margin = 4, - sync: 0, - - lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act, - lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512), + .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, + .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512), }; #endif #ifdef LART_VIDEO_OUT static struct sa1100fb_mach_info lart_video_info __initdata = { - pixclock: 39721, bpp: 16, - xres: 640, yres: 480, + .pixclock = 39721, .bpp = 16, + .xres = 640, .yres = 480, - hsync_len: 95, vsync_len: 2, - left_margin: 40, upper_margin: 32, - right_margin: 24, lower_margin: 11, + .hsync_len = 95, .vsync_len = 2, + .left_margin = 40, .upper_margin = 32, + .right_margin = 24, .lower_margin = 11, - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act, - lccr3: LCCR3_OutEnL | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512), + .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, + .lccr3 = LCCR3_OutEnL | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512), }; #endif #ifdef LART_KIT01_LCD -static struct sa1100fb_mach_info lart_kit01_info __initdata = -{ - pixclock: 63291, bpp: 16, - xres: 640, yres: 480, +static struct sa1100fb_mach_info lart_kit01_info __initdata = { + .pixclock = 63291, .bpp = 16, + .xres = 640, .yres = 480, - hsync_len: 64, vsync_len: 3, - left_margin: 122, upper_margin: 45, - right_margin: 10, lower_margin: 10, + .hsync_len = 64, .vsync_len = 3, + .left_margin = 122, .upper_margin = 45, + .right_margin = 10, .lower_margin = 10, - sync: 0, - - lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act, - lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg + .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, + .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg }; #endif #ifdef CONFIG_SA1100_SHANNON static struct sa1100fb_mach_info shannon_info __initdata = { - pixclock: 152500, bpp: 8, - xres: 640, yres: 480, + .pixclock = 152500, .bpp = 8, + .xres = 640, .yres = 480, - hsync_len: 4, vsync_len: 3, - left_margin: 2, upper_margin: 0, - right_margin: 1, lower_margin: 0, + .hsync_len = 4, .vsync_len = 3, + .left_margin = 2, .upper_margin = 0, + .right_margin = 1, .lower_margin = 0, - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - lccr0: LCCR0_Color | LCCR0_Dual | LCCR0_Pas, - lccr3: LCCR3_ACBsDiv(512), + .lccr0 = LCCR0_Color | LCCR0_Dual | LCCR0_Pas, + .lccr3 = LCCR3_ACBsDiv(512), }; #endif #ifdef CONFIG_SA1100_OMNIMETER static struct sa1100fb_mach_info omnimeter_info __initdata = { - pixclock: 0, bpp: 4, - xres: 480, yres: 320, + .pixclock = 0, .bpp = 4, + .xres = 480, .yres = 320, - hsync_len: 1, vsync_len: 1, - left_margin: 10, upper_margin: 0, - right_margin: 10, lower_margin: 0, + .hsync_len = 1, .vsync_len = 1, + .left_margin = 10, .upper_margin = 0, + .right_margin = 10, .lower_margin = 0, - cmap_greyscale: 1, - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .cmap_greyscale = 1, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - lccr0: LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_8PixMono, - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(255) | - LCCR3_PixClkDiv(44), + .lccr0 = LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_8PixMono, + .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(255) | + LCCR3_PixClkDiv(44), #error FIXME: fix pixclock, ACBsDiv /* * FIXME: I think ACBsDiv is wrong above - should it be 512 (disabled)? @@ -549,17 +538,17 @@ static struct sa1100fb_mach_info omnimeter_info __initdata = { #ifdef CONFIG_SA1100_PANGOLIN static struct sa1100fb_mach_info pangolin_info __initdata = { - pixclock: 341521, bpp: 16, - xres: 800, yres: 600, + .pixclock = 341521, .bpp = 16, + .xres = 800, .yres = 600, - hsync_len: 64, vsync_len: 7, - left_margin: 160, upper_margin: 7, - right_margin: 24, lower_margin: 1, + .hsync_len = 64, .vsync_len = 7, + .left_margin = 160, .upper_margin = 7, + .right_margin = 24, .lower_margin = 1, - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act, - lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsCntOff, + .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, + .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsCntOff, }; #endif @@ -571,49 +560,47 @@ static struct sa1100fb_mach_info pangolin_info __initdata = { * NB likely to be increased to ease bus timings wrt pcmcia interface */ static struct sa1100fb_mach_info stork_tft_info __initdata = { - pixclock: 28935, bpp: 16, - xres: 640, yres: 480, - - hsync_len: 64, vsync_len: 2, - left_margin: 48, upper_margin: 12, - right_margin: 48, lower_margin: 31, + .pixclock = 28935, .bpp = 16, + .xres = 640, .yres = 480, - sync: 0, + .hsync_len = 64, .vsync_len = 2, + .left_margin = 48, .upper_margin = 12, + .right_margin = 48, .lower_margin = 31, - lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act, - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg, + .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, + .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsCntOff, }; static struct sa1100fb_rgb stork_tft_rgb_16 = { - red: { offset: 11, length: 5, }, - green: { offset: 5, length: 6, }, - blue: { offset: 0, length: 5, }, - transp: { offset: 0, length: 0, }, + .red = { .offset = 11, .length = 5, }, + .green = { .offset = 5, .length = 6, }, + .blue = { .offset = 0, .length = 5, }, + .transp = { .offset = 0, .length = 0, }, }; #else /* Kyocera DSTN */ static struct sa1100fb_mach_info stork_dstn_info __initdata = { - pixclock: 0, bpp: 16, - xres: 640, yres: 480, + .pixclock = 0, .bpp = 16, + .xres = 640, .yres = 480, - hsync_len: 2, vsync_len: 2, - left_margin: 2, upper_margin: 0, - right_margin: 2, lower_margin: 0, + .hsync_len = 2, .vsync_len = 2, + .left_margin = 2, .upper_margin = 0, + .right_margin = 2, .lower_margin = 0, - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT , + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT , - lccr0: LCCR0_Color | LCCR0_Dual | LCCR0_Pas, + .lccr0 = LCCR0_Color | LCCR0_Dual | LCCR0_Pas, #error Fixme - lccr3: 0xff00 | + .lccr3 = 0xff00 | 0x18 /* ought to be 0x14 but DMA isn't up to that as yet */ }; static struct sa1100fb_rgb stork_dstn_rgb_16 = { - red: { offset: 8, length: 4, }, - green: { offset: 4, length: 4, }, - blue: { offset: 0, length: 4, }, - transp: { offset: 0, length: 0, }, + .red = { .offset = 8, .length = 4, }, + .green = { .offset = 4, .length = 4, }, + .blue = { .offset = 0, .length = 4, }, + .transp = { .offset = 0, .length = 0, }, }; #endif #endif @@ -630,34 +617,31 @@ static struct sa1100fb_rgb stork_dstn_rgb_16 = { * =>4.32Mhz => 231481E-12s */ static struct sa1100fb_mach_info system3_info __initdata = { - pixclock: 231481, bpp: 8, - xres: 640, yres: 480, + .pixclock = 231481, .bpp = 8, + .xres = 640, .yres = 480, - hsync_len: 2, vsync_len: 2, - left_margin: 2, upper_margin: 0, - right_margin: 2, lower_margin: 0, + .hsync_len = 2, .vsync_len = 2, + .left_margin = 2, .upper_margin = 0, + .right_margin = 2, .lower_margin = 0, - sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - lccr0: LCCR0_Color | LCCR0_Dual | LCCR0_Pas, - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512) | - LCCR3_ACBsCntOff, + .lccr0 = LCCR0_Color | LCCR0_Dual | LCCR0_Pas, + .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512), }; #endif #ifdef CONFIG_SA1100_XP860 static struct sa1100fb_mach_info xp860_info __initdata = { - pixclock: 0, bpp: 8, - xres: 1024, yres: 768, - - hsync_len: 3, vsync_len: 3, - left_margin: 3, upper_margin: 2, - right_margin: 2, lower_margin: 1, + .pixclock = 0, .bpp = 8, + .xres = 1024, .yres = 768, - sync: 0, + .hsync_len = 3, .vsync_len = 3, + .left_margin = 3, .upper_margin = 2, + .right_margin = 2, .lower_margin = 1, - lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act, - lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_PixClkDiv(6), + .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, + .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_PixClkDiv(6), }; #endif @@ -808,33 +792,7 @@ static inline void sa1100fb_schedule_task(struct sa1100fb_info *fbi, u_int state local_irq_restore(flags); } -/* - * Get the VAR structure pointer for the specified console - */ -static inline struct fb_var_screeninfo *get_con_var(struct fb_info *info, int con) -{ - return (con == info->currcon || con == -1) ? &info->var : &fb_display[con].var; -} - -/* - * Get the DISPLAY structure pointer for the specified console - */ -static inline struct display *get_con_display(struct fb_info *info, int con) -{ - struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; - return (con < 0) ? fbi->fb.disp : &fb_display[con]; -} - -/* - * Get the CMAP pointer for the specified console - */ -static inline struct fb_cmap *get_con_cmap(struct fb_info *info, int con) -{ - return (con == info->currcon || con == -1) ? &info->cmap : &fb_display[con].cmap; -} - -static inline u_int -chan_to_field(u_int chan, struct fb_bitfield *bf) +static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) { chan &= 0xffff; chan >>= 16 - bf->length; @@ -844,8 +802,7 @@ chan_to_field(u_int chan, struct fb_bitfield *bf) /* * Convert bits-per-pixel to a hardware palette PBS value. */ -static inline u_int -palette_pbs(struct fb_var_screeninfo *var) +static inline u_int palette_pbs(struct fb_var_screeninfo *var) { int ret = 0; switch (var->bits_per_pixel) { @@ -888,8 +845,7 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int trans, struct fb_info *info) { struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; - struct display *disp = get_con_display(info, info->currcon); - u_int val; + unsigned int val; int ret = 1; /* @@ -898,7 +854,7 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, * is what you poke into the framebuffer to produce the * colour you requested. */ - if (disp->inverse) { + if (fbi->cmap_inverse) { red = 0xffff - red; green = 0xffff - green; blue = 0xffff - blue; @@ -912,7 +868,7 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, red = green = blue = (19595 * red + 38470 * green + 7471 * blue) >> 16; - switch (fbi->fb.disp->visual) { + switch (fbi->fb.fix.visual) { case FB_VISUAL_TRUECOLOR: /* * 12 or 16-bit True Colour. We encode the RGB value @@ -942,38 +898,29 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, /* * sa1100fb_display_dma_period() * Calculate the minimum period (in picoseconds) between two DMA - * requests for the LCD controller. + * requests for the LCD controller. If we hit this, it means we're + * doing nothing but LCD DMA. */ -static unsigned int -sa1100fb_display_dma_period(struct fb_var_screeninfo *var) +static unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var) { - unsigned int mem_bits_per_pixel; - - mem_bits_per_pixel = var->bits_per_pixel; - if (mem_bits_per_pixel == 12) - mem_bits_per_pixel = 16; - /* * Period = pixclock * bits_per_byte * bytes_per_transfer * / memory_bits_per_pixel; */ - return var->pixclock * 8 * 16 / mem_bits_per_pixel; + return var->pixclock * 8 * 16 / var->bits_per_pixel; } /* - * sa1100fb_decode_var(): - * Get the video params out of 'var'. If a value doesn't fit, round it up, - * if it's too big, return -EINVAL. - * - * Suggestion: Round up in the following order: bits_per_pixel, xres, + * sa1100fb_check_var(): + * Round up in the following order: bits_per_pixel, xres, * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale, * bitfields, horizontal timing, vertical timing. */ static int -sa1100fb_validate_var(struct fb_var_screeninfo *var, - struct sa1100fb_info *fbi) +sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { - int ret = -EINVAL; + struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; + int rgbidx; if (var->xres < MIN_XRES) var->xres = MIN_XRES; @@ -983,42 +930,60 @@ sa1100fb_validate_var(struct fb_var_screeninfo *var, var->xres = fbi->max_xres; if (var->yres > fbi->max_yres) var->yres = fbi->max_yres; - var->xres_virtual = - var->xres_virtual < var->xres ? var->xres : var->xres_virtual; - var->yres_virtual = - var->yres_virtual < var->yres ? var->yres : var->yres_virtual; + var->xres_virtual = max(var->xres_virtual, var->xres); + var->yres_virtual = max(var->yres_virtual, var->yres); DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel); switch (var->bits_per_pixel) { #ifdef FBCON_HAS_CFB4 - case 4: ret = 0; break; + case 4: + rgbidx = RGB_8; + break; #endif #ifdef FBCON_HAS_CFB8 - case 8: ret = 0; break; + case 8: + rgbidx = RGB_8; + break; #endif #ifdef FBCON_HAS_CFB16 - case 16: ret = 0; break; + case 16: + rgbidx = RGB_16; + break; #endif default: - break; + return -EINVAL; } + /* + * Copy the RGB parameters for this display + * from the machine specific parameters. + */ + var->red = fbi->rgb[rgbidx]->red; + var->green = fbi->rgb[rgbidx]->green; + var->blue = fbi->rgb[rgbidx]->blue; + var->transp = fbi->rgb[rgbidx]->transp; + + DPRINTK("RGBT length = %d:%d:%d:%d\n", + var->red.length, var->green.length, var->blue.length, + var->transp.length); + + DPRINTK("RGBT offset = %d:%d:%d:%d\n", + var->red.offset, var->green.offset, var->blue.offset, + var->transp.offset); + #ifdef CONFIG_CPU_FREQ printk(KERN_DEBUG "dma period = %d ps, clock = %d kHz\n", sa1100fb_display_dma_period(var), cpufreq_get(smp_processor_id())); #endif - return ret; + return 0; } static inline void sa1100fb_set_truecolor(u_int is_true_color) { - DPRINTK("true_color = %d\n", is_true_color); - if (machine_is_assabet()) { -#if 1 - // phase 4 or newer Assabet's +#if 1 // phase 4 or newer Assabet's if (is_true_color) ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB); else @@ -1033,10 +998,30 @@ static inline void sa1100fb_set_truecolor(u_int is_true_color) } } -static void -sa1100fb_hw_set_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi) +/* + * sa1100fb_set_par(): + * Set the user defined part of the display for the specified console + */ +static int sa1100fb_set_par(struct fb_info *info) { - u_long palette_mem_size; + struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; + struct fb_var_screeninfo *var = &info->var; + unsigned long palette_mem_size; + + DPRINTK("set_par\n"); + + if (var->bits_per_pixel == 16) + fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR; + else if (!fbi->cmap_static) + fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; + else { + /* + * Some people have weird ideas about wanting static + * pseudocolor maps. I suspect their user space + * applications are broken. + */ + fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR; + } fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16; @@ -1047,10 +1032,10 @@ sa1100fb_hw_set_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi) fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size); fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size; - fb_set_cmap(&fbi->fb.cmap, 1, &fbi->fb); - - /* Set board control register to handle new color depth */ - sa1100fb_set_truecolor(var->bits_per_pixel >= 16); + /* + * Set (any) board control register to handle new color depth + */ + sa1100fb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR); #ifdef CONFIG_SA1100_OMNIMETER #error Do we have to do this here? We already do it at init time. @@ -1060,9 +1045,7 @@ sa1100fb_hw_set_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi) sa1100fb_activate_var(var, fbi); - fbi->palette_cpu[0] = (fbi->palette_cpu[0] & - 0xcfff) | palette_pbs(var); - + return 0; } /* @@ -1072,197 +1055,38 @@ sa1100fb_hw_set_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi) static int sa1100fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) { - struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; - struct fb_var_screeninfo *dvar = get_con_var(&fbi->fb, con); - struct display *display = get_con_display(&fbi->fb, con); - int err, chgvar = 0, rgbidx; - - DPRINTK("set_var\n"); + int ret, act; - /* - * Decode var contents into a par structure, adjusting any - * out of range values. - */ - err = sa1100fb_validate_var(var, fbi); - if (err) - return err; + act = var->activate & FB_ACTIVATE_MASK; - if (var->activate & FB_ACTIVATE_TEST) - return 0; + ret = gen_set_var(var, con, info); - if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) - return -EINVAL; + if (ret == 0 && act & FB_ACTIVATE_NOW) { + struct display *display = (con < 0) ? info->disp : fb_display + con; - if (dvar->xres != var->xres) - chgvar = 1; - if (dvar->yres != var->yres) - chgvar = 1; - if (dvar->xres_virtual != var->xres_virtual) - chgvar = 1; - if (dvar->yres_virtual != var->yres_virtual) - chgvar = 1; - if (dvar->bits_per_pixel != var->bits_per_pixel) - chgvar = 1; - if (con < 0) - chgvar = 0; - - switch (var->bits_per_pixel) { -#ifdef FBCON_HAS_CFB4 - case 4: - if (fbi->cmap_static) - display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR; - else - display->visual = FB_VISUAL_PSEUDOCOLOR; - display->line_length = var->xres / 2; - display->dispsw = &fbcon_cfb4; - rgbidx = RGB_8; - break; -#endif -#ifdef FBCON_HAS_CFB8 - case 8: - if (fbi->cmap_static) - display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR; - else - display->visual = FB_VISUAL_PSEUDOCOLOR; - display->line_length = var->xres; - display->dispsw = &fbcon_cfb8; - rgbidx = RGB_8; - break; -#endif -#ifdef FBCON_HAS_CFB16 - case 16: - display->visual = FB_VISUAL_TRUECOLOR; - display->line_length = var->xres * 2; - display->dispsw = &fbcon_cfb16; - display->dispsw_data = fbi->fb.pseudo_palette; - rgbidx = RGB_16; - break; -#endif - default: - rgbidx = 0; - display->dispsw = &fbcon_dummy; - break; + /* + * fbcon assumes too much. + */ + display->can_soft_blank = 1; } - display->next_line = display->line_length; - display->type = fbi->fb.fix.type; - display->type_aux = fbi->fb.fix.type_aux; - display->ypanstep = fbi->fb.fix.ypanstep; - display->ywrapstep = fbi->fb.fix.ywrapstep; - display->can_soft_blank = 1; - display->inverse = fbi->cmap_inverse; - - *dvar = *var; - dvar->activate &= ~FB_ACTIVATE_ALL; - - /* - * Copy the RGB parameters for this display - * from the machine specific parameters. - */ - dvar->red = fbi->rgb[rgbidx]->red; - dvar->green = fbi->rgb[rgbidx]->green; - dvar->blue = fbi->rgb[rgbidx]->blue; - dvar->transp = fbi->rgb[rgbidx]->transp; - - DPRINTK("RGBT length = %d:%d:%d:%d\n", - dvar->red.length, dvar->green.length, dvar->blue.length, - dvar->transp.length); - - DPRINTK("RGBT offset = %d:%d:%d:%d\n", - dvar->red.offset, dvar->green.offset, dvar->blue.offset, - dvar->transp.offset); - - /* - * Update the old var. The fbcon drivers still use this. - * Once they are using fbi->fb.var, this can be dropped. - */ - display->var = *dvar; - - /* - * If we are setting all the virtual consoles, also set the - * defaults used to create new consoles. - */ - if (var->activate & FB_ACTIVATE_ALL) - fbi->fb.disp->var = *dvar; - - /* - * If the console has changed and the console has defined - * a changevar function, call that function. - */ - if (chgvar && info && fbi->fb.changevar) - fbi->fb.changevar(con); - - /* If the current console is selected, activate the new var. */ - if (con != fbi->fb.currcon) - return 0; - - sa1100fb_hw_set_var(dvar, fbi); - - return 0; -} - -static int -__do_set_cmap(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info) -{ - struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; - struct fb_cmap *dcmap = get_con_cmap(info, con); - int err = 0; - - if (con == -1) - con = info->currcon; - - /* no colormap allocated? (we always have "this" colour map allocated) */ - if (con >= 0) - err = fb_alloc_cmap(&fb_display[con].cmap, fbi->palette_size, 0); - - if (!err && con == info->currcon) - err = fb_set_cmap(cmap, kspc, info); - - if (!err) - fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1); - - return err; + return ret; } static int sa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) { - struct display *disp = get_con_display(info, con); + struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; + struct display *disp = (con < 0) ? info->disp : (fb_display + con); - if (disp->visual == FB_VISUAL_TRUECOLOR || - disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR) + /* + * Make sure the user isn't doing something stupid. + */ + if (!kspc && (disp->var.bits_per_pixel == 16 || fbi->cmap_static)) return -EINVAL; - return __do_set_cmap(cmap, kspc, con, info); -} - -static int -sa1100fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) -{ - struct display *display = get_con_display(info, con); - - *fix = info->fix; - - fix->line_length = display->line_length; - fix->visual = display->visual; - return 0; -} - -static int -sa1100fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) -{ - *var = *get_con_var(info, con); - return 0; -} - -static int -sa1100fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) -{ - struct fb_cmap *dcmap = get_con_cmap(info, con); - fb_copy_cmap(dcmap, cmap, kspc ? 0 : 2); - return 0; + return gen_set_cmap(cmap, kspc, con, info); } /* @@ -1312,16 +1136,16 @@ static int sa1100fb_blank(int blank, struct fb_info *info) case VESA_POWERDOWN: case VESA_VSYNC_SUSPEND: case VESA_HSYNC_SUSPEND: - if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR || - fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR) + if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR || + fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) for (i = 0; i < fbi->palette_size; i++) sa1100fb_setpalettereg(i, 0, 0, 0, 0, info); sa1100fb_schedule_task(fbi, C_DISABLE); break; case VESA_NO_BLANKING: - if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR || - fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR) + if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR || + fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) fb_set_cmap(&fbi->fb.cmap, 1, info); sa1100fb_schedule_task(fbi, C_ENABLE); } @@ -1329,71 +1153,19 @@ static int sa1100fb_blank(int blank, struct fb_info *info) } static struct fb_ops sa1100fb_ops = { - owner: THIS_MODULE, - fb_get_fix: sa1100fb_get_fix, - fb_get_var: sa1100fb_get_var, - fb_set_var: sa1100fb_set_var, - fb_get_cmap: sa1100fb_get_cmap, - fb_set_cmap: sa1100fb_set_cmap, - fb_setcolreg: sa1100fb_setcolreg, - fb_blank: sa1100fb_blank, + .owner = THIS_MODULE, + .fb_check_var = sa1100fb_check_var, + .fb_set_par = sa1100fb_set_par, + .fb_set_var = sa1100fb_set_var, + .fb_get_cmap = gen_get_cmap, + .fb_set_cmap = sa1100fb_set_cmap, + .fb_setcolreg = sa1100fb_setcolreg, + .fb_blank = sa1100fb_blank, }; -/* - * sa1100fb_switch(): - * Change to the specified console. Palette and video mode - * are changed to the console's stored parameters. - * - * Uh oh, this can be called from a tasklet (IRQ) - */ -static int sa1100fb_switch(int con, struct fb_info *info) -{ - struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; - struct display *disp; - struct fb_cmap *cmap; - - DPRINTK("con=%d info->modename=%s\n", con, fbi->fb.modename); - - if (con == info->currcon) - return 0; - - if (info->currcon >= 0) { - disp = fb_display + info->currcon; - - /* - * Save the old colormap and video mode. - */ - disp->var = fbi->fb.var; - - if (disp->cmap.len) - fb_copy_cmap(&fbi->fb.cmap, &disp->cmap, 0); - } - - info->currcon = con; - disp = fb_display + con; - - /* - * Make sure that our colourmap contains 256 entries. - */ - fb_alloc_cmap(&fbi->fb.cmap, 256, 0); - - if (disp->cmap.len) - cmap = &disp->cmap; - else - cmap = fb_default_cmap(1 << disp->var.bits_per_pixel); - - fb_copy_cmap(cmap, &fbi->fb.cmap, 0); - - fbi->fb.var = disp->var; - fbi->fb.var.activate = FB_ACTIVATE_NOW; - - sa1100fb_set_var(&fbi->fb.var, con, info); - return 0; -} - static int sa1100fb_updatevar(int con, struct fb_info *info) { - DPRINTK("entered\n"); + /* we don't support panning nor scrolling */ return 0; } @@ -1401,34 +1173,14 @@ static int sa1100fb_updatevar(int con, struct fb_info *info) * Calculate the PCD value from the clock rate (in picoseconds). * We take account of the PPCR clock setting. */ -static inline int get_pcd(unsigned int pixclock) +static inline unsigned int get_pcd(unsigned int pixclock, unsigned int cpuclock) { - unsigned int pcd; - - if (pixclock) { - pcd = cpufreq_get(0) / 100; - pcd *= pixclock; - pcd /= 10000000; - pcd += 1; /* make up for integer math truncations */ - } else { - /* - * People seem to be missing this message. Make it big. - * Make it stand out. Make sure people see it. - */ - printk(KERN_WARNING "******************************************************\n"); - printk(KERN_WARNING "** ZERO PIXEL CLOCK DETECTED **\n"); - printk(KERN_WARNING "** You are using a zero pixclock. This means that **\n"); - printk(KERN_WARNING "** clock scaling will not be able to adjust your **\n"); - printk(KERN_WARNING "** your timing parameters appropriately, and the **\n"); - printk(KERN_WARNING "** bandwidth calculations will fail to work. This **\n"); - printk(KERN_WARNING "** will shortly become an error condition, which **\n"); - printk(KERN_WARNING "** will prevent your LCD display working. Please **\n"); - printk(KERN_WARNING "** send your patches in as soon as possible to shut **\n"); - printk(KERN_WARNING "** this message up. **\n"); - printk(KERN_WARNING "******************************************************\n"); - pcd = 0; - } - return pcd; + unsigned int pcd = cpuclock / 100; + + pcd *= pixclock; + pcd /= 10000000; + + return pcd + 1; /* make up for integer math truncations */ } /* @@ -1439,7 +1191,7 @@ static inline int get_pcd(unsigned int pixclock) static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi) { struct sa1100fb_lcd_reg new_regs; - u_int half_screen_size, yres, pcd = get_pcd(var->pixclock); + u_int half_screen_size, yres, pcd; u_long flags; DPRINTK("Configuring SA1100 LCD\n"); @@ -1502,13 +1254,10 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_ LCCR2_BegFrmDel(var->upper_margin) + LCCR2_EndFrmDel(var->lower_margin); - new_regs.lccr3 = fbi->lccr3 | + pcd = get_pcd(var->pixclock, cpufreq_get(0)); + new_regs.lccr3 = LCCR3_PixClkDiv(pcd) | fbi->lccr3 | (var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) | - (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL) | - LCCR3_ACBsCntOff; - - if (pcd) - new_regs.lccr3 |= LCCR3_PixClkDiv(pcd); + (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL); DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0); DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1); @@ -1547,61 +1296,20 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_ * to ensure that things happen in the right way 100% of time time. * -- rmk */ - -/* - * FIXME: move LCD power stuff into sa1100fb_power_up_lcd() - * Also, I'm expecting that the backlight stuff should - * be handled differently. - */ -static inline void sa1100fb_backlight_on(struct sa1100fb_info *fbi) -{ - DPRINTK("backlight on\n"); - - if (sa1100fb_backlight_power) - sa1100fb_backlight_power(1); -} - -/* - * FIXME: move LCD power stuf into sa1100fb_power_down_lcd() - * Also, I'm expecting that the backlight stuff should - * be handled differently. - */ -static inline void sa1100fb_backlight_off(struct sa1100fb_info *fbi) +static inline void __sa1100fb_backlight_power(struct sa1100fb_info *fbi, int on) { - DPRINTK("backlight off\n"); + DPRINTK("backlight o%s\n", on ? "n" : "ff"); if (sa1100fb_backlight_power) - sa1100fb_backlight_power(0); + sa1100fb_backlight_power(on); } -static inline void sa1100fb_power_up_lcd(struct sa1100fb_info *fbi) +static inline void __sa1100fb_lcd_power(struct sa1100fb_info *fbi, int on) { - DPRINTK("LCD power on\n"); + DPRINTK("LCD power o%s\n", on ? "n" : "ff"); if (sa1100fb_lcd_power) - sa1100fb_lcd_power(1); - -#ifdef CONFIG_SA1100_STORK - if (machine_is_stork()) { - storkSetLCDCPLD(0, 1); - storkSetLatchA(STORK_LCD_BACKLIGHT_INVERTER_ON); - } -#endif -} - -static inline void sa1100fb_power_down_lcd(struct sa1100fb_info *fbi) -{ - DPRINTK("LCD power off\n"); - - if (sa1100fb_lcd_power) - sa1100fb_lcd_power(0); - -#ifdef CONFIG_SA1100_STORK - if (machine_is_stork()) { - storkSetLCDCPLD(0, 0); - storkClearLatchA(STORK_LCD_BACKLIGHT_INVERTER_ON); - } -#endif + sa1100fb_lcd_power(on); } static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi) @@ -1630,38 +1338,9 @@ static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi) } - if (machine_is_cerf()) { - /* GPIO15 is used as a bypass for 3.8" displays */ + /* GPIO15 is used as a bypass for 3.8" displays */ + if (machine_is_cerf()) mask |= GPIO_GPIO15; -#ifdef CONFIG_SA1100_CERF -#warning Read Me Now! -#endif -#if 0 /* if this causes you problems, mail <rmk@arm.linux.org.uk> please. */ - /* - * This was enabled for the 72_A version only, which is a _color_ - * _dual_ LCD. Now look at the generic test above, and calculate - * the mask value for a colour dual display... - * - * I therefore conclude that the code below is redundant, and will - * be killed at the start of November 2001. - */ - /* FIXME: why is this? The Cerf's display doesn't seem - * to be dual scan or active. I just leave it here, - * but in my opinion this is definitively wrong. - * -- Erik <J.A.K.Mouw@its.tudelft.nl> - */ - - /* REPLY: Umm.. Well to be honest, the 5.7" LCD which - * this was used for does not use these pins, but - * apparently all hell breaks loose if they are not - * set on the Cerf, so we decided to leave them in ;) - * -- Daniel Chemko <dchemko@intrinsyc.com> - */ - /* color {dual/single} passive */ - mask |= GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 | - GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8; -#endif - } if (mask) { GPDR |= mask; @@ -1733,7 +1412,7 @@ static void sa1100fb_disable_controller(struct sa1100fb_info *fbi) } #endif #ifdef CONFIG_SA1100_HUW_WEBPANEL -#error Move me into sa1100fb_power_up_lcd and/or sa1100fb_backlight_on +#error Move me into __sa1100fb_lcd_power and/or __sa1100fb_backlight_power if (machine_is_huw_webpanel()) { // dont forget to set the control lines to zero (?) DPRINTK("ShutDown HuW LCD controller\n"); @@ -1806,10 +1485,10 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state) if (old_state != C_DISABLE) { fbi->state = state; - sa1100fb_backlight_off(fbi); + __sa1100fb_backlight_power(fbi, 0); if (old_state != C_DISABLE_CLKCHANGE) sa1100fb_disable_controller(fbi); - sa1100fb_power_down_lcd(fbi); + __sa1100fb_lcd_power(fbi, 0); } break; @@ -1855,9 +1534,9 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state) if (old_state != C_ENABLE) { fbi->state = C_ENABLE; sa1100fb_setup_gpio(fbi); - sa1100fb_power_up_lcd(fbi); + __sa1100fb_lcd_power(fbi, 1); sa1100fb_enable_controller(fbi); - sa1100fb_backlight_on(fbi); + __sa1100fb_backlight_power(fbi, 1); } break; } @@ -1888,18 +1567,19 @@ static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi) int i; for (i = 0; i < MAX_NR_CONSOLES; i++) { + struct display *disp = &fb_display[i]; unsigned int period; /* * Do we own this display? */ - if (fb_display[i].fb_info != &fbi->fb) + if (disp->fb_info != &fbi->fb) continue; /* * Ok, calculate its DMA period */ - period = sa1100fb_display_dma_period(get_con_var(&fbi->fb, i)); + period = sa1100fb_display_dma_period(&disp->var); if (period < min_period) min_period = period; } @@ -1913,33 +1593,42 @@ static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi) * subsystem. */ static int -sa1100fb_clkchg_notifier(struct notifier_block *nb, unsigned long val, +sa1100fb_freq_transition(struct notifier_block *nb, unsigned long val, void *data) { - struct sa1100fb_info *fbi = TO_INF(nb, clockchg); - struct cpufreq_minmax *mm = data; + struct sa1100fb_info *fbi = TO_INF(nb, freq_transition); + struct cpufreq_freqs *f = data; u_int pcd; switch (val) { - case CPUFREQ_MINMAX: - printk(KERN_DEBUG "min dma period: %d ps, old clock %d kHz, " - "new clock %d kHz\n", sa1100fb_min_dma_period(fbi), - mm->cur_freq, mm->new_freq); - /* todo: fill in min/max values */ - break; - case CPUFREQ_PRECHANGE: set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE); break; case CPUFREQ_POSTCHANGE: - pcd = get_pcd(fbi->fb.var.pixclock); + pcd = get_pcd(fbi->fb.var.pixclock, f->new); fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd); set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE); break; } return 0; } + +static int +sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val, + void *data) +{ + struct sa1100fb_info *fbi = TO_INF(nb, freq_policy); + struct cpufreq_policy *policy = data; + + if (val == CPUFREQ_INCOMPATIBLE) { + printk(KERN_DEBUG "min dma period: %d ps, " + "new clock %d kHz\n", sa1100fb_min_dma_period(fbi), + policy->max); + /* todo: fill in min/max values */ + } + return 0; +} #endif #ifdef CONFIG_PM @@ -2015,8 +1704,6 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void) memset(fbi, 0, sizeof(struct sa1100fb_info) + sizeof(struct display)); - fbi->fb.currcon = -1; - strcpy(fbi->fb.fix.id, SA1100_NAME); fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS; @@ -2024,6 +1711,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void) fbi->fb.fix.xpanstep = 0; fbi->fb.fix.ypanstep = 0; fbi->fb.fix.ywrapstep = 0; + fbi->fb.fix.line_length = 0; fbi->fb.fix.accel = FB_ACCEL_NONE; fbi->fb.var.nonstd = 0; @@ -2038,7 +1726,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void) fbi->fb.fbops = &sa1100fb_ops; fbi->fb.changevar = NULL; - fbi->fb.switch_con = sa1100fb_switch; + fbi->fb.switch_con = gen_switch; fbi->fb.updatevar = sa1100fb_updatevar; fbi->fb.flags = FBINFO_FLAG_DEFAULT; fbi->fb.node = NODEV; @@ -2052,6 +1740,16 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void) inf = sa1100fb_get_machine_info(fbi); + /* + * People just don't seem to get this. We don't support + * anything but correct entries now, so panic if someone + * does something stupid. + */ + if (inf->lccr3 & (LCCR3_VrtSnchL|LCCR3_HorSnchL|0xff) || + inf->pixclock == 0) + panic("sa1100fb error: invalid LCCR3 fields set or zero " + "pixclock."); + fbi->max_xres = inf->xres; fbi->fb.var.xres = inf->xres; fbi->fb.var.xres_virtual = inf->xres; @@ -2077,6 +1775,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void) fbi->task_state = (u_char)-1; fbi->fb.fix.smem_len = fbi->max_xres * fbi->max_yres * fbi->max_bpp / 8; + fbi->fb.disp->inverse = inf->cmap_inverse; init_waitqueue_head(&fbi->ctrlr_wait); INIT_TQUEUE(&fbi->task, sa1100fb_task, fbi); @@ -2116,7 +1815,7 @@ int __init sa1100fb_init(void) #endif #ifdef CONFIG_SA1100_FREEBIRD -#error Please move this into sa1100fb_power_up_lcd +#error Please move this into __sa1100fb_lcd_power if (machine_is_freebird()) { BCR_set(BCR_FREEBIRD_LCD_DISP); mdelay(20); @@ -2141,8 +1840,10 @@ int __init sa1100fb_init(void) fbi->pm->data = fbi; #endif #ifdef CONFIG_CPU_FREQ - fbi->clockchg.notifier_call = sa1100fb_clkchg_notifier; - cpufreq_register_notifier(&fbi->clockchg); + fbi->freq_transition.notifier_call = sa1100fb_freq_transition; + fbi->freq_policy.notifier_call = sa1100fb_freq_policy; + cpufreq_register_notifier(&fbi->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); + cpufreq_register_notifier(&fbi->freq_policy, CPUFREQ_POLICY_NOTIFIER); #endif /* diff --git a/drivers/video/sa1100fb.h b/drivers/video/sa1100fb.h index 96e79705be5cc5488046e68a7fa674f34851f51a..9b3b4a402a51d0564f59d21a79b6a8dd95e361b6 100644 --- a/drivers/video/sa1100fb.h +++ b/drivers/video/sa1100fb.h @@ -107,7 +107,8 @@ struct sa1100fb_info { struct pm_dev *pm; #endif #ifdef CONFIG_CPU_FREQ - struct notifier_block clockchg; + struct notifier_block freq_transition; + struct notifier_block freq_policy; #endif }; diff --git a/include/asm-arm/arch-sa1100/h3600.h b/include/asm-arm/arch-sa1100/h3600.h index d0fc9198c9eb08bdcbc5a7f7966afbc7dbf9a3e2..1b6355971574a0b2be21a881e4dedb8f45c8d92a 100644 --- a/include/asm-arm/arch-sa1100/h3600.h +++ b/include/asm-arm/arch-sa1100/h3600.h @@ -16,7 +16,7 @@ * * History: * - * 2001-10-?? Andrew Christian Added support for iPAQ H3800 + * 2001-10-?? Andrew Christian Added support for iPAQ H3800 * */ @@ -26,6 +26,11 @@ /* generalized support for H3xxx series Compaq Pocket PC's */ #define machine_is_h3xxx() (machine_is_h3100() || machine_is_h3600() || machine_is_h3800()) +/* Physical memory regions corresponding to chip selects */ +#define H3600_EGPIO_PHYS (SA1100_CS5_PHYS + 0x01000000) +#define H3600_BANK_2_PHYS SA1100_CS2_PHYS +#define H3600_BANK_4_PHYS SA1100_CS4_PHYS + /* Virtual memory regions corresponding to chip selects 2 & 4 (used on sleeves) */ #define H3600_EGPIO_VIRT 0xf0000000 #define H3600_BANK_2_VIRT 0xf1000000 @@ -36,8 +41,7 @@ --- these are common across all current iPAQ platforms */ -#define GPIO_H3600_NPOWER_BUTTON GPIO_GPIO (0) /* Also known as the "off button" */ -#define GPIO_H3600_MICROCONTROLLER GPIO_GPIO (1) /* From ASIC2 on H3800 */ +#define GPIO_H3600_NPOWER_BUTTON GPIO_GPIO (0) /* Also known as the "off button" */ #define GPIO_H3600_PCMCIA_CD1 GPIO_GPIO (10) #define GPIO_H3600_PCMCIA_IRQ1 GPIO_GPIO (11) @@ -56,83 +60,105 @@ #define GPIO_H3600_COM_CTS GPIO_GPIO (25) #define GPIO_H3600_COM_RTS GPIO_GPIO (26) -#define IRQ_GPIO_H3600_NPOWER_BUTTON IRQ_GPIO0 -#define IRQ_GPIO_H3600_MICROCONTROLLER IRQ_GPIO1 +#define IRQ_GPIO_H3600_NPOWER_BUTTON IRQ_GPIO0 #define IRQ_GPIO_H3600_PCMCIA_CD1 IRQ_GPIO10 #define IRQ_GPIO_H3600_PCMCIA_IRQ1 IRQ_GPIO11 #define IRQ_GPIO_H3600_PCMCIA_CD0 IRQ_GPIO17 #define IRQ_GPIO_H3600_PCMCIA_IRQ0 IRQ_GPIO21 -#define IRQ_GPIO_H3600_COM_DCD IRQ_GPIO23 +#define IRQ_GPIO_H3600_COM_DCD IRQ_GPIO23 #define IRQ_GPIO_H3600_OPT_IRQ IRQ_GPIO24 -#define IRQ_GPIO_H3600_COM_CTS IRQ_GPIO25 +#define IRQ_GPIO_H3600_COM_CTS IRQ_GPIO25 #ifndef __ASSEMBLY__ -enum ipaq_model { - IPAQ_H3100, - IPAQ_H3600, - IPAQ_H3800 -}; enum ipaq_egpio_type { - IPAQ_EGPIO_LCD_ON, /* Power to the LCD panel */ + IPAQ_EGPIO_LCD_POWER, /* Power to the LCD panel */ IPAQ_EGPIO_CODEC_NRESET, /* Clear to reset the audio codec (remember to return high) */ - IPAQ_EGPIO_AUDIO_ON, /* Audio power */ - IPAQ_EGPIO_QMUTE, /* Audio muting */ + IPAQ_EGPIO_AUDIO_ON, /* Audio power */ + IPAQ_EGPIO_QMUTE, /* Audio muting */ IPAQ_EGPIO_OPT_NVRAM_ON, /* Non-volatile RAM on extension sleeves (SPI interface) */ - IPAQ_EGPIO_OPT_ON, /* Power to extension sleeves */ - IPAQ_EGPIO_CARD_RESET, /* Reset PCMCIA cards on extension sleeve (???) */ - IPAQ_EGPIO_OPT_RESET, /* Reset option pack (???) */ - IPAQ_EGPIO_IR_ON, /* IR sensor/emitter power */ - IPAQ_EGPIO_IR_FSEL, /* IR speed selection 1->fast, 0->slow */ - IPAQ_EGPIO_RS232_ON, /* Maxim RS232 chip power */ - IPAQ_EGPIO_VPP_ON, /* Turn on power to flash programming */ + IPAQ_EGPIO_OPT_ON, /* Power to extension sleeves */ + IPAQ_EGPIO_CARD_RESET, /* Reset PCMCIA cards on extension sleeve (???) */ + IPAQ_EGPIO_OPT_RESET, /* Reset option pack (???) */ + IPAQ_EGPIO_IR_ON, /* IR sensor/emitter power */ + IPAQ_EGPIO_IR_FSEL, /* IR speed selection 1->fast, 0->slow */ + IPAQ_EGPIO_RS232_ON, /* Maxim RS232 chip power */ + IPAQ_EGPIO_VPP_ON, /* Turn on power to flash programming */ + IPAQ_EGPIO_LCD_ENABLE, /* Enable/disable LCD controller */ }; struct ipaq_model_ops { - enum ipaq_model model; const char *generic_name; - void (*initialize)(void); - void (*control)(enum ipaq_egpio_type, int); + void (*control)(enum ipaq_egpio_type, int); unsigned long (*read)(void); + void (*blank_callback)(int blank); + int (*pm_callback)(int req); /* Primary model callback */ + int (*pm_callback_aux)(int req); /* Secondary callback (used by HAL modules) */ }; extern struct ipaq_model_ops ipaq_model_ops; -static __inline__ enum ipaq_model h3600_model( void ) { - return ipaq_model_ops.model; -} - -static __inline__ const char * h3600_generic_name( void ) { +static __inline__ const char * h3600_generic_name(void) +{ return ipaq_model_ops.generic_name; } -static __inline__ void init_h3600_egpio( void ) { - if (ipaq_model_ops.initialize) - ipaq_model_ops.initialize(); -} - -static __inline__ void assign_h3600_egpio( enum ipaq_egpio_type x, int level ) { +static __inline__ void assign_h3600_egpio(enum ipaq_egpio_type x, int level) +{ if (ipaq_model_ops.control) ipaq_model_ops.control(x,level); } -static __inline__ void clr_h3600_egpio( enum ipaq_egpio_type x ) { +static __inline__ void clr_h3600_egpio(enum ipaq_egpio_type x) +{ if (ipaq_model_ops.control) ipaq_model_ops.control(x,0); } -static __inline__ void set_h3600_egpio( enum ipaq_egpio_type x ) { +static __inline__ void set_h3600_egpio(enum ipaq_egpio_type x) +{ if (ipaq_model_ops.control) ipaq_model_ops.control(x,1); } -static __inline__ unsigned long read_h3600_egpio( void ) { +static __inline__ unsigned long read_h3600_egpio(void) +{ if (ipaq_model_ops.read) return ipaq_model_ops.read(); return 0; } +static __inline__ int h3600_register_blank_callback(void (*f)(int)) +{ + ipaq_model_ops.blank_callback = f; + return 0; +} + +static __inline__ void h3600_unregister_blank_callback(void (*f)(int)) +{ + ipaq_model_ops.blank_callback = NULL; +} + + +static __inline__ int h3600_register_pm_callback(int (*f)(int)) +{ + ipaq_model_ops.pm_callback_aux = f; + return 0; +} + +static __inline__ void h3600_unregister_pm_callback(int (*f)(int)) +{ + ipaq_model_ops.pm_callback_aux = NULL; +} + +static __inline__ int h3600_power_management(int req) +{ + if (ipaq_model_ops.pm_callback) + return ipaq_model_ops.pm_callback(req); + return 0; +} + #endif /* ASSEMBLY */ #endif /* _INCLUDE_H3600_H_ */ diff --git a/include/asm-arm/arch-sa1100/irqs.h b/include/asm-arm/arch-sa1100/irqs.h index cc5dcda895c601e4911d7e88d06c49bd28388096..66e4f596c739ec74d1f48e28d0179f88674537ad 100644 --- a/include/asm-arm/arch-sa1100/irqs.h +++ b/include/asm-arm/arch-sa1100/irqs.h @@ -108,18 +108,18 @@ #define AUDDTS (IRQ_BOARD_END + 40) #define AUDRDD (IRQ_BOARD_END + 41) #define AUDSTO (IRQ_BOARD_END + 42) -#define USBPWR (IRQ_BOARD_END + 43) -#define NIRQHCIM (IRQ_BOARD_END + 44) -#define IRQHCIBUFFACC (IRQ_BOARD_END + 45) -#define IRQHCIRMTWKP (IRQ_BOARD_END + 46) -#define NHCIMFCIR (IRQ_BOARD_END + 47) -#define USB_PORT_RESUME (IRQ_BOARD_END + 48) -#define S0_READY_NINT (IRQ_BOARD_END + 49) -#define S1_READY_NINT (IRQ_BOARD_END + 50) -#define S0_CD_VALID (IRQ_BOARD_END + 51) -#define S1_CD_VALID (IRQ_BOARD_END + 52) -#define S0_BVD1_STSCHG (IRQ_BOARD_END + 53) -#define S1_BVD1_STSCHG (IRQ_BOARD_END + 54) +#define IRQ_USBPWR (IRQ_BOARD_END + 43) +#define IRQ_NHCIM (IRQ_BOARD_END + 44) +#define IRQ_HCIBUFFACC (IRQ_BOARD_END + 45) +#define IRQ_HCIRMTWKP (IRQ_BOARD_END + 46) +#define IRQ_NHCIMFCIR (IRQ_BOARD_END + 47) +#define IRQ_USB_PORT_RESUME (IRQ_BOARD_END + 48) +#define IRQ_S0_READY_NINT (IRQ_BOARD_END + 49) +#define IRQ_S1_READY_NINT (IRQ_BOARD_END + 50) +#define IRQ_S0_CD_VALID (IRQ_BOARD_END + 51) +#define IRQ_S1_CD_VALID (IRQ_BOARD_END + 52) +#define IRQ_S0_BVD1_STSCHG (IRQ_BOARD_END + 53) +#define IRQ_S1_BVD1_STSCHG (IRQ_BOARD_END + 54) /* * Figure out the MAX IRQ number. @@ -129,7 +129,7 @@ * Otherwise, we have the standard IRQs only. */ #ifdef CONFIG_SA1111 -#define NR_IRQS (S1_BVD1_STSCHG + 1) +#define NR_IRQS (IRQ_S1_BVD1_STSCHG + 1) #elif defined(CONFIG_SA1100_GRAPHICSCLIENT) || \ defined(CONFIG_SA1100_GRAPHICSMASTER) || \ defined(CONFIG_SA1100_H3800) diff --git a/include/asm-arm/hardware/sa1111.h b/include/asm-arm/hardware/sa1111.h index c334e869f8ef22e9fb39ee88884c0fd1d632a712..311e4832eb2fbc0639763d818a380d2df0b17028 100644 --- a/include/asm-arm/hardware/sa1111.h +++ b/include/asm-arm/hardware/sa1111.h @@ -64,18 +64,10 @@ #define SA1111_SMCR 0x0004 #define SA1111_SKID 0x0008 -#define _SBI_SKCR _SA1111(SA1111_SKCR) -#define _SBI_SMCR _SA1111(SA1111_SMCR) -#define _SBI_SKID _SA1111(SA1111_SKID) - -#if LANGUAGE == C - #define SBI_SKCR __CCREG(SA1111_SKCR) #define SBI_SMCR __CCREG(SA1111_SMCR) #define SBI_SKID __CCREG(SA1111_SKID) -#endif /* LANGUAGE == C */ - #define SKCR_PLL_BYPASS (1<<0) #define SKCR_RCLKEN (1<<1) #define SKCR_SLEEP (1<<2) @@ -135,22 +127,10 @@ #define SA1111_SKPMC 0x020c #define SA1111_SKPTC 0x0210 #define SA1111_SKPEN0 0x0214 -#define SA1111_SKPWN0 0x0218 +#define SA1111_SKPWM0 0x0218 #define SA1111_SKPEN1 0x021c #define SA1111_SKPWM1 0x0220 -#define _SKPCR _SA1111(SA1111_SKPCR) -#define _SKCDR _SA1111(SA1111_SKCDR) -#define _SKAUD _SA1111(SA1111_SKAUD) -#define _SKPMC _SA1111(SA1111_SKPMC) -#define _SKPTC _SA1111(SA1111_SKPTC) -#define _SKPEN0 _SA1111(SA1111_SKPEN0) -#define _SKPWM0 _SA1111(SA1111_SKPWM0) -#define _SKPEN1 _SA1111(SA1111_SKPEN1) -#define _SKPWM1 _SA1111(SA1111_SKPWM1) - -#if LANGUAGE == C - #define SKPCR __CCREG(SA1111_SKPCR) #define SKCDR __CCREG(SA1111_SKCDR) #define SKAUD __CCREG(SA1111_SKAUD) @@ -161,8 +141,6 @@ #define SKPEN1 __CCREG(SA1111_SKPEN1) #define SKPWM1 __CCREG(SA1111_SKPWM1) -#endif /* LANGUAGE == C */ - #define SKPCR_UCLKEN (1<<0) #define SKPCR_ACCLKEN (1<<1) #define SKPCR_I2SCLKEN (1<<2) @@ -176,21 +154,14 @@ /* * USB Host controller */ -#define _USB_OHCI_OP_BASE _SA1111( 0x400 ) -#define _USB_STATUS _SA1111( 0x518 ) -#define _USB_RESET _SA1111( 0x51c ) -#define _USB_INTERRUPTEST _SA1111( 0x520 ) - -#define _USB_EXTENT (_USB_INTERRUPTEST - _USB_OHCI_OP_BASE + 4) - -#if LANGUAGE == C - -#define USB_OHCI_OP_BASE __CCREG(0x0400) -#define USB_STATUS __CCREG(0x0518) -#define USB_RESET __CCREG(0x051c) -#define USB_INTERRUPTEST __CCReG(0x0520) +#define SA1111_USB 0x0400 -#endif /* LANGUAGE == C */ +/* + * Offsets from SA1111_USB_BASE + */ +#define SA1111_USB_STATUS 0x0118 +#define SA1111_USB_RESET 0x011c +#define SA1111_USB_IRQTEST 0x0120 #define USB_RESET_FORCEIFRESET (1 << 0) #define USB_RESET_FORCEHCRESET (1 << 1) @@ -451,82 +422,56 @@ * WAKE_POL0 Wake-up polarity selection 0 * WAKE_POL1 Wake-up polarity selection 1 */ +#define SA1111_INTC 0x1600 -#define SA1111_INTTEST0 0x1600 -#define SA1111_INTTEST1 0x1604 -#define SA1111_INTEN0 0x1608 -#define SA1111_INTEN1 0x160c -#define SA1111_INTPOL0 0x1610 -#define SA1111_INTPOL1 0x1614 -#define SA1111_INTTSTSEL 0x1618 -#define SA1111_INTSTATCLR0 0x161c -#define SA1111_INTSTATCLR1 0x1620 -#define SA1111_INTSET0 0x1624 -#define SA1111_INTSET1 0x1628 -#define SA1111_WAKE_EN0 0x162c -#define SA1111_WAKE_EN1 0x1630 -#define SA1111_WAKE_POL0 0x1634 -#define SA1111_WAKE_POL1 0x1638 - -#define _INTTEST0 _SA1111(SA1111_INTTEST0) -#define _INTTEST1 _SA1111(SA1111_INTTEST1) -#define _INTEN0 _SA1111(SA1111_INTEN0) -#define _INTEN1 _SA1111(SA1111_INTEN1) -#define _INTPOL0 _SA1111(SA1111_INTPOL0) -#define _INTPOL1 _SA1111(SA1111_INTPOL1) -#define _INTTSTSEL _SA1111(SA1111_INTTSTSEL) -#define _INTSTATCLR0 _SA1111(SA1111_INTSTATCLR0) -#define _INTSTATCLR1 _SA1111(SA1111_INTSTATCLR1) -#define _INTSET0 _SA1111(SA1111_INTSET0) -#define _INTSET1 _SA1111(SA1111_INTSET1) -#define _WAKE_EN0 _SA1111(SA1111_WAKE_EN0) -#define _WAKE_EN1 _SA1111(SA1111_WAKE_EN1) -#define _WAKE_POL0 _SA1111(SA1111_WAKE_POL0) -#define _WAKE_POL1 _SA1111(SA1111_WAKE_POL1) - -#if LANGUAGE == C - -#define INTTEST0 __CCREG(SA1111_INTTEST0) -#define INTTEST1 __CCREG(SA1111_INTTEST1) -#define INTEN0 __CCREG(SA1111_INTEN0) -#define INTEN1 __CCREG(SA1111_INTEN1) -#define INTPOL0 __CCREG(SA1111_INTPOL0) -#define INTPOL1 __CCREG(SA1111_INTPOL1) -#define INTTSTSEL __CCREG(SA1111_INTTSTSEL) -#define INTSTATCLR0 __CCREG(SA1111_INTSTATCLR0) -#define INTSTATCLR1 __CCREG(SA1111_INTSTATCLR1) -#define INTSET0 __CCREG(SA1111_INTSET0) -#define INTSET1 __CCREG(SA1111_INTSET1) -#define WAKE_EN0 __CCREG(SA1111_WAKE_EN0) -#define WAKE_EN1 __CCREG(SA1111_WAKE_EN1) -#define WAKE_POL0 __CCREG(SA1111_WAKE_POL0) -#define WAKE_POL1 __CCREG(SA1111_WAKE_POL1) - -#endif /* LANGUAGE == C */ +/* + * These are offsets from the above base. + */ +#define SA1111_INTTEST0 0x0000 +#define SA1111_INTTEST1 0x0004 +#define SA1111_INTEN0 0x0008 +#define SA1111_INTEN1 0x000c +#define SA1111_INTPOL0 0x0010 +#define SA1111_INTPOL1 0x0014 +#define SA1111_INTTSTSEL 0x0018 +#define SA1111_INTSTATCLR0 0x001c +#define SA1111_INTSTATCLR1 0x0020 +#define SA1111_INTSET0 0x0024 +#define SA1111_INTSET1 0x0028 +#define SA1111_WAKEEN0 0x002c +#define SA1111_WAKEEN1 0x0030 +#define SA1111_WAKEPOL0 0x0034 +#define SA1111_WAKEPOL1 0x0038 + +#define INTTEST0 __CCREG(SA1111_INTC + SA1111_INTTEST0) +#define INTTEST1 __CCREG(SA1111_INTC + SA1111_INTTEST1) +#define INTEN0 __CCREG(SA1111_INTC + SA1111_INTEN0) +#define INTEN1 __CCREG(SA1111_INTC + SA1111_INTEN1) +#define INTPOL0 __CCREG(SA1111_INTC + SA1111_INTPOL0) +#define INTPOL1 __CCREG(SA1111_INTC + SA1111_INTPOL1) +#define INTTSTSEL __CCREG(SA1111_INTC + SA1111_INTTSTSEL) +#define INTSTATCLR0 __CCREG(SA1111_INTC + SA1111_INTSTATCLR0) +#define INTSTATCLR1 __CCREG(SA1111_INTC + SA1111_INTSTATCLR1) +#define INTSET0 __CCREG(SA1111_INTC + SA1111_INTSET0) +#define INTSET1 __CCREG(SA1111_INTC + SA1111_INTSET1) +#define WAKE_EN0 __CCREG(SA1111_INTC + SA1111_WAKEEN0) +#define WAKE_EN1 __CCREG(SA1111_INTC + SA1111_WAKEEN1) +#define WAKE_POL0 __CCREG(SA1111_INTC + SA1111_WAKEPOL0) +#define WAKE_POL1 __CCREG(SA1111_INTC + SA1111_WAKEPOL1) /* * PS/2 Trackpad and Mouse Interfaces * - * Registers (prefix kbd applies to trackpad interface, mse to mouse) - * KBDCR Control Register - * KBDSTAT Status Register - * KBDDATA Transmit/Receive Data register - * KBDCLKDIV Clock Division Register - * KBDPRECNT Clock Precount Register - * KBDTEST1 Test register 1 - * KBDTEST2 Test register 2 - * KBDTEST3 Test register 3 - * KBDTEST4 Test register 4 - * MSECR - * MSESTAT - * MSEDATA - * MSECLKDIV - * MSEPRECNT - * MSETEST1 - * MSETEST2 - * MSETEST3 - * MSETEST4 - * + * Registers + * PS2CR Control Register + * PS2STAT Status Register + * PS2DATA Transmit/Receive Data register + * PS2CLKDIV Clock Division Register + * PS2PRECNT Clock Precount Register + * PS2TEST1 Test register 1 + * PS2TEST2 Test register 2 + * PS2TEST3 Test register 3 + * PS2TEST4 Test register 4 */ #define SA1111_KBD 0x0a00 @@ -564,17 +509,14 @@ * PCSSR Sleep State Register */ -#define _PCCR _SA1111( 0x1800 ) -#define _PCSSR _SA1111( 0x1804 ) -#define _PCSR _SA1111( 0x1808 ) - -#if LANGUAGE == C - -#define PCCR __CCREG(0x1800) -#define PCSSR __CCREG(0x1804) -#define PCSR __CCREG(0x1808) +#define SA1111_PCMCIA 0x1600 -#endif /* LANGUAGE == C */ +/* + * These are offsets from the above base. + */ +#define SA1111_PCCR 0x0000 +#define SA1111_PCSSR 0x0004 +#define SA1111_PCSR 0x0008 #define PCSR_S0_READY (1<<0) #define PCSR_S1_READY (1<<1) @@ -603,21 +545,61 @@ #define PCSSR_S0_SLEEP (1<<0) #define PCSSR_S1_SLEEP (1<<1) -struct sa1111_device { + + + +extern struct bus_type sa1111_bus_type; + +#define SA1111_DEVID_SBI 0 +#define SA1111_DEVID_SK 1 +#define SA1111_DEVID_USB 2 +#define SA1111_DEVID_SAC 3 +#define SA1111_DEVID_SSP 4 +#define SA1111_DEVID_PS2 5 +#define SA1111_DEVID_GPIO 6 +#define SA1111_DEVID_INT 7 +#define SA1111_DEVID_PCMCIA 8 + +struct sa1111_dev { struct device dev; - struct resource resource; - void *base; + unsigned int devid; + struct resource res; + void *mapbase; + unsigned int skpcr_mask; + unsigned int irq[6]; }; -extern struct sa1111_device *sa1111; +#define SA1111_DEV(_d) container_of((_d), struct sa1111_dev, dev) -int sa1111_check_dma_bug(dma_addr_t addr); +struct sa1111_driver { + struct device_driver drv; + unsigned int devid; +}; + +#define SA1111_DRV(_d) container_of((_d), struct sa1111_driver, drv) + +#define SA1111_DRIVER_NAME(_sadev) ((_sadev)->dev.driver->name) + +/* + * Probe for a SA1111 chip. + */ +extern int sa1111_init(unsigned long phys, unsigned int irq); /* * These frob the SKPCR register. */ -void sa1111_enable_device(unsigned int mask); -void sa1111_disable_device(unsigned int mask); +void sa1111_enable_device(struct sa1111_dev *); +void sa1111_disable_device(struct sa1111_dev *); + +unsigned int sa1111_pll_clock(struct sa1111_dev *); +#define SA1111_AUDIO_ACLINK 0 +#define SA1111_AUDIO_I2S 1 + +void sa1111_select_audio_mode(struct sa1111_dev *sadev, int mode); +int sa1111_set_audio_rate(struct sa1111_dev *sadev, int rate); +int sa1111_get_audio_rate(struct sa1111_dev *sadev); + +int sa1111_check_dma_bug(dma_addr_t addr); #endif /* _ASM_ARCH_SA1111 */ diff --git a/include/asm-arm/pci.h b/include/asm-arm/pci.h index 70fcb5c4d021e0309a954d6c722c42936b4c215d..3a7310558dd2a7957ff9c728b3e858973c1816a9 100644 --- a/include/asm-arm/pci.h +++ b/include/asm-arm/pci.h @@ -27,15 +27,11 @@ void sa1111_dma_sync_sg(struct pci_dev *, struct scatterlist *, int, int); #ifdef CONFIG_SA1111 #define SA1111_FAKE_PCIDEV ((struct pci_dev *) 1111) - -static inline int dev_is_sa1111(const struct pci_dev *dev) -{ - return (dev == SA1111_FAKE_PCIDEV); -} +#define dev_is_sa1111(dev) (dev == SA1111_FAKE_PCIDEV) #else -static inline int dev_is_sa1111(const struct pci_dev *dev) { return 0; } +#define dev_is_sa1111(dev) (0) #endif