11b897cf84
On Alchemy the PCMCIA area lies at the end of the chips 36bit system bus area. Currently, addresses at the far end of the 32bit area are assumed to belong to the PCMCIA area and fixed up to the real 36bit address before being passed to ioremap(). A previous commit enabled 64 bit physical size for the resource datatype on Alchemy and this allows to use the correct 36bit addresses when registering the PCMCIA sockets. This patch removes the 32-to-36bit address fixup and registers the Alchemy demo board pcmcia socket with the correct 36bit physical addresses. Tested on DB1200, with a CF card (ide-cs driver) and a 3c589 PCMCIA ethernet card. Signed-off-by: Manuel Lauss <manuel.lauss@gmail.com> To: Linux-MIPS <linux-mips@linux-mips.org> Cc: Manuel Lauss <manuel.lauss@gmail.com> Patchwork: http://patchwork.linux-mips.org/patch/994/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
223 lines
4.4 KiB
C
223 lines
4.4 KiB
C
/*
|
|
* devoard misc stuff.
|
|
*/
|
|
|
|
#include <linux/init.h>
|
|
#include <linux/mtd/mtd.h>
|
|
#include <linux/mtd/map.h>
|
|
#include <linux/mtd/physmap.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/pm.h>
|
|
|
|
#include <asm/reboot.h>
|
|
#include <asm/mach-db1x00/bcsr.h>
|
|
|
|
static void db1x_power_off(void)
|
|
{
|
|
bcsr_write(BCSR_RESETS, 0);
|
|
bcsr_write(BCSR_SYSTEM, BCSR_SYSTEM_PWROFF | BCSR_SYSTEM_RESET);
|
|
}
|
|
|
|
static void db1x_reset(char *c)
|
|
{
|
|
bcsr_write(BCSR_RESETS, 0);
|
|
bcsr_write(BCSR_SYSTEM, 0);
|
|
}
|
|
|
|
static int __init db1x_poweroff_setup(void)
|
|
{
|
|
if (!pm_power_off)
|
|
pm_power_off = db1x_power_off;
|
|
if (!_machine_halt)
|
|
_machine_halt = db1x_power_off;
|
|
if (!_machine_restart)
|
|
_machine_restart = db1x_reset;
|
|
|
|
return 0;
|
|
}
|
|
late_initcall(db1x_poweroff_setup);
|
|
|
|
/* register a pcmcia socket */
|
|
int __init db1x_register_pcmcia_socket(phys_addr_t pcmcia_attr_start,
|
|
phys_addr_t pcmcia_attr_end,
|
|
phys_addr_t pcmcia_mem_start,
|
|
phys_addr_t pcmcia_mem_end,
|
|
phys_addr_t pcmcia_io_start,
|
|
phys_addr_t pcmcia_io_end,
|
|
int card_irq,
|
|
int cd_irq,
|
|
int stschg_irq,
|
|
int eject_irq,
|
|
int id)
|
|
{
|
|
int cnt, i, ret;
|
|
struct resource *sr;
|
|
struct platform_device *pd;
|
|
|
|
cnt = 5;
|
|
if (eject_irq)
|
|
cnt++;
|
|
if (stschg_irq)
|
|
cnt++;
|
|
|
|
sr = kzalloc(sizeof(struct resource) * cnt, GFP_KERNEL);
|
|
if (!sr)
|
|
return -ENOMEM;
|
|
|
|
pd = platform_device_alloc("db1xxx_pcmcia", id);
|
|
if (!pd) {
|
|
ret = -ENOMEM;
|
|
goto out;
|
|
}
|
|
|
|
sr[0].name = "pcmcia-attr";
|
|
sr[0].flags = IORESOURCE_MEM;
|
|
sr[0].start = pcmcia_attr_start;
|
|
sr[0].end = pcmcia_attr_end;
|
|
|
|
sr[1].name = "pcmcia-mem";
|
|
sr[1].flags = IORESOURCE_MEM;
|
|
sr[1].start = pcmcia_mem_start;
|
|
sr[1].end = pcmcia_mem_end;
|
|
|
|
sr[2].name = "pcmcia-io";
|
|
sr[2].flags = IORESOURCE_MEM;
|
|
sr[2].start = pcmcia_io_start;
|
|
sr[2].end = pcmcia_io_end;
|
|
|
|
sr[3].name = "insert";
|
|
sr[3].flags = IORESOURCE_IRQ;
|
|
sr[3].start = sr[3].end = cd_irq;
|
|
|
|
sr[4].name = "card";
|
|
sr[4].flags = IORESOURCE_IRQ;
|
|
sr[4].start = sr[4].end = card_irq;
|
|
|
|
i = 5;
|
|
if (stschg_irq) {
|
|
sr[i].name = "stschg";
|
|
sr[i].flags = IORESOURCE_IRQ;
|
|
sr[i].start = sr[i].end = stschg_irq;
|
|
i++;
|
|
}
|
|
if (eject_irq) {
|
|
sr[i].name = "eject";
|
|
sr[i].flags = IORESOURCE_IRQ;
|
|
sr[i].start = sr[i].end = eject_irq;
|
|
}
|
|
|
|
pd->resource = sr;
|
|
pd->num_resources = cnt;
|
|
|
|
ret = platform_device_add(pd);
|
|
if (!ret)
|
|
return 0;
|
|
|
|
platform_device_put(pd);
|
|
out:
|
|
kfree(sr);
|
|
return ret;
|
|
}
|
|
|
|
#define YAMON_SIZE 0x00100000
|
|
#define YAMON_ENV_SIZE 0x00040000
|
|
|
|
int __init db1x_register_norflash(unsigned long size, int width,
|
|
int swapped)
|
|
{
|
|
struct physmap_flash_data *pfd;
|
|
struct platform_device *pd;
|
|
struct mtd_partition *parts;
|
|
struct resource *res;
|
|
int ret, i;
|
|
|
|
if (size < (8 * 1024 * 1024))
|
|
return -EINVAL;
|
|
|
|
ret = -ENOMEM;
|
|
parts = kzalloc(sizeof(struct mtd_partition) * 5, GFP_KERNEL);
|
|
if (!parts)
|
|
goto out;
|
|
|
|
res = kzalloc(sizeof(struct resource), GFP_KERNEL);
|
|
if (!res)
|
|
goto out1;
|
|
|
|
pfd = kzalloc(sizeof(struct physmap_flash_data), GFP_KERNEL);
|
|
if (!pfd)
|
|
goto out2;
|
|
|
|
pd = platform_device_alloc("physmap-flash", 0);
|
|
if (!pd)
|
|
goto out3;
|
|
|
|
/* NOR flash ends at 0x20000000, regardless of size */
|
|
res->start = 0x20000000 - size;
|
|
res->end = 0x20000000 - 1;
|
|
res->flags = IORESOURCE_MEM;
|
|
|
|
/* partition setup. Most Develboards have a switch which allows
|
|
* to swap the physical locations of the 2 NOR flash banks.
|
|
*/
|
|
i = 0;
|
|
if (!swapped) {
|
|
/* first NOR chip */
|
|
parts[i].offset = 0;
|
|
parts[i].name = "User FS";
|
|
parts[i].size = size / 2;
|
|
i++;
|
|
}
|
|
|
|
parts[i].offset = MTDPART_OFS_APPEND;
|
|
parts[i].name = "User FS 2";
|
|
parts[i].size = (size / 2) - (0x20000000 - 0x1fc00000);
|
|
i++;
|
|
|
|
parts[i].offset = MTDPART_OFS_APPEND;
|
|
parts[i].name = "YAMON";
|
|
parts[i].size = YAMON_SIZE;
|
|
parts[i].mask_flags = MTD_WRITEABLE;
|
|
i++;
|
|
|
|
parts[i].offset = MTDPART_OFS_APPEND;
|
|
parts[i].name = "raw kernel";
|
|
parts[i].size = 0x00400000 - YAMON_SIZE - YAMON_ENV_SIZE;
|
|
i++;
|
|
|
|
parts[i].offset = MTDPART_OFS_APPEND;
|
|
parts[i].name = "YAMON Env";
|
|
parts[i].size = YAMON_ENV_SIZE;
|
|
parts[i].mask_flags = MTD_WRITEABLE;
|
|
i++;
|
|
|
|
if (swapped) {
|
|
parts[i].offset = MTDPART_OFS_APPEND;
|
|
parts[i].name = "User FS";
|
|
parts[i].size = size / 2;
|
|
i++;
|
|
}
|
|
|
|
pfd->width = width;
|
|
pfd->parts = parts;
|
|
pfd->nr_parts = 5;
|
|
|
|
pd->dev.platform_data = pfd;
|
|
pd->resource = res;
|
|
pd->num_resources = 1;
|
|
|
|
ret = platform_device_add(pd);
|
|
if (!ret)
|
|
return ret;
|
|
|
|
platform_device_put(pd);
|
|
out3:
|
|
kfree(pfd);
|
|
out2:
|
|
kfree(res);
|
|
out1:
|
|
kfree(parts);
|
|
out:
|
|
return ret;
|
|
}
|