aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/processor_throttling.c10
-rw-r--r--drivers/ata/sata_mv.c31
-rw-r--r--drivers/base/cpu.c48
-rw-r--r--drivers/base/node.c29
-rw-r--r--drivers/base/topology.c41
-rw-r--r--drivers/firmware/dcdbas.c4
-rw-r--r--drivers/i2c/busses/Kconfig2
-rw-r--r--drivers/i2c/busses/i2c-pxa.c1
-rw-r--r--drivers/i2c/chips/Kconfig1
-rw-r--r--drivers/i2c/chips/tps65010.c101
-rw-r--r--drivers/input/keyboard/Kconfig9
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/corgikbd.c1
-rw-r--r--drivers/input/keyboard/sh_keysc.c280
-rw-r--r--drivers/input/keyboard/spitzkbd.c1
-rw-r--r--drivers/input/touchscreen/ads7846.c40
-rw-r--r--drivers/input/touchscreen/corgi_ts.c1
-rw-r--r--drivers/leds/Kconfig7
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-tosa.c132
-rw-r--r--drivers/mfd/Kconfig16
-rw-r--r--drivers/mfd/Makefile3
-rw-r--r--drivers/mfd/htc-egpio.c440
-rw-r--r--drivers/mfd/htc-pasic3.c265
-rw-r--r--drivers/mtd/nand/Kconfig2
-rw-r--r--drivers/mtd/nand/orion_nand.c2
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/net/arm/at91_ether.c4
-rw-r--r--drivers/net/irda/pxaficp_ir.c11
-rw-r--r--drivers/pci/pci-driver.c9
-rw-r--r--drivers/pci/pci-sysfs.c20
-rw-r--r--drivers/pci/probe.c27
-rw-r--r--drivers/pcmcia/Kconfig1
-rw-r--r--drivers/pcmcia/pxa2xx_cm_x270.c1
-rw-r--r--drivers/rtc/rtc-sh.c296
-rw-r--r--drivers/serial/imx.c111
-rw-r--r--drivers/serial/sh-sci.c7
-rw-r--r--drivers/serial/sh-sci.h60
-rw-r--r--drivers/usb/host/ehci-hcd.c2
-rw-r--r--drivers/usb/host/ehci-orion.c37
-rw-r--r--drivers/video/pxafb.c1
41 files changed, 1655 insertions, 403 deletions
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 1b8e592a824..0bba3a914e8 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -838,10 +838,10 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr)
* Migrate task to the cpu pointed by pr.
*/
saved_mask = current->cpus_allowed;
- set_cpus_allowed(current, cpumask_of_cpu(pr->id));
+ set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id));
ret = pr->throttling.acpi_processor_get_throttling(pr);
/* restore the previous state */
- set_cpus_allowed(current, saved_mask);
+ set_cpus_allowed_ptr(current, &saved_mask);
return ret;
}
@@ -1025,7 +1025,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* it can be called only for the cpu pointed by pr.
*/
if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
- set_cpus_allowed(current, cpumask_of_cpu(pr->id));
+ set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id));
ret = p_throttling->acpi_processor_set_throttling(pr,
t_state.target_state);
} else {
@@ -1056,7 +1056,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
continue;
}
t_state.cpu = i;
- set_cpus_allowed(current, cpumask_of_cpu(i));
+ set_cpus_allowed_ptr(current, &cpumask_of_cpu(i));
ret = match_pr->throttling.
acpi_processor_set_throttling(
match_pr, t_state.target_state);
@@ -1074,7 +1074,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
&t_state);
}
/* restore the previous state */
- set_cpus_allowed(current, saved_mask);
+ set_cpus_allowed_ptr(current, &saved_mask);
return ret;
}
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 05ff8c77649..d52ce118832 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -76,6 +76,7 @@
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/ata_platform.h>
+#include <linux/mbus.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
@@ -370,6 +371,9 @@ enum {
#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
#define HAS_PCI(host) (!((host)->ports[0]->flags & MV_FLAG_SOC))
+#define WINDOW_CTRL(i) (0x20030 + ((i) << 4))
+#define WINDOW_BASE(i) (0x20034 + ((i) << 4))
+
enum {
/* DMA boundary 0xffff is required by the s/g splitting
* we need on /length/ in mv_fill-sg().
@@ -2769,6 +2773,27 @@ static int mv_create_dma_pools(struct mv_host_priv *hpriv, struct device *dev)
return 0;
}
+static void mv_conf_mbus_windows(struct mv_host_priv *hpriv,
+ struct mbus_dram_target_info *dram)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ writel(0, hpriv->base + WINDOW_CTRL(i));
+ writel(0, hpriv->base + WINDOW_BASE(i));
+ }
+
+ for (i = 0; i < dram->num_cs; i++) {
+ struct mbus_dram_window *cs = dram->cs + i;
+
+ writel(((cs->size - 1) & 0xffff0000) |
+ (cs->mbus_attr << 8) |
+ (dram->mbus_dram_target_id << 4) | 1,
+ hpriv->base + WINDOW_CTRL(i));
+ writel(cs->base, hpriv->base + WINDOW_BASE(i));
+ }
+}
+
/**
* mv_platform_probe - handle a positive probe of an soc Marvell
* host
@@ -2823,6 +2848,12 @@ static int mv_platform_probe(struct platform_device *pdev)
res->end - res->start + 1);
hpriv->base -= MV_SATAHC0_REG_BASE;
+ /*
+ * (Re-)program MBUS remapping windows if we are asked to.
+ */
+ if (mv_platform_data->dram != NULL)
+ mv_conf_mbus_windows(hpriv, mv_platform_data->dram);
+
rc = mv_create_dma_pools(hpriv, &pdev->dev);
if (rc)
return rc;
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 499b003f927..2c76afff3b1 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -103,6 +103,51 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL);
#endif
/*
+ * Print cpu online, possible, present, and system maps
+ */
+static ssize_t print_cpus_map(char *buf, cpumask_t *map)
+{
+ int n = cpulist_scnprintf(buf, PAGE_SIZE-2, *map);
+
+ buf[n++] = '\n';
+ buf[n] = '\0';
+ return n;
+}
+
+#define print_cpus_func(type) \
+static ssize_t print_cpus_##type(struct sysdev_class *class, char *buf) \
+{ \
+ return print_cpus_map(buf, &cpu_##type##_map); \
+} \
+struct sysdev_class_attribute attr_##type##_map = \
+ _SYSDEV_CLASS_ATTR(type, 0444, print_cpus_##type, NULL)
+
+print_cpus_func(online);
+print_cpus_func(possible);
+print_cpus_func(present);
+
+struct sysdev_class_attribute *cpu_state_attr[] = {
+ &attr_online_map,
+ &attr_possible_map,
+ &attr_present_map,
+};
+
+static int cpu_states_init(void)
+{
+ int i;
+ int err = 0;
+
+ for (i = 0; i < ARRAY_SIZE(cpu_state_attr); i++) {
+ int ret;
+ ret = sysdev_class_create_file(&cpu_sysdev_class,
+ cpu_state_attr[i]);
+ if (!err)
+ err = ret;
+ }
+ return err;
+}
+
+/*
* register_cpu - Setup a sysfs device for a CPU.
* @cpu - cpu->hotpluggable field set to 1 will generate a control file in
* sysfs for this CPU.
@@ -147,6 +192,9 @@ int __init cpu_dev_init(void)
int err;
err = sysdev_class_register(&cpu_sysdev_class);
+ if (!err)
+ err = cpu_states_init();
+
#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
if (!err)
err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class);
diff --git a/drivers/base/node.c b/drivers/base/node.c
index e59861f18ce..12fde2d03d6 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -19,21 +19,34 @@ static struct sysdev_class node_class = {
};
-static ssize_t node_read_cpumap(struct sys_device * dev, char * buf)
+static ssize_t node_read_cpumap(struct sys_device *dev, int type, char *buf)
{
struct node *node_dev = to_node(dev);
- cpumask_t mask = node_to_cpumask(node_dev->sysdev.id);
+ node_to_cpumask_ptr(mask, node_dev->sysdev.id);
int len;
- /* 2004/06/03: buf currently PAGE_SIZE, need > 1 char per 4 bits. */
- BUILD_BUG_ON(MAX_NUMNODES/4 > PAGE_SIZE/2);
+ /* 2008/04/07: buf currently PAGE_SIZE, need 9 chars per 32 bits. */
+ BUILD_BUG_ON((NR_CPUS/32 * 9) > (PAGE_SIZE-1));
- len = cpumask_scnprintf(buf, PAGE_SIZE-1, mask);
- len += sprintf(buf + len, "\n");
+ len = type?
+ cpulist_scnprintf(buf, PAGE_SIZE-2, *mask):
+ cpumask_scnprintf(buf, PAGE_SIZE-2, *mask);
+ buf[len++] = '\n';
+ buf[len] = '\0';
return len;
}
-static SYSDEV_ATTR(cpumap, S_IRUGO, node_read_cpumap, NULL);
+static inline ssize_t node_read_cpumask(struct sys_device *dev, char *buf)
+{
+ return node_read_cpumap(dev, 0, buf);
+}
+static inline ssize_t node_read_cpulist(struct sys_device *dev, char *buf)
+{
+ return node_read_cpumap(dev, 1, buf);
+}
+
+static SYSDEV_ATTR(cpumap, S_IRUGO, node_read_cpumask, NULL);
+static SYSDEV_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL);
#define K(x) ((x) << (PAGE_SHIFT - 10))
static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
@@ -149,6 +162,7 @@ int register_node(struct node *node, int num, struct node *parent)
if (!error){
sysdev_create_file(&node->sysdev, &attr_cpumap);
+ sysdev_create_file(&node->sysdev, &attr_cpulist);
sysdev_create_file(&node->sysdev, &attr_meminfo);
sysdev_create_file(&node->sysdev, &attr_numastat);
sysdev_create_file(&node->sysdev, &attr_distance);
@@ -166,6 +180,7 @@ int register_node(struct node *node, int num, struct node *parent)
void unregister_node(struct node *node)
{
sysdev_remove_file(&node->sysdev, &attr_cpumap);
+ sysdev_remove_file(&node->sysdev, &attr_cpulist);
sysdev_remove_file(&node->sysdev, &attr_meminfo);
sysdev_remove_file(&node->sysdev, &attr_numastat);
sysdev_remove_file(&node->sysdev, &attr_distance);
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index e1d3ad4db2f..fdf4044d2e7 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -40,15 +40,38 @@ static ssize_t show_##name(struct sys_device *dev, char *buf) \
return sprintf(buf, "%d\n", topology_##name(cpu)); \
}
-#define define_siblings_show_func(name) \
-static ssize_t show_##name(struct sys_device *dev, char *buf) \
+static ssize_t show_cpumap(int type, cpumask_t *mask, char *buf)
+{
+ ptrdiff_t len = PTR_ALIGN(buf + PAGE_SIZE - 1, PAGE_SIZE) - buf;
+ int n = 0;
+
+ if (len > 1) {
+ n = type?
+ cpulist_scnprintf(buf, len-2, *mask):
+ cpumask_scnprintf(buf, len-2, *mask);
+ buf[n++] = '\n';
+ buf[n] = '\0';
+ }
+ return n;
+}
+
+#define define_siblings_show_map(name) \
+static inline ssize_t show_##name(struct sys_device *dev, char *buf) \
{ \
- ssize_t len = -1; \
unsigned int cpu = dev->id; \
- len = cpumask_scnprintf(buf, NR_CPUS+1, topology_##name(cpu)); \
- return (len + sprintf(buf + len, "\n")); \
+ return show_cpumap(0, &(topology_##name(cpu)), buf); \
}
+#define define_siblings_show_list(name) \
+static inline ssize_t show_##name##_list(struct sys_device *dev, char *buf) \
+{ \
+ unsigned int cpu = dev->id; \
+ return show_cpumap(1, &(topology_##name(cpu)), buf); \
+}
+
+#define define_siblings_show_func(name) \
+ define_siblings_show_map(name); define_siblings_show_list(name)
+
#ifdef topology_physical_package_id
define_id_show_func(physical_package_id);
define_one_ro(physical_package_id);
@@ -68,7 +91,9 @@ define_one_ro(core_id);
#ifdef topology_thread_siblings
define_siblings_show_func(thread_siblings);
define_one_ro(thread_siblings);
-#define ref_thread_siblings_attr &attr_thread_siblings.attr,
+define_one_ro(thread_siblings_list);
+#define ref_thread_siblings_attr \
+ &attr_thread_siblings.attr, &attr_thread_siblings_list.attr,
#else
#define ref_thread_siblings_attr
#endif
@@ -76,7 +101,9 @@ define_one_ro(thread_siblings);
#ifdef topology_core_siblings
define_siblings_show_func(core_siblings);
define_one_ro(core_siblings);
-#define ref_core_siblings_attr &attr_core_siblings.attr,
+define_one_ro(core_siblings_list);
+#define ref_core_siblings_attr \
+ &attr_core_siblings.attr, &attr_core_siblings_list.attr,
#else
#define ref_core_siblings_attr
#endif
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
index d8822eedba6..f235940719e 100644
--- a/drivers/firmware/dcdbas.c
+++ b/drivers/firmware/dcdbas.c
@@ -264,7 +264,7 @@ static int smi_request(struct smi_cmd *smi_cmd)
/* SMI requires CPU 0 */
old_mask = current->cpus_allowed;
- set_cpus_allowed(current, cpumask_of_cpu(0));
+ set_cpus_allowed_ptr(current, &cpumask_of_cpu(0));
if (smp_processor_id() != 0) {
dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n",
__FUNCTION__);
@@ -284,7 +284,7 @@ static int smi_request(struct smi_cmd *smi_cmd)
);
out:
- set_cpus_allowed(current, old_mask);
+ set_cpus_allowed_ptr(current, &old_mask);
return ret;
}
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 5fa9c3c67e0..b04c99580d0 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -645,7 +645,7 @@ config I2C_PCA_ISA
config I2C_MV64XXX
tristate "Marvell mv64xxx I2C Controller"
- depends on (MV64X60 || ARCH_ORION) && EXPERIMENTAL
+ depends on (MV64X60 || PLAT_ORION) && EXPERIMENTAL
help
If you say yes to this option, support will be included for the
built-in I2C interface on the Marvell 64xxx line of host bridges.
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 2d2087ad708..6fd2d6a84ef 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -39,6 +39,7 @@
#include <asm/io.h>
#include <asm/arch/i2c.h>
#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
struct pxa_i2c {
spinlock_t lock;
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index b21593f9358..2da2edfa68e 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -93,6 +93,7 @@ config ISP1301_OMAP
config TPS65010
tristate "TPS6501x Power Management chips"
+ depends on HAVE_GPIO_LIB
default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
help
If you say yes here you get support for the TPS6501x series of
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
index 4154a910885..b67f69c2e7f 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/i2c/chips/tps65010.c
@@ -30,9 +30,13 @@
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/mutex.h>
+#include <linux/platform_device.h>
#include <linux/i2c/tps65010.h>
+#include <asm/gpio.h>
+
+
/*-------------------------------------------------------------------------*/
#define DRIVER_VERSION "2 May 2005"
@@ -84,7 +88,9 @@ struct tps65010 {
u8 chgstatus, regstatus, chgconf;
u8 nmask1, nmask2;
- /* not currently tracking GPIO state */
+ u8 outmask;
+ struct gpio_chip chip;
+ struct platform_device *leds;
};
#define POWER_POLL_DELAY msecs_to_jiffies(5000)
@@ -449,12 +455,72 @@ static irqreturn_t tps65010_irq(int irq, void *_tps)
/*-------------------------------------------------------------------------*/
+/* offsets 0..3 == GPIO1..GPIO4
+ * offsets 4..5 == LED1/nPG, LED2 (we set one of the non-BLINK modes)
+ */
+static void
+tps65010_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ if (offset < 4)
+ tps65010_set_gpio_out_value(offset + 1, value);
+ else
+ tps65010_set_led(offset - 3, value ? ON : OFF);
+}
+
+static int
+tps65010_output(struct gpio_chip *chip, unsigned offset, int value)
+{
+ /* GPIOs may be input-only */
+ if (offset < 4) {
+ struct tps65010 *tps;
+
+ tps = container_of(chip, struct tps65010, chip);
+ if (!(tps->outmask & (1 << offset)))
+ return -EINVAL;
+ tps65010_set_gpio_out_value(offset + 1, value);
+ } else
+ tps65010_set_led(offset - 3, value ? ON : OFF);
+
+ return 0;
+}
+
+static int tps65010_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ int value;
+ struct tps65010 *tps;
+
+ tps = container_of(chip, struct tps65010, chip);
+
+ if (offset < 4) {
+ value = i2c_smbus_read_byte_data(tps->client, TPS_DEFGPIO);
+ if (value < 0)
+ return 0;
+ if (value & (1 << (offset + 4))) /* output */
+ return !(value & (1 << offset));
+ else /* input */
+ return (value & (1 << offset));
+ }
+
+ /* REVISIT we *could* report LED1/nPG and LED2 state ... */
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
static struct tps65010 *the_tps;
static int __exit tps65010_remove(struct i2c_client *client)
{
struct tps65010 *tps = i2c_get_clientdata(client);
+ struct tps65010_board *board = client->dev.platform_data;
+ if (board && board->teardown) {
+ int status = board->teardown(client, board->context);
+ if (status < 0)
+ dev_dbg(&client->dev, "board %s %s err %d\n",
+ "teardown", client->name, status);
+ }
if (client->irq > 0)
free_irq(client->irq, tps);
cancel_delayed_work(&tps->work);
@@ -469,6 +535,7 @@ static int tps65010_probe(struct i2c_client *client)
{
struct tps65010 *tps;
int status;
+ struct tps65010_board *board = client->dev.platform_data;
if (the_tps) {
dev_dbg(&client->dev, "only one tps6501x chip allowed\n");
@@ -577,6 +644,38 @@ static int tps65010_probe(struct i2c_client *client)
tps->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, NULL,
tps, DEBUG_FOPS);
+
+ /* optionally register GPIOs */
+ if (board && board->base > 0) {
+ tps->outmask = board->outmask;
+
+ tps->chip.label = client->name;
+
+ tps->chip.set = tps65010_gpio_set;
+ tps->chip.direction_output = tps65010_output;
+
+ /* NOTE: only partial support for inputs; nyet IRQs */
+ tps->chip.get = tps65010_gpio_get;
+
+ tps->chip.base = board->base;
+ tps->chip.ngpio = 6;
+ tps->chip.can_sleep = 1;
+
+ status = gpiochip_add(&tps->chip);
+ if (status < 0)
+ dev_err(&client->dev, "can't add gpiochip, err %d\n",
+ status);
+ else if (board->setup) {
+ status = board->setup(client, board->context);
+ if (status < 0) {
+ dev_dbg(&client->dev,
+ "board %s %s err %d\n",
+ "setup", client->name, status);
+ status = 0;
+ }
+ }
+ }
+
return 0;
fail1:
kfree(tps);
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 8ea709be330..efd70a97459 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -314,4 +314,13 @@ config KEYBOARD_BFIN
To compile this driver as a module, choose M here: the
module will be called bf54x-keys.
+config KEYBOARD_SH_KEYSC
+ tristate "SuperH KEYSC keypad support"
+ depends on SUPERH
+ help
+ Say Y here if you want to use a keypad attached to the KEYSC block
+ on SuperH processors such as sh7722 and sh7343.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sh_keysc.
endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index e741f403101..0edc8f285d1 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -26,3 +26,4 @@ obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o
obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o
obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o
obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
+obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index 790fed368aa..5d6cc7f1dc9 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -23,6 +23,7 @@
#include <asm/arch/corgi.h>
#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
#include <asm/hardware/scoop.h>
#define KB_ROWS 8
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c
new file mode 100644
index 00000000000..8486abc457e
--- /dev/null
+++ b/drivers/input/keyboard/sh_keysc.c
@@ -0,0 +1,280 @@
+/*
+ * SuperH KEYSC Keypad Driver
+ *
+ * Copyright (C) 2008 Magnus Damm
+ *
+ * Based on gpio_keys.c, Copyright 2005 Phil Blundell
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <asm/sh_keysc.h>
+
+#define KYCR1_OFFS 0x00
+#define KYCR2_OFFS 0x04
+#define KYINDR_OFFS 0x08
+#define KYOUTDR_OFFS 0x0c
+
+#define KYCR2_IRQ_LEVEL 0x10
+#define KYCR2_IRQ_DISABLED 0x00
+
+static const struct {
+ unsigned char kymd, keyout, keyin;
+} sh_keysc_mode[] = {
+ [SH_KEYSC_MODE_1] = { 0, 6, 5 },
+ [SH_KEYSC_MODE_2] = { 1, 5, 6 },
+ [SH_KEYSC_MODE_3] = { 2, 4, 7 },
+};
+
+struct sh_keysc_priv {
+ void __iomem *iomem_base;
+ unsigned long last_keys;
+ struct input_dev *input;
+ struct sh_keysc_info pdata;
+};
+
+static irqreturn_t sh_keysc_isr(int irq, void *dev_id)
+{
+ struct platform_device *pdev = dev_id;
+ struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
+ struct sh_keysc_info *pdata = &priv->pdata;
+ unsigned long keys, keys1, keys0, mask;
+ unsigned char keyin_set, tmp;
+ int i, k;
+
+ dev_dbg(&pdev->dev, "isr!\n");
+
+ keys1 = ~0;
+ keys0 = 0;
+
+ do {
+ keys = 0;
+ keyin_set = 0;
+
+ iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS);
+
+ for (i = 0; i < sh_keysc_mode[pdata->mode].keyout; i++) {
+ iowrite16(0xfff ^ (3 << (i * 2)),
+ priv->iomem_base + KYOUTDR_OFFS);
+ udelay(pdata->delay);
+ tmp = ioread16(priv->iomem_base + KYINDR_OFFS);
+ keys |= tmp << (sh_keysc_mode[pdata->mode].keyin * i);
+ tmp ^= (1 << sh_keysc_mode[pdata->mode].keyin) - 1;
+ keyin_set |= tmp;
+ }
+
+ iowrite16(0, priv->iomem_base + KYOUTDR_OFFS);
+ iowrite16(KYCR2_IRQ_LEVEL | (keyin_set << 8),
+ priv->iomem_base + KYCR2_OFFS);
+
+ keys ^= ~0;
+ keys &= (1 << (sh_keysc_mode[pdata->mode].keyin *
+ sh_keysc_mode[pdata->mode].keyout)) - 1;
+ keys1 &= keys;
+ keys0 |= keys;
+
+ dev_dbg(&pdev->dev, "keys 0x%08lx\n", keys);
+
+ } while (ioread16(priv->iomem_base + KYCR2_OFFS) & 0x01);
+
+ dev_dbg(&pdev->dev, "last_keys 0x%08lx keys0 0x%08lx keys1 0x%08lx\n",
+ priv->last_keys, keys0, keys1);
+
+ for (i = 0; i < SH_KEYSC_MAXKEYS; i++) {
+ k = pdata->keycodes[i];
+ if (!k)
+ continue;
+
+ mask = 1 << i;
+
+ if (!((priv->last_keys ^ keys0) & mask))
+ continue;
+
+ if ((keys1 | keys0) & mask) {
+ input_event(priv->input, EV_KEY, k, 1);
+ priv->last_keys |= mask;
+ }
+
+ if (!(keys1 & mask)) {
+ input_event(priv->input, EV_KEY, k, 0);
+ priv->last_keys &= ~mask;
+ }
+
+ }
+ input_sync(priv->input);
+
+ return IRQ_HANDLED;
+}
+
+#define res_size(res) ((res)->end - (res)->start + 1)
+
+static int __devinit sh_keysc_probe(struct platform_device *pdev)
+{
+ struct sh_keysc_priv *priv;
+ struct sh_keysc_info *pdata;
+ struct resource *res;
+ struct input_dev *input;
+ int i, k;
+ int irq, error;
+
+ if (!pdev->dev.platform_data) {
+ dev_err(&pdev->dev, "no platform data defined\n");
+ error = -EINVAL;
+ goto err0;
+ }
+
+ error = -ENXIO;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "failed to get I/O memory\n");
+ goto err0;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "failed to get irq\n");
+ goto err0;
+ }
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (priv == NULL) {
+ dev_err(&pdev->dev, "failed to allocate driver data\n");
+ error = -ENOMEM;
+ goto err0;
+ }
+
+ platform_set_drvdata(pdev, priv);
+ memcpy(&priv->pdata, pdev->dev.platform_data, sizeof(priv->pdata));
+ pdata = &priv->pdata;
+
+ res = request_mem_region(res->start, res_size(res), pdev->name);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "failed to request I/O memory\n");
+ error = -EBUSY;
+ goto err1;
+ }
+
+ priv->iomem_base = ioremap_nocache(res->start, res_size(res));
+ if (priv->iomem_base == NULL) {
+ dev_err(&pdev->dev, "failed to remap I/O memory\n");
+ error = -ENXIO;
+ goto err2;
+ }
+
+ priv->input = input_allocate_device();
+ if (!priv->input) {
+ dev_err(&pdev->dev, "failed to allocate input device\n");
+ error = -ENOMEM;
+ goto err3;
+ }
+
+ input = priv->input;
+ input->evbit[0] = BIT_MASK(EV_KEY);
+
+ input->name = pdev->name;
+ input->phys = "sh-keysc-keys/input0";
+ input->dev.parent = &pdev->dev;
+
+ input->id.bustype = BUS_HOST;
+ input->id.vendor = 0x0001;
+ input->id.product = 0x0001;
+ input->id.version = 0x0100;
+
+ error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev);
+ if (error) {
+ dev_err(&pdev->dev, "failed to request IRQ\n");
+ goto err4;
+ }
+
+ for (i = 0; i < SH_KEYSC_MAXKEYS; i++) {
+ k = pdata->keycodes[i];
+ if (k)
+ input_set_capability(input, EV_KEY, k);
+ }
+
+ error = input_register_device(input);
+ if (error) {
+ dev_err(&pdev->dev, "failed to register input device\n");
+ goto err5;
+ }
+
+ iowrite16((sh_keysc_mode[pdata->mode].kymd << 8) |
+ pdata->scan_timing, priv->iomem_base + KYCR1_OFFS);
+ iowrite16(0, priv->iomem_base + KYOUTDR_OFFS);
+ iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS);
+ return 0;
+ err5:
+ free_irq(irq, pdev);
+ err4:
+ input_free_device(input);
+ err3:
+ iounmap(priv->iomem_base);
+ err2:
+ release_mem_region(res->start, res_size(res));
+ err1:
+ platform_set_drvdata(pdev, NULL);
+ kfree(priv);
+ err0:
+ return error;
+}
+
+static int __devexit sh_keysc_remove(struct platform_device *pdev)
+{
+ struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
+ struct resource *res;
+
+ iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS);
+
+ input_unregister_device(priv->input);
+ free_irq(platform_get_irq(pdev, 0), pdev);
+ iounmap(priv->iomem_base);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, res_size(res));
+
+ platform_set_drvdata(pdev, NULL);
+ kfree(priv);
+ return 0;
+}
+
+
+#define sh_keysc_suspend NULL
+#define sh_keysc_resume NULL
+
+struct platform_driver sh_keysc_device_driver = {
+ .probe = sh_keysc_probe,
+ .remove = __devexit_p(sh_keysc_remove),
+ .suspend = sh_keysc_suspend,
+ .resume = sh_keysc_resume,
+ .driver = {
+ .name = "sh_keysc",
+ }
+};
+
+static int __init sh_keysc_init(void)
+{
+ return platform_driver_register(&sh_keysc_device_driver);
+}
+
+static void __exit sh_keysc_exit(void)
+{
+ platform_driver_unregister(&sh_keysc_device_driver);
+}
+
+module_init(sh_keysc_init);
+module_exit(sh_keysc_exit);
+
+MODULE_AUTHOR("Magnus Damm");
+MODULE_DESCRIPTION("SuperH KEYSC Keypad Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
index 1d59a2dc3c1..0be74bfc58f 100644
--- a/drivers/input/keyboard/spitzkbd.c
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -23,6 +23,7 @@
#include <asm/arch/spitz.h>
#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
#define KB_ROWS 7
#define KB_COLS 11
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 57a1c28bf12..39573b91c8d 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -28,13 +28,6 @@
#include <linux/spi/ads7846.h>
#include <asm/irq.h>
-#ifdef CONFIG_ARM
-#include <asm/mach-types.h>
-#ifdef CONFIG_ARCH_OMAP
-#include <asm/arch/gpio.h>
-#endif
-#endif
-
/*
* This code has been heavily tested on a Nokia 770, and lightly
@@ -1174,31 +1167,6 @@ static struct spi_driver ads7846_driver = {
static int __init ads7846_init(void)
{
- /* grr, board-specific init should stay out of drivers!! */
-
-#ifdef CONFIG_ARCH_OMAP
- if (machine_is_omap_osk()) {
- /* GPIO4 = PENIRQ; GPIO6 = BUSY */
- omap_request_gpio(4);
- omap_set_gpio_direction(4, 1);
- omap_request_gpio(6);
- omap_set_gpio_direction(6, 1);
- }
- // also TI 1510 Innovator, bitbanging through FPGA
- // also Nokia 770
- // also Palm Tungsten T2
-#endif
-
- // PXA:
- // also Dell Axim X50
- // also HP iPaq H191x/H192x/H415x/H435x
- // also Intel Lubbock (additional to UCB1400; as temperature sensor)
- // also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky)
-
- // Atmel at91sam9261-EK uses ads7843
-
- // also various AMD Au1x00 devel boards
-
return spi_register_driver(&ads7846_driver);
}
module_init(ads7846_init);
@@ -1206,14 +1174,6 @@ module_init(ads7846_init);
static void __exit ads7846_exit(void)
{
spi_unregister_driver(&ads7846_driver);
-
-#ifdef CONFIG_ARCH_OMAP
- if (machine_is_omap_osk()) {
- omap_free_gpio(4);
- omap_free_gpio(6);
- }
-#endif
-
}
module_exit(ads7846_exit);
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index 99d92f5c93d..a22576779ac 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -22,6 +22,7 @@
#include <asm/arch/sharpsl.h>
#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
#define PWR_MODE_ACTIVE 0
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 859814f62cb..a3a6199639f 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -46,13 +46,6 @@ config LEDS_SPITZ
This option enables support for the LEDs on Sharp Zaurus
SL-Cxx00 series (C1000, C3000, C3100).
-config LEDS_TOSA
- tristate "LED Support for the Sharp SL-6000 series"
- depends on LEDS_CLASS && PXA_SHARPSL
- help
- This option enables support for the LEDs on Sharp Zaurus
- SL-6000 series.
-
config LEDS_S3C24XX
tristate "LED Support for Samsung S3C24XX GPIO LEDs"
depends on LEDS_CLASS && ARCH_S3C2410
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 84ced3b1a13..e54f42da21a 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -9,7 +9,6 @@ obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o
obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o
obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o
-obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o
obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o
obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
diff --git a/drivers/leds/leds-tosa.c b/drivers/leds/leds-tosa.c
deleted file mode 100644
index 7ebecc41a9b..00000000000
--- a/drivers/leds/leds-tosa.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * LED Triggers Core
- *
- * Copyright 2005 Dirk Opfer
- *
- * Author: Dirk Opfer <Dirk@Opfer-Online.de>
- * based on spitz.c
- *
- * 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/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/leds.h>
-#include <asm/hardware/scoop.h>
-#include <asm/mach-types.h>
-#include <asm/arch/hardware.h>
-#include <asm/arch/pxa-regs.h>
-#include <asm/arch/tosa.h>
-
-static void tosaled_amber_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- if (value)
- set_scoop_gpio(&tosascoop_jc_device.dev,
- TOSA_SCOOP_JC_CHRG_ERR_LED);
- else
- reset_scoop_gpio(&tosascoop_jc_device.dev,
- TOSA_SCOOP_JC_CHRG_ERR_LED);
-}
-
-static void tosaled_green_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- if (value)
- set_scoop_gpio(&tosascoop_jc_device.dev,
- TOSA_SCOOP_JC_NOTE_LED);
- else
- reset_scoop_gpio(&tosascoop_jc_device.dev,
- TOSA_SCOOP_JC_NOTE_LED);
-}
-
-static struct led_classdev tosa_amber_led = {
- .name = "tosa:amber:charge",
- .default_trigger = "sharpsl-charge",
- .brightness_set = tosaled_amber_set,
-};
-
-static struct led_classdev tosa_green_led = {
- .name = "tosa:green:mail",
- .default_trigger = "nand-disk",
- .brightness_set = tosaled_green_set,
-};
-
-#ifdef CONFIG_PM
-static int tosaled_suspend(struct platform_device *dev, pm_message_t state)
-{
-#ifdef CONFIG_LEDS_TRIGGERS
- if (tosa_amber_led.trigger && strcmp(tosa_amber_led.trigger->name,
- "sharpsl-charge"))
-#endif
- led_classdev_suspend(&tosa_amber_led);
- led_classdev_suspend(&tosa_green_led);
- return 0;
-}
-
-static int tosaled_resume(struct platform_device *dev)
-{
- led_classdev_resume(&tosa_amber_led);
- led_classdev_resume(&tosa_green_led);
- return 0;
-}
-#else
-#define tosaled_suspend NULL
-#define tosaled_resume NULL
-#endif
-
-static int tosaled_probe(struct platform_device *pdev)
-{
- int ret;
-
- ret = led_classdev_register(&pdev->dev, &tosa_amber_led);
- if (ret < 0)
- return ret;
-
- ret = led_classdev_register(&pdev->dev, &tosa_green_led);
- if (ret < 0)
- led_classdev_unregister(&tosa_amber_led);
-
- return ret;
-}
-
-static int tosaled_remove(struct platform_device *pdev)
-{
- led_classdev_unregister(&tosa_amber_led);
- led_classdev_unregister(&tosa_green_led);
-
- return 0;
-}
-
-static struct platform_driver tosaled_driver = {
- .probe = tosaled_probe,
- .remove = tosaled_remove,
- .suspend = tosaled_suspend,
- .resume = tosaled_resume,
- .driver = {
- .name = "tosa-led",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init tosaled_init(void)
-{
- return platform_driver_register(&tosaled_driver);
-}
-
-static void __exit tosaled_exit(void)
-{
- platform_driver_unregister(&tosaled_driver);
-}
-
-module_init(tosaled_init);
-module_exit(tosaled_exit);
-
-MODULE_AUTHOR("Dirk Opfer <Dirk@Opfer-Online.de>");
-MODULE_DESCRIPTION("Tosa LED driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:tosa-led");
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 0c886c88238..2566479937c 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -22,6 +22,22 @@ config MFD_ASIC3
This driver supports the ASIC3 multifunction chip found on many
PDAs (mainly iPAQ and HTC based ones)
+config HTC_EGPIO
+ bool "HTC EGPIO support"
+ depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB
+ help
+ This driver supports the CPLD egpio chip present on
+ several HTC phones. It provides basic support for input
+ pins, output pins, and irqs.
+
+config HTC_PASIC3
+ tristate "HTC PASIC3 LED/DS1WM chip support"
+ help
+ This core driver provides register access for the LED/DS1WM
+ chips labeled "AIC2" and "AIC3", found on HTC Blueangel and
+ HTC Magician devices, respectively. Actual functionality is
+ handled by the leds-pasic3 and ds1wm drivers.
+
endmenu
menu "Multimedia Capabilities Port drivers"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 521cd5cb68a..eef4e26807d 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -5,6 +5,9 @@
obj-$(CONFIG_MFD_SM501) += sm501.o
obj-$(CONFIG_MFD_ASIC3) += asic3.o
+obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
+obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
+
obj-$(CONFIG_MCP) += mcp-core.o
obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c
new file mode 100644
index 00000000000..8872cc07751
--- /dev/null
+++ b/drivers/mfd/htc-egpio.c
@@ -0,0 +1,440 @@
+/*
+ * Support for the GPIO/IRQ expander chips present on several HTC phones.
+ * These are implemented in CPLD chips present on the board.
+ *
+ * Copyright (c) 2007 Kevin O'Connor <kevin@koconnor.net>
+ * Copyright (c) 2007 Philipp Zabel <philipp.zabel@gmail.com>
+ *
+ * This file may be distributed under the terms of the GNU GPL license.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/mfd/htc-egpio.h>
+
+struct egpio_chip {
+ int reg_start;
+ int cached_values;
+ unsigned long is_out;
+ struct device *dev;
+ struct gpio_chip chip;
+};
+
+struct egpio_info {
+ spinlock_t lock;
+
+ /* iomem info */
+ void __iomem *base_addr;
+ int bus_shift; /* byte shift */
+ int reg_shift; /* bit shift */
+ int reg_mask;
+
+ /* irq info */
+ int ack_register;
+ int ack_write;
+ u16 irqs_enabled;
+ uint irq_start;
+ int nirqs;
+ uint chained_irq;
+
+ /* egpio info */
+ struct egpio_chip *chip;
+ int nchips;
+};
+
+static inline void egpio_writew(u16 value, struct egpio_info *ei, int reg)
+{
+ writew(value, ei->base_addr + (reg << ei->bus_shift));
+}
+
+static inline u16 egpio_readw(struct egpio_info *ei, int reg)
+{
+ return readw(ei->base_addr + (reg << ei->bus_shift));
+}
+
+/*
+ * IRQs
+ */
+
+static inline void ack_irqs(struct egpio_info *ei)
+{
+ egpio_writew(ei->ack_write, ei, ei->ack_register);
+ pr_debug("EGPIO ack - write %x to base+%x\n",
+ ei->ack_write, ei->ack_register << ei->bus_shift);
+}
+
+static void egpio_ack(unsigned int irq)
+{
+}
+
+/* There does not appear to be a way to proactively mask interrupts
+ * on the egpio chip itself. So, we simply ignore interrupts that
+ * aren't desired. */
+static void egpio_mask(unsigned int irq)
+{
+ struct egpio_info *ei = get_irq_chip_data(irq);
+ ei->irqs_enabled &= ~(1 << (irq - ei->irq_start));
+ pr_debug("EGPIO mask %d %04x\n", irq, ei->irqs_enabled);
+}
+static void egpio_unmask(unsigned int irq)
+{
+ struct egpio_info *ei = get_irq_chip_data(irq);
+ ei->irqs_enabled |= 1 << (irq - ei->irq_start);
+ pr_debug("EGPIO unmask %d %04x\n", irq, ei->irqs_enabled);
+}
+
+static struct irq_chip egpio_muxed_chip = {
+ .name = "htc-egpio",
+ .ack = egpio_ack,
+ .mask = egpio_mask,
+ .unmask = egpio_unmask,
+};
+
+static void egpio_handler(unsigned int irq, struct irq_desc *desc)
+{
+ struct egpio_info *ei = get_irq_data(irq);
+ int irqpin;
+
+ /* Read current pins. */
+ unsigned long readval = egpio_readw(ei, ei->ack_register);
+ pr_debug("IRQ reg: %x\n", (unsigned int)readval);
+ /* Ack/unmask interrupts. */
+ ack_irqs(ei);
+ /* Process all set pins. */
+ readval &= ei->irqs_enabled;
+ for_each_bit(irqpin, &readval, ei->nirqs) {
+ /* Run irq handler */
+ pr_debug("got IRQ %d\n", irqpin);
+ irq = ei->irq_start + irqpin;
+ desc = &irq_desc[irq];
+ desc->handle_irq(irq, desc);
+ }
+}
+
+int htc_egpio_get_wakeup_irq(struct device *dev)
+{
+ struct egpio_info *ei = dev_get_drvdata(dev);
+
+ /* Read current pins. */
+ u16 readval = egpio_readw(ei, ei->ack_register);
+ /* Ack/unmask interrupts. */
+ ack_irqs(ei);
+ /* Return first set pin. */
+ readval &= ei->irqs_enabled;
+ return ei->irq_start + ffs(readval) - 1;
+}
+EXPORT_SYMBOL(htc_egpio_get_wakeup_irq);
+
+static inline int egpio_pos(struct egpio_info *ei, int bit)
+{
+ return bit >> ei->reg_shift;
+}
+
+static inline int egpio_bit(struct egpio_info *ei, int bit)
+{
+ return 1 << (bit & ((1 << ei->reg_shift)-1));
+}
+
+/*
+ * Input pins
+ */
+
+static int egpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct egpio_chip *egpio;
+ struct egpio_info *ei;
+ unsigned bit;
+ int reg;
+ int value;
+
+ pr_debug("egpio_get_value(%d)\n", chip->base + offset);
+
+ egpio = container_of(chip, struct egpio_chip, chip);
+ ei = dev_get_drvdata(egpio->dev);
+ bit = egpio_bit(ei, offset);
+ reg = egpio->reg_start + egpio_pos(ei, offset);
+
+ value = egpio_readw(ei, reg);
+ pr_debug("readw(%p + %x) = %x\n",
+ ei->base_addr, reg << ei->bus_shift, value);
+ return value & bit;
+}
+
+static int egpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct egpio_chip *egpio;
+
+ egpio = container_of(chip, struct egpio_chip, chip);
+ return test_bit(offset, &egpio->is_out) ? -EINVAL : 0;
+}
+
+
+/*
+ * Output pins
+ */
+
+static void egpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ unsigned long flag;
+ struct egpio_chip *egpio;
+ struct egpio_info *ei;
+ unsigned bit;
+ int pos;
+ int reg;
+ int shift;
+
+ pr_debug("egpio_set(%s, %d(%d), %d)\n",
+ chip->label, offset, offset+chip->base, value);
+
+ egpio = container_of(chip, struct egpio_chip, chip);
+ ei = dev_get_drvdata(egpio->dev);
+ bit = egpio_bit(ei, offset);
+ pos = egpio_pos(ei, offset);
+ reg = egpio->reg_start + pos;
+ shift = pos << ei->reg_shift;
+
+ pr_debug("egpio %s: reg %d = 0x%04x\n", value ? "set" : "clear",
+ reg, (egpio->cached_values >> shift) & ei->reg_mask);
+
+ spin_lock_irqsave(&ei->lock, flag);
+ if (value)
+ egpio->cached_values |= (1 << offset);
+ else
+ egpio->cached_values &= ~(1 << offset);
+ egpio_writew((egpio->cached_values >> shift) & ei->reg_mask, ei, reg);
+ spin_unlock_irqrestore(&ei->lock, flag);
+}
+
+static int egpio_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct egpio_chip *egpio;
+
+ egpio = container_of(chip, struct egpio_chip, chip);
+ if (test_bit(offset, &egpio->is_out)) {
+ egpio_set(chip, offset, value);
+ return 0;
+ } else {
+ return -EINVAL;
+ }
+}
+
+static void egpio_write_cache(struct egpio_info *ei)
+{
+ int i;
+ struct egpio_chip *egpio;
+ int shift;
+
+ for (i = 0; i < ei->nchips; i++) {
+ egpio = &(ei->chip[i]);
+ if (!egpio->is_out)
+ continue;
+
+ for (shift = 0; shift < egpio->chip.ngpio;
+ shift += (1<<ei->reg_shift)) {
+
+ int reg = egpio->reg_start + egpio_pos(ei, shift);
+
+ if (!((egpio->is_out >> shift) & ei->reg_mask))
+ continue;
+
+ pr_debug("EGPIO: setting %x to %x, was %x\n", reg,
+ (egpio->cached_values >> shift) & ei->reg_mask,
+ egpio_readw(ei, reg));
+
+ egpio_writew((egpio->cached_values >> shift)
+ & ei->reg_mask, ei, reg);
+ }
+ }
+}
+
+
+/*
+ * Setup
+ */
+
+static int __init egpio_probe(struct platform_device *pdev)
+{
+ struct htc_egpio_platform_data *pdata = pdev->dev.platform_data;
+ struct resource *res;
+ struct egpio_info *ei;
+ struct gpio_chip *chip;
+ unsigned int irq, irq_end;
+ int i;
+ int ret;
+
+ /* Initialize ei data structure. */
+ ei = kzalloc(sizeof(*ei), GFP_KERNEL);
+ if (!ei)
+ return -ENOMEM;
+
+ spin_lock_init(&ei->lock);
+
+ /* Find chained irq */
+ ret = -EINVAL;
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (res)
+ ei->chained_irq = res->start;
+
+ /* Map egpio chip into virtual address space. */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ goto fail;
+ ei->base_addr = ioremap_nocache(res->start, res->end - res->start);
+ if (!ei->base_addr)
+ goto fail;
+ pr_debug("EGPIO phys=%08x virt=%p\n", res->start, ei->base_addr);
+
+ if ((pdata->bus_width != 16) && (pdata->bus_width != 32))
+ goto fail;
+ ei->bus_shift = fls(pdata->bus_width - 1) - 3;
+ pr_debug("bus_shift = %d\n", ei->bus_shift);
+
+ if ((pdata->reg_width != 8) && (pdata->reg_width != 16))
+ goto fail;
+ ei->reg_shift = fls(pdata->reg_width - 1);
+ pr_debug("reg_shift = %d\n", ei->reg_shift);
+
+ ei->reg_mask = (1 << pdata->reg_width) - 1;
+
+ platform_set_drvdata(pdev, ei);
+
+ ei->nchips = pdata->num_chips;
+ ei->chip = kzalloc(sizeof(struct egpio_chip) * ei->nchips, GFP_KERNEL);
+ if (!ei) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+ for (i = 0; i < ei->nchips; i++) {
+ ei->chip[i].reg_start = pdata->chip[i].reg_start;
+ ei->chip[i].cached_values = pdata->chip[i].initial_values;
+ ei->chip[i].is_out = pdata->chip[i].direction;
+ ei->chip[i].dev = &(pdev->dev);
+ chip = &(ei->chip[i].chip);
+ chip->label = "htc-egpio";
+ chip->get = egpio_get;
+ chip->set = egpio_set;
+ chip->direction_input = egpio_direction_input;
+ chip->direction_output = egpio_direction_output;
+ chip->base = pdata->chip[i].gpio_base;
+ chip->ngpio = pdata->chip[i].num_gpios;
+
+ gpiochip_add(chip);
+ }
+
+ /* Set initial pin values */
+ egpio_write_cache(ei);
+
+ ei->irq_start = pdata->irq_base;
+ ei->nirqs = pdata->num_irqs;
+ ei->ack_register = pdata->ack_register;
+
+ if (ei->chained_irq) {
+ /* Setup irq handlers */
+ ei->ack_write = 0xFFFF;
+ if (pdata->invert_acks)
+ ei->ack_write = 0;
+ irq_end = ei->irq_start + ei->nirqs;
+ for (irq = ei->irq_start; irq < irq_end; irq++) {
+ set_irq_chip(irq, &egpio_muxed_chip);
+ set_irq_chip_data(irq, ei);
+ set_irq_handler(irq, handle_simple_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ }
+ set_irq_type(ei->chained_irq, IRQ_TYPE_EDGE_RISING);
+ set_irq_data(ei->chained_irq, ei);
+ set_irq_chained_handler(ei->chained_irq, egpio_handler);
+ ack_irqs(ei);
+
+ device_init_wakeup(&pdev->dev, 1);
+ }
+
+ return 0;
+
+fail:
+ printk(KERN_ERR "EGPIO failed to setup\n");
+ kfree(ei);
+ return ret;
+}
+
+static int __exit egpio_remove(struct platform_device *pdev)
+{
+ struct egpio_info *ei = platform_get_drvdata(pdev);
+ unsigned int irq, irq_end;
+
+ if (ei->chained_irq) {
+ irq_end = ei->irq_start + ei->nirqs;
+ for (irq = ei->irq_start; irq < irq_end; irq++) {
+ set_irq_chip(irq, NULL);
+ set_irq_handler(irq, NULL);
+ set_irq_flags(irq, 0);
+ }
+ set_irq_chained_handler(ei->chained_irq, NULL);
+ device_init_wakeup(&pdev->dev, 0);
+ }
+ iounmap(ei->base_addr);
+ kfree(ei->chip);
+ kfree(ei);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int egpio_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct egpio_info *ei = platform_get_drvdata(pdev);
+
+ if (ei->chained_irq && device_may_wakeup(&pdev->dev))
+ enable_irq_wake(ei->chained_irq);
+ return 0;
+}
+
+static int egpio_resume(struct platform_device *pdev)
+{
+ struct egpio_info *ei = platform_get_drvdata(pdev);
+
+ if (ei->chained_irq && device_may_wakeup(&pdev->dev))
+ disable_irq_wake(ei->chained_irq);
+
+ /* Update registers from the cache, in case
+ the CPLD was powered off during suspend */
+ egpio_write_cache(ei);
+ return 0;
+}
+#else
+#define egpio_suspend NULL
+#define egpio_resume NULL
+#endif
+
+
+static struct platform_driver egpio_driver = {
+ .driver = {
+ .name = "htc-egpio",
+ },
+ .remove = __exit_p(egpio_remove),
+ .suspend = egpio_suspend,
+ .resume = egpio_resume,
+};
+
+static int __init egpio_init(void)
+{
+ return platform_driver_probe(&egpio_driver, egpio_probe);
+}
+
+static void __exit egpio_exit(void)
+{
+ platform_driver_unregister(&egpio_driver);
+}
+
+/* start early for dependencies */
+subsys_initcall(egpio_init);
+module_exit(egpio_exit)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kevin O'Connor <kevin@koconnor.net>");
diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c
new file mode 100644
index 00000000000..af66f4f2830
--- /dev/null
+++ b/drivers/mfd/htc-pasic3.c
@@ -0,0 +1,265 @@
+/*
+ * Core driver for HTC PASIC3 LED/DS1WM chip.
+ *
+ * Copyright (C) 2006 Philipp Zabel <philipp.zabel@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <linux/ds1wm.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/htc-pasic3.h>
+
+#include <asm/arch/pxa-regs.h>
+
+struct pasic3_data {
+ void __iomem *mapping;
+ unsigned int bus_shift;
+ struct platform_device *ds1wm_pdev;
+ struct platform_device *led_pdev;
+};
+
+#define REG_ADDR 5
+#define REG_DATA 6
+#define NUM_REGS 7
+
+#define READ_MODE 0x80
+
+/*
+ * write to a secondary register on the PASIC3
+ */
+void pasic3_write_register(struct device *dev, u32 reg, u8 val)
+{
+ struct pasic3_data *asic = dev->driver_data;
+ int bus_shift = asic->bus_shift;
+ void __iomem *addr = asic->mapping + (REG_ADDR << bus_shift);
+ void __iomem *data = asic->mapping + (REG_DATA << bus_shift);
+
+ __raw_writeb(~READ_MODE & reg, addr);
+ __raw_writeb(val, data);
+}
+EXPORT_SYMBOL(pasic3_write_register); /* for leds-pasic3 */
+
+/*
+ * read from a secondary register on the PASIC3
+ */
+u8 pasic3_read_register(struct device *dev, u32 reg)
+{
+ struct pasic3_data *asic = dev->driver_data;
+ int bus_shift = asic->bus_shift;
+ void __iomem *addr = asic->mapping + (REG_ADDR << bus_shift);
+ void __iomem *data = asic->mapping + (REG_DATA << bus_shift);
+
+ __raw_writeb(READ_MODE | reg, addr);
+ return __raw_readb(data);
+}
+EXPORT_SYMBOL(pasic3_read_register); /* for leds-pasic3 */
+
+/*
+ * LEDs
+ */
+
+static int led_device_add(struct device *pasic3_dev,
+ const struct pasic3_leds_machinfo *pdata)
+{
+ struct pasic3_data *asic = pasic3_dev->driver_data;
+ struct platform_device *pdev;
+ int ret;
+
+ pdev = platform_device_alloc("pasic3-led", -1);
+ if (!pdev) {
+ dev_dbg(pasic3_dev, "failed to allocate LED platform device\n");
+ return -ENOMEM;
+ }
+
+ ret = platform_device_add_data(pdev, pdata,
+ sizeof(struct pasic3_leds_machinfo));
+ if (ret < 0) {
+ dev_dbg(pasic3_dev, "failed to add LED platform data\n");
+ goto exit_pdev_put;
+ }
+
+ pdev->dev.parent = pasic3_dev;
+ ret = platform_device_add(pdev);
+ if (ret < 0) {
+ dev_dbg(pasic3_dev, "failed to add LED platform device\n");
+ goto exit_pdev_put;
+ }
+
+ asic->led_pdev = pdev;
+ return 0;
+
+exit_pdev_put:
+ platform_device_put(pdev);
+ return ret;
+}
+
+/*
+ * DS1WM
+ */
+
+static void ds1wm_enable(struct platform_device *pdev)
+{
+ struct device *dev = pdev->dev.parent;
+ int c;
+
+ c = pasic3_read_register(dev, 0x28);
+ pasic3_write_register(dev, 0x28, c & 0x7f);
+
+ dev_dbg(dev, "DS1WM OWM_EN low (active) %02x\n", c & 0x7f);
+}
+
+static void ds1wm_disable(struct platform_device *pdev)
+{
+ struct device *dev = pdev->dev.parent;
+ int c;
+
+ c = pasic3_read_register(dev, 0x28);
+ pasic3_write_register(dev, 0x28, c | 0x80);
+
+ dev_dbg(dev, "DS1WM OWM_EN high (inactive) %02x\n", c | 0x80);
+}
+
+static struct ds1wm_platform_data ds1wm_pdata = {
+ .bus_shift = 2,
+ .enable = ds1wm_enable,
+ .disable = ds1wm_disable,
+};
+
+static int ds1wm_device_add(struct device *pasic3_dev, int bus_shift)
+{
+ struct pasic3_data *asic = pasic3_dev->driver_data;
+ struct platform_device *pdev;
+ int ret;
+
+ pdev = platform_device_alloc("ds1wm", -1);
+ if (!pdev) {
+ dev_dbg(pasic3_dev, "failed to allocate DS1WM platform device\n");
+ return -ENOMEM;
+ }
+
+ ret = platform_device_add_resources(pdev, pdev->resource,
+ pdev->num_resources);
+ if (ret < 0) {
+ dev_dbg(pasic3_dev, "failed to add DS1WM resources\n");
+ goto exit_pdev_put;
+ }
+
+ ds1wm_pdata.bus_shift = asic->bus_shift;
+ ret = platform_device_add_data(pdev, &ds1wm_pdata,
+ sizeof(struct ds1wm_platform_data));
+ if (ret < 0) {
+ dev_dbg(pasic3_dev, "failed to add DS1WM platform data\n");
+ goto exit_pdev_put;
+ }
+
+ pdev->dev.parent = pasic3_dev;
+ ret = platform_device_add(pdev);
+ if (ret < 0) {
+ dev_dbg(pasic3_dev, "failed to add DS1WM platform device\n");
+ goto exit_pdev_put;
+ }
+
+ asic->ds1wm_pdev = pdev;
+ return 0;
+
+exit_pdev_put:
+ platform_device_put(pdev);
+ return ret;
+}
+
+static int __init pasic3_probe(struct platform_device *pdev)
+{
+ struct pasic3_platform_data *pdata = pdev->dev.platform_data;
+ struct device *dev = &pdev->dev;
+ struct pasic3_data *asic;
+ struct resource *r;
+ int ret;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!r)
+ return -ENXIO;
+
+ if (!request_mem_region(r->start, r->end - r->start + 1, "pasic3"))
+ return -EBUSY;
+
+ asic = kzalloc(sizeof(struct pasic3_data), GFP_KERNEL);
+ if (!asic)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, asic);
+
+ if (pdata && pdata->bus_shift)
+ asic->bus_shift = pdata->bus_shift;
+ else
+ asic->bus_shift = 2;
+
+ asic->mapping = ioremap(r->start, r->end - r->start + 1);
+ if (!asic->mapping) {
+ dev_err(dev, "couldn't ioremap PASIC3\n");
+ kfree(asic);
+ return -ENOMEM;
+ }
+
+ ret = ds1wm_device_add(dev, asic->bus_shift);
+ if (ret < 0)
+ dev_warn(dev, "failed to register DS1WM\n");
+
+ if (pdata->led_pdata) {
+ ret = led_device_add(dev, pdata->led_pdata);
+ if (ret < 0)
+ dev_warn(dev, "failed to register LED device\n");
+ }
+
+ return 0;
+}
+
+static int pasic3_remove(struct platform_device *pdev)
+{
+ struct pasic3_data *asic = platform_get_drvdata(pdev);
+ struct resource *r;
+
+ if (asic->led_pdev)
+ platform_device_unregister(asic->led_pdev);
+ if (asic->ds1wm_pdev)
+ platform_device_unregister(asic->ds1wm_pdev);
+
+ iounmap(asic->mapping);
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(r->start, r->end - r->start + 1);
+ kfree(asic);
+ return 0;
+}
+
+static struct platform_driver pasic3_driver = {
+ .driver = {
+ .name = "pasic3",
+ },
+ .remove = pasic3_remove,
+};
+
+static int __init pasic3_base_init(void)
+{
+ return platform_driver_probe(&pasic3_driver, pasic3_probe);
+}
+
+static void __exit pasic3_base_exit(void)
+{
+ platform_driver_unregister(&pasic3_driver);
+}
+
+module_init(pasic3_base_init);
+module_exit(pasic3_base_exit);
+
+MODULE_AUTHOR("Philipp Zabel <philipp.zabel@gmail.com>");
+MODULE_DESCRIPTION("Core driver for HTC PASIC3");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 4a3c6759492..959fb86cda0 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -314,7 +314,7 @@ config MTD_ALAUDA
config MTD_NAND_ORION
tristate "NAND Flash support for Marvell Orion SoC"
- depends on ARCH_ORION && MTD_NAND
+ depends on PLAT_ORION && MTD_NAND
help
This enables the NAND flash controller on Orion machines.
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index 9162cca0182..ec5ad28b237 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -18,8 +18,8 @@
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/sizes.h>
-#include <asm/arch/platform.h>
#include <asm/arch/hardware.h>
+#include <asm/plat-orion/orion_nand.h>
#ifdef CONFIG_MTD_CMDLINE_PARTS
static const char *part_probes[] = { "cmdlinepart", NULL };
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 45c3a208d93..2399a3796f6 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2335,7 +2335,7 @@ config UGETH_TX_ON_DEMAND
config MV643XX_ETH
tristate "Marvell Discovery (643XX) and Orion ethernet support"
- depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) || ARCH_ORION
+ depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) || PLAT_ORION
select MII
help
This driver supports the gigabit ethernet MACs in the
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
index 0ae0d83e5d2..978e20a1791 100644
--- a/drivers/net/arm/at91_ether.c
+++ b/drivers/net/arm/at91_ether.c
@@ -1043,7 +1043,9 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add
} else if (machine_is_csb337()) {
/* mix link activity status into LED2 link state */
write_phy(phy_address, MII_LEDCTRL_REG, 0x0d22);
- }
+ } else if (machine_is_ecbat91())
+ write_phy(phy_address, MII_LEDCTRL_REG, 0x156A);
+
disable_mdi();
spin_unlock_irq(&lp->lock);
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 8c09344f58d..8db71ab2045 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -36,6 +36,7 @@
#include <asm/hardware.h>
#include <asm/arch/irda.h>
#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
#ifdef CONFIG_MACH_MAINSTONE
#include <asm/arch/mainstone.h>
@@ -831,6 +832,11 @@ static int pxa_irda_probe(struct platform_device *pdev)
if (err)
goto err_mem_5;
+ if (si->pdata->startup)
+ err = si->pdata->startup(si->dev);
+ if (err)
+ goto err_startup;
+
dev->hard_start_xmit = pxa_irda_hard_xmit;
dev->open = pxa_irda_start;
dev->stop = pxa_irda_stop;
@@ -856,6 +862,9 @@ static int pxa_irda_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, dev);
if (err) {
+ if (si->pdata->shutdown)
+ si->pdata->shutdown(si->dev);
+err_startup:
kfree(si->tx_buff.head);
err_mem_5:
kfree(si->rx_buff.head);
@@ -881,6 +890,8 @@ static int pxa_irda_remove(struct platform_device *_dev)
if (dev) {
struct pxa_irda *si = netdev_priv(dev);
unregister_netdev(dev);
+ if (si->pdata->shutdown)
+ si->pdata->shutdown(si->dev);
kfree(si->tx_buff.head);
kfree(si->rx_buff.head);
clk_put(si->fir_clk);
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index e571c72e675..e8d94fafc28 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -182,15 +182,18 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
struct mempolicy *oldpol;
cpumask_t oldmask = current->cpus_allowed;
int node = pcibus_to_node(dev->bus);
- if (node >= 0 && node_online(node))
- set_cpus_allowed(current, node_to_cpumask(node));
+
+ if (node >= 0) {
+ node_to_cpumask_ptr(nodecpumask, node);
+ set_cpus_allowed_ptr(current, nodecpumask);
+ }
/* And set default memory allocation policy */
oldpol = current->mempolicy;
current->mempolicy = NULL; /* fall back to system default policy */
#endif
error = drv->probe(dev, id);
#ifdef CONFIG_NUMA
- set_cpus_allowed(current, oldmask);
+ set_cpus_allowed_ptr(current, &oldmask);
current->mempolicy = oldpol;
#endif
return error;
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 8dcf1458aa2..8d9d648daeb 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -73,8 +73,23 @@ static ssize_t local_cpus_show(struct device *dev,
mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
- strcat(buf,"\n");
- return 1+len;
+ buf[len++] = '\n';
+ buf[len] = '\0';
+ return len;
+}
+
+
+static ssize_t local_cpulist_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ cpumask_t mask;
+ int len;
+
+ mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
+ len = cpulist_scnprintf(buf, PAGE_SIZE-2, mask);
+ buf[len++] = '\n';
+ buf[len] = '\0';
+ return len;
}
/* show resources */
@@ -201,6 +216,7 @@ struct device_attribute pci_dev_attrs[] = {
__ATTR_RO(class),
__ATTR_RO(irq),
__ATTR_RO(local_cpus),
+ __ATTR_RO(local_cpulist),
__ATTR_RO(modalias),
#ifdef CONFIG_NUMA
__ATTR_RO(numa_node),
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 2db2e4bb0d1..4b3011a23ef 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -82,6 +82,7 @@ void pci_remove_legacy_files(struct pci_bus *bus) { return; }
* PCI Bus Class Devices
*/
static ssize_t pci_bus_show_cpuaffinity(struct device *dev,
+ int type,
struct device_attribute *attr,
char *buf)
{
@@ -89,12 +90,30 @@ static ssize_t pci_bus_show_cpuaffinity(struct device *dev,
cpumask_t cpumask;
cpumask = pcibus_to_cpumask(to_pci_bus(dev));
- ret = cpumask_scnprintf(buf, PAGE_SIZE, cpumask);
- if (ret < PAGE_SIZE)
- buf[ret++] = '\n';
+ ret = type?
+ cpulist_scnprintf(buf, PAGE_SIZE-2, cpumask):
+ cpumask_scnprintf(buf, PAGE_SIZE-2, cpumask);
+ buf[ret++] = '\n';
+ buf[ret] = '\0';
return ret;
}
-DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL);
+
+static ssize_t inline pci_bus_show_cpumaskaffinity(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return pci_bus_show_cpuaffinity(dev, 0, attr, buf);
+}
+
+static ssize_t inline pci_bus_show_cpulistaffinity(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return pci_bus_show_cpuaffinity(dev, 1, attr, buf);
+}
+
+DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpumaskaffinity, NULL);
+DEVICE_ATTR(cpulistaffinity, S_IRUGO, pci_bus_show_cpulistaffinity, NULL);
/*
* PCI Bus Class
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 8b22281b087..ed8c0690480 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -200,6 +200,7 @@ config PCMCIA_AU1X00
config PCMCIA_SA1100
tristate "SA1100 support"
depends on ARM && ARCH_SA1100 && PCMCIA
+ depends on ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL || MACH_ARMCORE
help
Say Y here to include support for SA11x0-based PCMCIA or CF
sockets, found on HP iPAQs, Yopy, and other StrongARM(R)/
diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c
index fbf2f3a6984..e7ab060ff11 100644
--- a/drivers/pcmcia/pxa2xx_cm_x270.c
+++ b/drivers/pcmcia/pxa2xx_cm_x270.c
@@ -20,6 +20,7 @@
#include <asm/hardware.h>
#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
#include <asm/arch/cm-x270.h>
#include "soc_common.h"
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 9e9caa5d7f5..c594b34c676 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -1,8 +1,9 @@
/*
* SuperH On-Chip RTC Support
*
- * Copyright (C) 2006, 2007 Paul Mundt
+ * Copyright (C) 2006, 2007, 2008 Paul Mundt
* Copyright (C) 2006 Jamie Lenehan
+ * Copyright (C) 2008 Angelo Castello
*
* Based on the old arch/sh/kernel/cpu/rtc.c by:
*
@@ -26,7 +27,7 @@
#include <asm/rtc.h>
#define DRV_NAME "sh-rtc"
-#define DRV_VERSION "0.1.6"
+#define DRV_VERSION "0.2.0"
#define RTC_REG(r) ((r) * rtc_reg_size)
@@ -63,6 +64,13 @@
/* ALARM Bits - or with BCD encoded value */
#define AR_ENB 0x80 /* Enable for alarm cmp */
+/* Period Bits */
+#define PF_HP 0x100 /* Enable Half Period to support 8,32,128Hz */
+#define PF_COUNT 0x200 /* Half periodic counter */
+#define PF_OXS 0x400 /* Periodic One x Second */
+#define PF_KOU 0x800 /* Kernel or User periodic request 1=kernel */
+#define PF_MASK 0xf00
+
/* RCR1 Bits */
#define RCR1_CF 0x80 /* Carry Flag */
#define RCR1_CIE 0x10 /* Carry Interrupt Enable */
@@ -84,33 +92,24 @@ struct sh_rtc {
unsigned int alarm_irq, periodic_irq, carry_irq;
struct rtc_device *rtc_dev;
spinlock_t lock;
- int rearm_aie;
unsigned long capabilities; /* See asm-sh/rtc.h for cap bits */
+ unsigned short periodic_freq;
};
static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id)
{
- struct platform_device *pdev = to_platform_device(dev_id);
- struct sh_rtc *rtc = platform_get_drvdata(pdev);
- unsigned int tmp, events = 0;
+ struct sh_rtc *rtc = dev_id;
+ unsigned int tmp;
spin_lock(&rtc->lock);
tmp = readb(rtc->regbase + RCR1);
tmp &= ~RCR1_CF;
-
- if (rtc->rearm_aie) {
- if (tmp & RCR1_AF)
- tmp &= ~RCR1_AF; /* try to clear AF again */
- else {
- tmp |= RCR1_AIE; /* AF has cleared, rearm IRQ */
- rtc->rearm_aie = 0;
- }
- }
-
writeb(tmp, rtc->regbase + RCR1);
- rtc_update_irq(rtc->rtc_dev, 1, events);
+ /* Users have requested One x Second IRQ */
+ if (rtc->periodic_freq & PF_OXS)
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
spin_unlock(&rtc->lock);
@@ -119,47 +118,48 @@ static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id)
static irqreturn_t sh_rtc_alarm(int irq, void *dev_id)
{
- struct platform_device *pdev = to_platform_device(dev_id);
- struct sh_rtc *rtc = platform_get_drvdata(pdev);
- unsigned int tmp, events = 0;
+ struct sh_rtc *rtc = dev_id;
+ unsigned int tmp;
spin_lock(&rtc->lock);
tmp = readb(rtc->regbase + RCR1);
-
- /*
- * If AF is set then the alarm has triggered. If we clear AF while
- * the alarm time still matches the RTC time then AF will
- * immediately be set again, and if AIE is enabled then the alarm
- * interrupt will immediately be retrigger. So we clear AIE here
- * and use rtc->rearm_aie so that the carry interrupt will keep
- * trying to clear AF and once it stays cleared it'll re-enable
- * AIE.
- */
- if (tmp & RCR1_AF) {
- events |= RTC_AF | RTC_IRQF;
-
- tmp &= ~(RCR1_AF|RCR1_AIE);
-
+ tmp &= ~(RCR1_AF | RCR1_AIE);
writeb(tmp, rtc->regbase + RCR1);
- rtc->rearm_aie = 1;
-
- rtc_update_irq(rtc->rtc_dev, 1, events);
- }
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
spin_unlock(&rtc->lock);
+
return IRQ_HANDLED;
}
static irqreturn_t sh_rtc_periodic(int irq, void *dev_id)
{
- struct platform_device *pdev = to_platform_device(dev_id);
- struct sh_rtc *rtc = platform_get_drvdata(pdev);
+ struct sh_rtc *rtc = dev_id;
+ struct rtc_device *rtc_dev = rtc->rtc_dev;
+ unsigned int tmp;
spin_lock(&rtc->lock);
- rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
+ tmp = readb(rtc->regbase + RCR2);
+ tmp &= ~RCR2_PEF;
+ writeb(tmp, rtc->regbase + RCR2);
+
+ /* Half period enabled than one skipped and the next notified */
+ if ((rtc->periodic_freq & PF_HP) && (rtc->periodic_freq & PF_COUNT))
+ rtc->periodic_freq &= ~PF_COUNT;
+ else {
+ if (rtc->periodic_freq & PF_HP)
+ rtc->periodic_freq |= PF_COUNT;
+ if (rtc->periodic_freq & PF_KOU) {
+ spin_lock(&rtc_dev->irq_task_lock);
+ if (rtc_dev->irq_task)
+ rtc_dev->irq_task->func(rtc_dev->irq_task->private_data);
+ spin_unlock(&rtc_dev->irq_task_lock);
+ } else
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
+ }
spin_unlock(&rtc->lock);
@@ -176,8 +176,8 @@ static inline void sh_rtc_setpie(struct device *dev, unsigned int enable)
tmp = readb(rtc->regbase + RCR2);
if (enable) {
- tmp &= ~RCR2_PESMASK;
- tmp |= RCR2_PEF | (2 << 4);
+ tmp &= ~RCR2_PEF; /* Clear PES bit */
+ tmp |= (rtc->periodic_freq & ~PF_HP); /* Set PES2-0 */
} else
tmp &= ~(RCR2_PESMASK | RCR2_PEF);
@@ -186,82 +186,81 @@ static inline void sh_rtc_setpie(struct device *dev, unsigned int enable)
spin_unlock_irq(&rtc->lock);
}
-static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)
+static inline int sh_rtc_setfreq(struct device *dev, unsigned int freq)
{
struct sh_rtc *rtc = dev_get_drvdata(dev);
- unsigned int tmp;
+ int tmp, ret = 0;
spin_lock_irq(&rtc->lock);
+ tmp = rtc->periodic_freq & PF_MASK;
- tmp = readb(rtc->regbase + RCR1);
-
- if (!enable) {
- tmp &= ~RCR1_AIE;
- rtc->rearm_aie = 0;
- } else if (rtc->rearm_aie == 0)
- tmp |= RCR1_AIE;
+ switch (freq) {
+ case 0:
+ rtc->periodic_freq = 0x00;
+ break;
+ case 1:
+ rtc->periodic_freq = 0x60;
+ break;
+ case 2:
+ rtc->periodic_freq = 0x50;
+ break;
+ case 4:
+ rtc->periodic_freq = 0x40;
+ break;
+ case 8:
+ rtc->periodic_freq = 0x30 | PF_HP;
+ break;
+ case 16:
+ rtc->periodic_freq = 0x30;
+ break;
+ case 32:
+ rtc->periodic_freq = 0x20 | PF_HP;
+ break;
+ case 64:
+ rtc->periodic_freq = 0x20;
+ break;
+ case 128:
+ rtc->periodic_freq = 0x10 | PF_HP;
+ break;
+ case 256:
+ rtc->periodic_freq = 0x10;
+ break;
+ default:
+ ret = -ENOTSUPP;
+ }
- writeb(tmp, rtc->regbase + RCR1);
+ if (ret == 0) {
+ rtc->periodic_freq |= tmp;
+ rtc->rtc_dev->irq_freq = freq;
+ }
spin_unlock_irq(&rtc->lock);
+ return ret;
}
-static int sh_rtc_open(struct device *dev)
+static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)
{
struct sh_rtc *rtc = dev_get_drvdata(dev);
unsigned int tmp;
- int ret;
-
- tmp = readb(rtc->regbase + RCR1);
- tmp &= ~RCR1_CF;
- tmp |= RCR1_CIE;
- writeb(tmp, rtc->regbase + RCR1);
- ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, IRQF_DISABLED,
- "sh-rtc period", dev);
- if (unlikely(ret)) {
- dev_err(dev, "request period IRQ failed with %d, IRQ %d\n",
- ret, rtc->periodic_irq);
- return ret;
- }
-
- ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, IRQF_DISABLED,
- "sh-rtc carry", dev);
- if (unlikely(ret)) {
- dev_err(dev, "request carry IRQ failed with %d, IRQ %d\n",
- ret, rtc->carry_irq);
- free_irq(rtc->periodic_irq, dev);
- goto err_bad_carry;
- }
+ spin_lock_irq(&rtc->lock);
- ret = request_irq(rtc->alarm_irq, sh_rtc_alarm, IRQF_DISABLED,
- "sh-rtc alarm", dev);
- if (unlikely(ret)) {
- dev_err(dev, "request alarm IRQ failed with %d, IRQ %d\n",
- ret, rtc->alarm_irq);
- goto err_bad_alarm;
- }
+ tmp = readb(rtc->regbase + RCR1);
- return 0;
+ if (!enable)
+ tmp &= ~RCR1_AIE;
+ else
+ tmp |= RCR1_AIE;
-err_bad_alarm:
- free_irq(rtc->carry_irq, dev);
-err_bad_carry:
- free_irq(rtc->periodic_irq, dev);
+ writeb(tmp, rtc->regbase + RCR1);
- return ret;
+ spin_unlock_irq(&rtc->lock);
}
static void sh_rtc_release(struct device *dev)
{
- struct sh_rtc *rtc = dev_get_drvdata(dev);
-
sh_rtc_setpie(dev, 0);
sh_rtc_setaie(dev, 0);
-
- free_irq(rtc->periodic_irq, dev);
- free_irq(rtc->carry_irq, dev);
- free_irq(rtc->alarm_irq, dev);
}
static int sh_rtc_proc(struct device *dev, struct seq_file *seq)
@@ -270,31 +269,44 @@ static int sh_rtc_proc(struct device *dev, struct seq_file *seq)
unsigned int tmp;
tmp = readb(rtc->regbase + RCR1);
- seq_printf(seq, "carry_IRQ\t: %s\n",
- (tmp & RCR1_CIE) ? "yes" : "no");
+ seq_printf(seq, "carry_IRQ\t: %s\n", (tmp & RCR1_CIE) ? "yes" : "no");
tmp = readb(rtc->regbase + RCR2);
seq_printf(seq, "periodic_IRQ\t: %s\n",
- (tmp & RCR2_PEF) ? "yes" : "no");
+ (tmp & RCR2_PESMASK) ? "yes" : "no");
return 0;
}
static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
- unsigned int ret = -ENOIOCTLCMD;
+ struct sh_rtc *rtc = dev_get_drvdata(dev);
+ unsigned int ret = 0;
switch (cmd) {
case RTC_PIE_OFF:
case RTC_PIE_ON:
sh_rtc_setpie(dev, cmd == RTC_PIE_ON);
- ret = 0;
break;
case RTC_AIE_OFF:
case RTC_AIE_ON:
sh_rtc_setaie(dev, cmd == RTC_AIE_ON);
- ret = 0;
break;
+ case RTC_UIE_OFF:
+ rtc->periodic_freq &= ~PF_OXS;
+ break;
+ case RTC_UIE_ON:
+ rtc->periodic_freq |= PF_OXS;
+ break;
+ case RTC_IRQP_READ:
+ ret = put_user(rtc->rtc_dev->irq_freq,
+ (unsigned long __user *)arg);
+ break;
+ case RTC_IRQP_SET:
+ ret = sh_rtc_setfreq(dev, arg);
+ break;
+ default:
+ ret = -ENOIOCTLCMD;
}
return ret;
@@ -421,7 +433,7 @@ static int sh_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
{
struct platform_device *pdev = to_platform_device(dev);
struct sh_rtc *rtc = platform_get_drvdata(pdev);
- struct rtc_time* tm = &wkalrm->time;
+ struct rtc_time *tm = &wkalrm->time;
spin_lock_irq(&rtc->lock);
@@ -452,7 +464,7 @@ static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc,
writeb(BIN2BCD(value) | AR_ENB, rtc->regbase + reg_off);
}
-static int sh_rtc_check_alarm(struct rtc_time* tm)
+static int sh_rtc_check_alarm(struct rtc_time *tm)
{
/*
* The original rtc says anything > 0xc0 is "don't care" or "match
@@ -503,11 +515,9 @@ static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
/* disable alarm interrupt and clear the alarm flag */
rcr1 = readb(rtc->regbase + RCR1);
- rcr1 &= ~(RCR1_AF|RCR1_AIE);
+ rcr1 &= ~(RCR1_AF | RCR1_AIE);
writeb(rcr1, rtc->regbase + RCR1);
- rtc->rearm_aie = 0;
-
/* set alarm time */
sh_rtc_write_alarm_value(rtc, tm->tm_sec, RSECAR);
sh_rtc_write_alarm_value(rtc, tm->tm_min, RMINAR);
@@ -529,14 +539,34 @@ static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
return 0;
}
+static int sh_rtc_irq_set_state(struct device *dev, int enabled)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct sh_rtc *rtc = platform_get_drvdata(pdev);
+
+ if (enabled) {
+ rtc->periodic_freq |= PF_KOU;
+ return sh_rtc_ioctl(dev, RTC_PIE_ON, 0);
+ } else {
+ rtc->periodic_freq &= ~PF_KOU;
+ return sh_rtc_ioctl(dev, RTC_PIE_OFF, 0);
+ }
+}
+
+static int sh_rtc_irq_set_freq(struct device *dev, int freq)
+{
+ return sh_rtc_ioctl(dev, RTC_IRQP_SET, freq);
+}
+
static struct rtc_class_ops sh_rtc_ops = {
- .open = sh_rtc_open,
.release = sh_rtc_release,
.ioctl = sh_rtc_ioctl,
.read_time = sh_rtc_read_time,
.set_time = sh_rtc_set_time,
.read_alarm = sh_rtc_read_alarm,
.set_alarm = sh_rtc_set_alarm,
+ .irq_set_state = sh_rtc_irq_set_state,
+ .irq_set_freq = sh_rtc_irq_set_freq,
.proc = sh_rtc_proc,
};
@@ -544,6 +574,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
{
struct sh_rtc *rtc;
struct resource *res;
+ unsigned int tmp;
int ret = -ENOENT;
rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL);
@@ -552,6 +583,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
spin_lock_init(&rtc->lock);
+ /* get periodic/carry/alarm irqs */
rtc->periodic_irq = platform_get_irq(pdev, 0);
if (unlikely(rtc->periodic_irq < 0)) {
dev_err(&pdev->dev, "No IRQ for period\n");
@@ -608,8 +640,48 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
rtc->capabilities |= pinfo->capabilities;
}
+ rtc->rtc_dev->max_user_freq = 256;
+ rtc->rtc_dev->irq_freq = 1;
+ rtc->periodic_freq = 0x60;
+
platform_set_drvdata(pdev, rtc);
+ /* register periodic/carry/alarm irqs */
+ ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, IRQF_DISABLED,
+ "sh-rtc period", rtc);
+ if (unlikely(ret)) {
+ dev_err(&pdev->dev,
+ "request period IRQ failed with %d, IRQ %d\n", ret,
+ rtc->periodic_irq);
+ goto err_badmap;
+ }
+
+ ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, IRQF_DISABLED,
+ "sh-rtc carry", rtc);
+ if (unlikely(ret)) {
+ dev_err(&pdev->dev,
+ "request carry IRQ failed with %d, IRQ %d\n", ret,
+ rtc->carry_irq);
+ free_irq(rtc->periodic_irq, rtc);
+ goto err_badmap;
+ }
+
+ ret = request_irq(rtc->alarm_irq, sh_rtc_alarm, IRQF_DISABLED,
+ "sh-rtc alarm", rtc);
+ if (unlikely(ret)) {
+ dev_err(&pdev->dev,
+ "request alarm IRQ failed with %d, IRQ %d\n", ret,
+ rtc->alarm_irq);
+ free_irq(rtc->carry_irq, rtc);
+ free_irq(rtc->periodic_irq, rtc);
+ goto err_badmap;
+ }
+
+ tmp = readb(rtc->regbase + RCR1);
+ tmp &= ~RCR1_CF;
+ tmp |= RCR1_CIE;
+ writeb(tmp, rtc->regbase + RCR1);
+
return 0;
err_badmap:
@@ -630,6 +702,10 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev)
sh_rtc_setpie(&pdev->dev, 0);
sh_rtc_setaie(&pdev->dev, 0);
+ free_irq(rtc->carry_irq, rtc);
+ free_irq(rtc->periodic_irq, rtc);
+ free_irq(rtc->alarm_irq, rtc);
+
release_resource(rtc->res);
platform_set_drvdata(pdev, NULL);
@@ -662,6 +738,8 @@ module_exit(sh_rtc_exit);
MODULE_DESCRIPTION("SuperH on-chip RTC driver");
MODULE_VERSION(DRV_VERSION);
-MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, Jamie Lenehan <lenehan@twibble.org>");
+MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, "
+ "Jamie Lenehan <lenehan@twibble.org>, "
+ "Angelo Castello <angelo.castello@st.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 16ba9ac7a56..5a375bf0ebf 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -166,15 +166,6 @@
#define SERIAL_IMX_MAJOR 204
#define MINOR_START 41
-#define NR_PORTS 2
-
-#define IMX_ISR_PASS_LIMIT 256
-
-/*
- * This is the size of our serial port register set.
- */
-#define UART_PORT_SIZE 0x100
-
/*
* This determines how often we check the modem status signals
* for any change. They generally aren't connected to an IRQ
@@ -358,66 +349,60 @@ static irqreturn_t imx_rxint(int irq, void *dev_id)
struct tty_struct *tty = sport->port.info->tty;
unsigned long flags, temp;
- rx = readl(sport->port.membase + URXD0);
spin_lock_irqsave(&sport->port.lock,flags);
- do {
+ while (readl(sport->port.membase + USR2) & USR2_RDR) {
flg = TTY_NORMAL;
sport->port.icount.rx++;
+ rx = readl(sport->port.membase + URXD0);
+
temp = readl(sport->port.membase + USR2);
- if( temp & USR2_BRCD ) {
+ if (temp & USR2_BRCD) {
writel(temp | USR2_BRCD, sport->port.membase + USR2);
- if(uart_handle_break(&sport->port))
- goto ignore_char;
+ if (uart_handle_break(&sport->port))
+ continue;
}
if (uart_handle_sysrq_char
(&sport->port, (unsigned char)rx))
- goto ignore_char;
+ continue;
+
+ if (rx & (URXD_PRERR | URXD_OVRRUN | URXD_FRMERR) ) {
+ if (rx & URXD_PRERR)
+ sport->port.icount.parity++;
+ else if (rx & URXD_FRMERR)
+ sport->port.icount.frame++;
+ if (rx & URXD_OVRRUN)
+ sport->port.icount.overrun++;
+
+ if (rx & sport->port.ignore_status_mask) {
+ if (++ignored > 100)
+ goto out;
+ continue;
+ }
+
+ rx &= sport->port.read_status_mask;
+
+ if (rx & URXD_PRERR)
+ flg = TTY_PARITY;
+ else if (rx & URXD_FRMERR)
+ flg = TTY_FRAME;
+ if (rx & URXD_OVRRUN)
+ flg = TTY_OVERRUN;
- if( rx & (URXD_PRERR | URXD_OVRRUN | URXD_FRMERR) )
- goto handle_error;
+#ifdef SUPPORT_SYSRQ
+ sport->port.sysrq = 0;
+#endif
+ }
- error_return:
tty_insert_flip_char(tty, rx, flg);
-
- ignore_char:
- rx = readl(sport->port.membase + URXD0);
- } while(rx & URXD_CHARRDY);
+ }
out:
spin_unlock_irqrestore(&sport->port.lock,flags);
tty_flip_buffer_push(tty);
return IRQ_HANDLED;
-
-handle_error:
- if (rx & URXD_PRERR)
- sport->port.icount.parity++;
- else if (rx & URXD_FRMERR)
- sport->port.icount.frame++;
- if (rx & URXD_OVRRUN)
- sport->port.icount.overrun++;
-
- if (rx & sport->port.ignore_status_mask) {
- if (++ignored > 100)
- goto out;
- goto ignore_char;
- }
-
- rx &= sport->port.read_status_mask;
-
- if (rx & URXD_PRERR)
- flg = TTY_PARITY;
- else if (rx & URXD_FRMERR)
- flg = TTY_FRAME;
- if (rx & URXD_OVRRUN)
- flg = TTY_OVERRUN;
-
-#ifdef SUPPORT_SYSRQ
- sport->port.sysrq = 0;
-#endif
- goto error_return;
}
/*
@@ -546,7 +531,7 @@ static int imx_startup(struct uart_port *port)
writel(USR1_RTSD, sport->port.membase + USR1);
temp = readl(sport->port.membase + UCR1);
- temp |= (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
+ temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
writel(temp, sport->port.membase + UCR1);
temp = readl(sport->port.membase + UCR2);
@@ -731,9 +716,11 @@ static const char *imx_type(struct uart_port *port)
*/
static void imx_release_port(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct platform_device *pdev = to_platform_device(port->dev);
+ struct resource *mmres;
- release_mem_region(sport->port.mapbase, UART_PORT_SIZE);
+ mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(mmres->start, mmres->end - mmres->start + 1);
}
/*
@@ -741,10 +728,18 @@ static void imx_release_port(struct uart_port *port)
*/
static int imx_request_port(struct uart_port *port)
{
- struct imx_port *sport = (struct imx_port *)port;
+ struct platform_device *pdev = to_platform_device(port->dev);
+ struct resource *mmres;
+ void *ret;
+
+ mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mmres)
+ return -ENODEV;
+
+ ret = request_mem_region(mmres->start, mmres->end - mmres->start + 1,
+ "imx-uart");
- return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
- "imx-uart") != NULL ? 0 : -EBUSY;
+ return ret ? 0 : -EBUSY;
}
/*
@@ -815,7 +810,7 @@ static struct imx_port imx_ports[] = {
.type = PORT_IMX,
.iotype = UPIO_MEM,
.membase = (void *)IMX_UART1_BASE,
- .mapbase = IMX_UART1_BASE, /* FIXME */
+ .mapbase = 0x00206000,
.irq = UART1_MINT_RX,
.uartclk = 16000000,
.fifosize = 32,
@@ -831,7 +826,7 @@ static struct imx_port imx_ports[] = {
.type = PORT_IMX,
.iotype = UPIO_MEM,
.membase = (void *)IMX_UART2_BASE,
- .mapbase = IMX_UART2_BASE, /* FIXME */
+ .mapbase = 0x00207000,
.irq = UART2_MINT_RX,
.uartclk = 16000000,
.fifosize = 32,
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index eff593080d4..c2ea5d4df44 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -333,7 +333,6 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
}
sci_out(port, SCFCR, fcr_val);
}
-
#elif defined(CONFIG_CPU_SH3)
/* For SH7705, SH7706, SH7707, SH7709, SH7709A, SH7729 */
static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
@@ -384,6 +383,12 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
sci_out(port, SCFCR, fcr_val);
}
+#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
+static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
+{
+ /* Nothing to do here.. */
+ sci_out(port, SCFCR, 0);
+}
#else
/* For SH7750 */
static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index 01a9dd715f5..fa8700a968f 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -1,20 +1,5 @@
-/* $Id: sh-sci.h,v 1.4 2004/02/19 16:43:56 lethal Exp $
- *
- * linux/drivers/serial/sh-sci.h
- *
- * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO)
- * Copyright (C) 1999, 2000 Niibe Yutaka
- * Copyright (C) 2000 Greg Banks
- * Copyright (C) 2002, 2003 Paul Mundt
- * Modified to support multiple serial ports. Stuart Menefy (May 2000).
- * Modified to support SH7300(SH-Mobile) SCIF. Takashi Kusuda (Jun 2003).
- * Modified to support H8/300 Series Yoshinori Sato (Feb 2004).
- * Removed SH7300 support (Jul 2007).
- * Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Aug 2007).
- */
#include <linux/serial_core.h>
#include <asm/io.h>
-
#include <asm/gpio.h>
#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
@@ -102,6 +87,15 @@
# define SCSPTR0 SCPDR0
# define SCIF_ORER 0x0001 /* overrun error bit */
# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
+# define SCSPTR0 0xa4050160
+# define SCSPTR1 0xa405013e
+# define SCSPTR2 0xa4050160
+# define SCSPTR3 0xa405013e
+# define SCSPTR4 0xa4050128
+# define SCSPTR5 0xa4050128
+# define SCIF_ORER 0x0001 /* overrun error bit */
+# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
# define SCIF_ONLY
#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
# define SCSPTR2 0xffe80020 /* 16 bit SCIF */
@@ -395,6 +389,11 @@
h8_sci_offset, h8_sci_size) \
CPU_SCI_FNS(name, h8_sci_offset, h8_sci_size)
#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
+ #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) \
+ CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size)
+ #define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \
+ CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
#else
#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
@@ -419,6 +418,18 @@ SCIF_FNS(SCFDR, 0x1c, 16)
SCIF_FNS(SCxTDR, 0x20, 8)
SCIF_FNS(SCxRDR, 0x24, 8)
SCIF_FNS(SCLSR, 0x24, 16)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
+SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16)
+SCIx_FNS(SCBRR, 0x04, 8, 0x04, 8)
+SCIx_FNS(SCSCR, 0x08, 16, 0x08, 16)
+SCIx_FNS(SCxTDR, 0x20, 8, 0x0c, 8)
+SCIx_FNS(SCxSR, 0x14, 16, 0x10, 16)
+SCIx_FNS(SCxRDR, 0x24, 8, 0x14, 8)
+SCIF_FNS(SCTDSR, 0x0c, 8)
+SCIF_FNS(SCFER, 0x10, 16)
+SCIF_FNS(SCFCR, 0x18, 16)
+SCIF_FNS(SCFDR, 0x1c, 16)
+SCIF_FNS(SCLSR, 0x24, 16)
#else
/* reg SCI/SH3 SCI/SH4 SCIF/SH3 SCIF/SH4 SCI/H8*/
/* name off sz off sz off sz off sz off sz*/
@@ -589,6 +600,23 @@ static inline int sci_rxd_in(struct uart_port *port)
return ctrl_inb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */
return 1;
}
+#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+ if (port->mapbase == 0xffe00000)
+ return ctrl_inb(SCSPTR0) & 0x0008 ? 1 : 0; /* SCIF0 */
+ if (port->mapbase == 0xffe10000)
+ return ctrl_inb(SCSPTR1) & 0x0020 ? 1 : 0; /* SCIF1 */
+ if (port->mapbase == 0xffe20000)
+ return ctrl_inb(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF2 */
+ if (port->mapbase == 0xa4e30000)
+ return ctrl_inb(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF3 */
+ if (port->mapbase == 0xa4e40000)
+ return ctrl_inb(SCSPTR4) & 0x0001 ? 1 : 0; /* SCIF4 */
+ if (port->mapbase == 0xa4e50000)
+ return ctrl_inb(SCSPTR5) & 0x0008 ? 1 : 0; /* SCIF5 */
+ return 1;
+}
#elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
static inline int sci_rxd_in(struct uart_port *port)
{
@@ -727,6 +755,8 @@ static inline int sci_rxd_in(struct uart_port *port)
defined(CONFIG_CPU_SUBTYPE_SH7720) || \
defined(CONFIG_CPU_SUBTYPE_SH7721)
#define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
+#define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(16*bps)-1)
#elif defined(__H8300H__) || defined(__H8300S__)
#define SCBRR_VALUE(bps) (((CONFIG_CPU_CLOCK*1000/32)/bps)-1)
#elif defined(CONFIG_SUPERH64)
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 46ee7f4c091..85074cb36f3 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1033,7 +1033,7 @@ MODULE_LICENSE ("GPL");
#define OF_PLATFORM_DRIVER ehci_hcd_ppc_of_driver
#endif
-#ifdef CONFIG_ARCH_ORION
+#ifdef CONFIG_PLAT_ORION
#include "ehci-orion.c"
#define PLATFORM_DRIVER ehci_orion_driver
#endif
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index e129981f139..d187d031374 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -11,15 +11,18 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <asm/arch/orion.h>
+#include <linux/mbus.h>
+#include <asm/plat-orion/ehci-orion.h>
#define rdl(off) __raw_readl(hcd->regs + (off))
#define wrl(off, val) __raw_writel((val), hcd->regs + (off))
-#define USB_CAUSE 0x310
-#define USB_MASK 0x314
#define USB_CMD 0x140
#define USB_MODE 0x1a8
+#define USB_CAUSE 0x310
+#define USB_MASK 0x314
+#define USB_WINDOW_CTRL(i) (0x320 + ((i) << 4))
+#define USB_WINDOW_BASE(i) (0x324 + ((i) << 4))
#define USB_IPG 0x360
#define USB_PHY_PWR_CTRL 0x400
#define USB_PHY_TX_CTRL 0x420
@@ -162,8 +165,30 @@ static const struct hc_driver ehci_orion_hc_driver = {
.bus_resume = ehci_bus_resume,
};
+static void __init
+ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
+ struct mbus_dram_target_info *dram)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ wrl(USB_WINDOW_CTRL(i), 0);
+ wrl(USB_WINDOW_BASE(i), 0);
+ }
+
+ for (i = 0; i < dram->num_cs; i++) {
+ struct mbus_dram_window *cs = dram->cs + i;
+
+ wrl(USB_WINDOW_CTRL(i), ((cs->size - 1) & 0xffff0000) |
+ (cs->mbus_attr << 8) |
+ (dram->mbus_dram_target_id << 4) | 1);
+ wrl(USB_WINDOW_BASE(i), cs->base);
+ }
+}
+
static int __init ehci_orion_drv_probe(struct platform_device *pdev)
{
+ struct orion_ehci_data *pd = pdev->dev.platform_data;
struct resource *res;
struct usb_hcd *hcd;
struct ehci_hcd *ehci;
@@ -227,6 +252,12 @@ static int __init ehci_orion_drv_probe(struct platform_device *pdev)
ehci->sbrn = 0x20;
/*
+ * (Re-)program MBUS remapping windows if we are asked to.
+ */
+ if (pd != NULL && pd->dram != NULL)
+ ehci_orion_conf_mbus_windows(hcd, pd->dram);
+
+ /*
* setup Orion USB controller
*/
orion_usb_setup(hcd);
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 97facb121c7..757651954e6 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -45,6 +45,7 @@
#include <asm/irq.h>
#include <asm/div64.h>
#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
#include <asm/arch/bitfield.h>
#include <asm/arch/pxafb.h>