summaryrefslogtreecommitdiff
path: root/arch/arm/mach-sa1100/assabet.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-sa1100/assabet.c')
-rw-r--r--arch/arm/mach-sa1100/assabet.c379
1 files changed, 180 insertions, 199 deletions
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index d28ecb9ef172..2b833aa0212b 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -1,20 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* linux/arch/arm/mach-sa1100/assabet.c
*
* Author: Nicolas Pitre
*
* This file contains all Assabet-specific tweaks.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio/gpio-reg.h>
+#include <linux/gpio/machine.h>
+#include <linux/gpio_keys.h>
#include <linux/ioport.h>
#include <linux/platform_data/sa11x0-serial.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>
#include <linux/mfd/ucb1x00.h>
@@ -32,12 +35,10 @@
#include <asm/setup.h>
#include <asm/page.h>
#include <asm/pgtable-hwdef.h>
-#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
-#include <linux/platform_data/irda-sa11x0.h>
#include <asm/mach/map.h>
#include <mach/assabet.h>
#include <linux/platform_data/mfd-mcp-sa11x0.h>
@@ -61,20 +62,43 @@
unsigned long SCR_value = ASSABET_SCR_INIT;
EXPORT_SYMBOL(SCR_value);
-static unsigned long BCR_value = ASSABET_BCR_DB1110;
+static struct gpio_chip *assabet_bcr_gc;
+
+static const char *assabet_names[] = {
+ "cf_pwr", "cf_gfx_reset", "nsoft_reset", "irda_fsel",
+ "irda_md0", "irda_md1", "stereo_loopback", "ncf_bus_on",
+ "audio_pwr_on", "light_pwr_on", "lcd16data", "lcd_pwr_on",
+ "rs232_on", "nred_led", "ngreen_led", "vib_on",
+ "com_dtr", "com_rts", "radio_wake_mod", "i2c_enab",
+ "tvir_enab", "qmute", "radio_pwr_on", "spkr_off",
+ "rs232_valid", "com_dcd", "com_cts", "com_dsr",
+ "radio_cts", "radio_dsr", "radio_dcd", "radio_ri",
+};
+/* The old deprecated interface */
void ASSABET_BCR_frob(unsigned int mask, unsigned int val)
{
- unsigned long flags;
+ unsigned long m = mask, v = val;
- local_irq_save(flags);
- BCR_value = (BCR_value & ~mask) | val;
- ASSABET_BCR = BCR_value;
- local_irq_restore(flags);
+ assabet_bcr_gc->set_multiple(assabet_bcr_gc, &m, &v);
}
-
EXPORT_SYMBOL(ASSABET_BCR_frob);
+static void __init assabet_init_gpio(void __iomem *reg, u32 def_val)
+{
+ struct gpio_chip *gc;
+
+ writel_relaxed(def_val, reg);
+
+ gc = gpio_reg_init(NULL, reg, -1, 32, "assabet", 0xff000000, def_val,
+ assabet_names, NULL, NULL);
+
+ if (IS_ERR(gc))
+ return;
+
+ assabet_bcr_gc = gc;
+}
+
/*
* The codec reset goes to three devices, so we need to release
* the rest when any one of these requests it. However, that
@@ -146,7 +170,7 @@ static void adv7171_write(unsigned reg, unsigned val)
unsigned gpdr = GPDR;
unsigned gplr = GPLR;
- ASSABET_BCR = BCR_value | ASSABET_BCR_AUDIO_ON;
+ ASSABET_BCR_frob(ASSABET_BCR_AUDIO_ON, ASSABET_BCR_AUDIO_ON);
udelay(100);
GPCR = SDA | SCK | MOD; /* clear L3 mode to ensure UDA1341 doesn't respond */
@@ -273,38 +297,6 @@ static struct resource assabet_flash_resources[] = {
};
-/*
- * Assabet IrDA support code.
- */
-
-static int assabet_irda_set_power(struct device *dev, unsigned int state)
-{
- static unsigned int bcr_state[4] = {
- ASSABET_BCR_IRDA_MD0,
- ASSABET_BCR_IRDA_MD1|ASSABET_BCR_IRDA_MD0,
- ASSABET_BCR_IRDA_MD1,
- 0
- };
-
- if (state < 4)
- ASSABET_BCR_frob(ASSABET_BCR_IRDA_MD1 | ASSABET_BCR_IRDA_MD0,
- bcr_state[state]);
- return 0;
-}
-
-static void assabet_irda_set_speed(struct device *dev, unsigned int speed)
-{
- if (speed < 4000000)
- ASSABET_BCR_clear(ASSABET_BCR_IRDA_FSEL);
- else
- ASSABET_BCR_set(ASSABET_BCR_IRDA_FSEL);
-}
-
-static struct irda_platform_data assabet_irda_data = {
- .set_power = assabet_irda_set_power,
- .set_speed = assabet_irda_set_speed,
-};
-
static struct ucb1x00_plat_data assabet_ucb1x00_data = {
.reset = assabet_ucb1x00_reset,
.gpio_base = -1,
@@ -419,6 +411,109 @@ static struct resource neponset_resources[] = {
};
#endif
+static struct gpiod_lookup_table assabet_cf_gpio_table = {
+ .dev_id = "sa11x0-pcmcia.1",
+ .table = {
+ GPIO_LOOKUP("gpio", 21, "ready", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("gpio", 22, "detect", GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP("gpio", 24, "bvd2", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("gpio", 25, "bvd1", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("assabet", 1, "reset", GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP("assabet", 7, "bus-enable", GPIO_ACTIVE_LOW),
+ { },
+ },
+};
+
+static struct regulator_consumer_supply assabet_cf_vcc_consumers[] = {
+ REGULATOR_SUPPLY("vcc", "sa11x0-pcmcia.1"),
+};
+
+static struct fixed_voltage_config assabet_cf_vcc_pdata __initdata = {
+ .supply_name = "cf-power",
+ .microvolts = 3300000,
+};
+
+static struct gpiod_lookup_table assabet_cf_vcc_gpio_table = {
+ .dev_id = "reg-fixed-voltage.0",
+ .table = {
+ GPIO_LOOKUP("assabet", 0, NULL, GPIO_ACTIVE_HIGH),
+ { },
+ },
+};
+
+static struct gpiod_lookup_table assabet_leds_gpio_table = {
+ .dev_id = "leds-gpio",
+ .table = {
+ GPIO_LOOKUP("assabet", 13, NULL, GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP("assabet", 14, NULL, GPIO_ACTIVE_LOW),
+ { },
+ },
+};
+
+static struct gpio_led assabet_leds[] __initdata = {
+ {
+ .name = "assabet:red",
+ .default_trigger = "cpu0",
+ .default_state = LEDS_GPIO_DEFSTATE_KEEP,
+ }, {
+ .name = "assabet:green",
+ .default_trigger = "heartbeat",
+ .default_state = LEDS_GPIO_DEFSTATE_KEEP,
+ },
+};
+
+static const struct gpio_led_platform_data assabet_leds_pdata __initconst = {
+ .num_leds = ARRAY_SIZE(assabet_leds),
+ .leds = assabet_leds,
+};
+
+static struct gpio_keys_button assabet_keys_buttons[] = {
+ {
+ .gpio = 0,
+ .irq = IRQ_GPIO0,
+ .desc = "gpio0",
+ .wakeup = 1,
+ .can_disable = 1,
+ .debounce_interval = 5,
+ }, {
+ .gpio = 1,
+ .irq = IRQ_GPIO1,
+ .desc = "gpio1",
+ .wakeup = 1,
+ .can_disable = 1,
+ .debounce_interval = 5,
+ },
+};
+
+static const struct gpio_keys_platform_data assabet_keys_pdata = {
+ .buttons = assabet_keys_buttons,
+ .nbuttons = ARRAY_SIZE(assabet_keys_buttons),
+ .rep = 0,
+};
+
+static struct gpiod_lookup_table assabet_uart1_gpio_table = {
+ .dev_id = "sa11x0-uart.1",
+ .table = {
+ GPIO_LOOKUP("assabet", 16, "dtr", GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP("assabet", 17, "rts", GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP("assabet", 25, "dcd", GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP("assabet", 26, "cts", GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP("assabet", 27, "dsr", GPIO_ACTIVE_LOW),
+ { },
+ },
+};
+
+static struct gpiod_lookup_table assabet_uart3_gpio_table = {
+ .dev_id = "sa11x0-uart.3",
+ .table = {
+ GPIO_LOOKUP("assabet", 28, "cts", GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP("assabet", 29, "dsr", GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP("assabet", 30, "dcd", GPIO_ACTIVE_LOW),
+ GPIO_LOOKUP("assabet", 31, "rng", GPIO_ACTIVE_LOW),
+ { },
+ },
+};
+
static void __init assabet_init(void)
{
/*
@@ -457,14 +552,6 @@ static void __init assabet_init(void)
sa11x0_ppc_configure_mcp();
if (machine_has_neponset()) {
- /*
- * Angel sets this, but other bootloaders may not.
- *
- * This must precede any driver calls to BCR_set()
- * or BCR_clear().
- */
- ASSABET_BCR = BCR_value = ASSABET_BCR_DB1111;
-
#ifndef CONFIG_ASSABET_NEPONSET
printk( "Warning: Neponset detected but full support "
"hasn't been configured in the kernel\n" );
@@ -472,8 +559,26 @@ static void __init assabet_init(void)
platform_device_register_simple("neponset", 0,
neponset_resources, ARRAY_SIZE(neponset_resources));
#endif
+ } else {
+ gpiod_add_lookup_table(&assabet_uart1_gpio_table);
+ gpiod_add_lookup_table(&assabet_uart3_gpio_table);
+ gpiod_add_lookup_table(&assabet_cf_vcc_gpio_table);
+
+ sa11x0_register_fixed_regulator(0, &assabet_cf_vcc_pdata,
+ assabet_cf_vcc_consumers,
+ ARRAY_SIZE(assabet_cf_vcc_consumers),
+ true);
+
}
+ platform_device_register_resndata(NULL, "gpio-keys", 0,
+ NULL, 0,
+ &assabet_keys_pdata,
+ sizeof(assabet_keys_pdata));
+
+ gpiod_add_lookup_table(&assabet_leds_gpio_table);
+ gpio_led_register_device(-1, &assabet_leds_pdata);
+
#ifndef ASSABET_PAL_VIDEO
sa11x0_register_lcd(&lq039q2ds54_info);
#else
@@ -481,8 +586,10 @@ static void __init assabet_init(void)
#endif
sa11x0_register_mtd(&assabet_flash_data, assabet_flash_resources,
ARRAY_SIZE(assabet_flash_resources));
- sa11x0_register_irda(&assabet_irda_data);
sa11x0_register_mcp(&assabet_mcp_data);
+
+ if (!machine_has_neponset())
+ sa11x0_register_pcmcia(1, &assabet_cf_gpio_table);
}
/*
@@ -498,7 +605,7 @@ static void __init map_sa1100_gpio_regs( void )
int prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO);
pmd_t *pmd;
- pmd = pmd_offset(pud_offset(pgd_offset_k(virt), virt), virt);
+ pmd = pmd_off_k(virt);
*pmd = __pmd(phys | prot);
flush_pmd_entry(pmd);
}
@@ -518,7 +625,7 @@ static void __init map_sa1100_gpio_regs( void )
*/
static void __init get_assabet_scr(void)
{
- unsigned long uninitialized_var(scr), i;
+ unsigned long scr, i;
GPDR |= 0x3fc; /* Configure GPIO 9:2 as outputs */
GPSR = 0x3fc; /* Write 0xFF to GPIO 9:2 */
@@ -546,74 +653,13 @@ static void assabet_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
{
if (port->mapbase == _Ser1UTCR0) {
if (state)
- ASSABET_BCR_clear(ASSABET_BCR_RS232EN |
- ASSABET_BCR_COM_RTS |
- ASSABET_BCR_COM_DTR);
- else
- ASSABET_BCR_set(ASSABET_BCR_RS232EN |
- ASSABET_BCR_COM_RTS |
- ASSABET_BCR_COM_DTR);
- }
-}
-
-/*
- * Assabet uses COM_RTS and COM_DTR for both UART1 (com port)
- * and UART3 (radio module). We only handle them for UART1 here.
- */
-static void assabet_set_mctrl(struct uart_port *port, u_int mctrl)
-{
- if (port->mapbase == _Ser1UTCR0) {
- u_int set = 0, clear = 0;
-
- if (mctrl & TIOCM_RTS)
- clear |= ASSABET_BCR_COM_RTS;
+ ASSABET_BCR_clear(ASSABET_BCR_RS232EN);
else
- set |= ASSABET_BCR_COM_RTS;
-
- if (mctrl & TIOCM_DTR)
- clear |= ASSABET_BCR_COM_DTR;
- else
- set |= ASSABET_BCR_COM_DTR;
-
- ASSABET_BCR_clear(clear);
- ASSABET_BCR_set(set);
+ ASSABET_BCR_set(ASSABET_BCR_RS232EN);
}
}
-static u_int assabet_get_mctrl(struct uart_port *port)
-{
- u_int ret = 0;
- u_int bsr = ASSABET_BSR;
-
- /* need 2 reads to read current value */
- bsr = ASSABET_BSR;
-
- if (port->mapbase == _Ser1UTCR0) {
- if (bsr & ASSABET_BSR_COM_DCD)
- ret |= TIOCM_CD;
- if (bsr & ASSABET_BSR_COM_CTS)
- ret |= TIOCM_CTS;
- if (bsr & ASSABET_BSR_COM_DSR)
- ret |= TIOCM_DSR;
- } else if (port->mapbase == _Ser3UTCR0) {
- if (bsr & ASSABET_BSR_RAD_DCD)
- ret |= TIOCM_CD;
- if (bsr & ASSABET_BSR_RAD_CTS)
- ret |= TIOCM_CTS;
- if (bsr & ASSABET_BSR_RAD_DSR)
- ret |= TIOCM_DSR;
- if (bsr & ASSABET_BSR_RAD_RI)
- ret |= TIOCM_RI;
- } else {
- ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
- }
-
- return ret;
-}
-
static struct sa1100_port_fns assabet_port_fns __initdata = {
- .set_mctrl = assabet_set_mctrl,
- .get_mctrl = assabet_get_mctrl,
.pm = assabet_uart_pm,
};
@@ -664,96 +710,31 @@ static void __init assabet_map_io(void)
sa1100_register_uart(2, 3);
}
-/* LEDs */
-#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
-struct assabet_led {
- struct led_classdev cdev;
- u32 mask;
-};
-
-/*
- * The triggers lines up below will only be used if the
- * LED triggers are compiled in.
- */
-static const struct {
- const char *name;
- const char *trigger;
-} assabet_leds[] = {
- { "assabet:red", "cpu0",},
- { "assabet:green", "heartbeat", },
-};
-
-/*
- * The LED control in Assabet is reversed:
- * - setting bit means turn off LED
- * - clearing bit means turn on LED
- */
-static void assabet_led_set(struct led_classdev *cdev,
- enum led_brightness b)
-{
- struct assabet_led *led = container_of(cdev,
- struct assabet_led, cdev);
-
- if (b != LED_OFF)
- ASSABET_BCR_clear(led->mask);
- else
- ASSABET_BCR_set(led->mask);
-}
-
-static enum led_brightness assabet_led_get(struct led_classdev *cdev)
+static void __init assabet_init_irq(void)
{
- struct assabet_led *led = container_of(cdev,
- struct assabet_led, cdev);
-
- return (ASSABET_BCR & led->mask) ? LED_OFF : LED_FULL;
-}
-
-static int __init assabet_leds_init(void)
-{
- int i;
-
- if (!machine_is_assabet())
- return -ENODEV;
-
- for (i = 0; i < ARRAY_SIZE(assabet_leds); i++) {
- struct assabet_led *led;
+ u32 def_val;
- led = kzalloc(sizeof(*led), GFP_KERNEL);
- if (!led)
- break;
+ sa1100_init_irq();
- led->cdev.name = assabet_leds[i].name;
- led->cdev.brightness_set = assabet_led_set;
- led->cdev.brightness_get = assabet_led_get;
- led->cdev.default_trigger = assabet_leds[i].trigger;
-
- if (!i)
- led->mask = ASSABET_BCR_LED_RED;
- else
- led->mask = ASSABET_BCR_LED_GREEN;
-
- if (led_classdev_register(NULL, &led->cdev) < 0) {
- kfree(led);
- break;
- }
- }
+ if (machine_has_neponset())
+ def_val = ASSABET_BCR_DB1111;
+ else
+ def_val = ASSABET_BCR_DB1110;
- return 0;
+ /*
+ * Angel sets this, but other bootloaders may not.
+ *
+ * This must precede any driver calls to BCR_set() or BCR_clear().
+ */
+ assabet_init_gpio((void *)&ASSABET_BCR, def_val);
}
-/*
- * Since we may have triggers on any subsystem, defer registration
- * until after subsystem_init.
- */
-fs_initcall(assabet_leds_init);
-#endif
-
MACHINE_START(ASSABET, "Intel-Assabet")
.atag_offset = 0x100,
.fixup = fixup_assabet,
.map_io = assabet_map_io,
.nr_irqs = SA1100_NR_IRQS,
- .init_irq = sa1100_init_irq,
+ .init_irq = assabet_init_irq,
.init_time = sa1100_timer_init,
.init_machine = assabet_init,
.init_late = sa11x0_init_late,