162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
362306a36Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
462306a36Sopenharmony_ci * for more details.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/init.h>
1062306a36Sopenharmony_ci#include <linux/kernel.h>
1162306a36Sopenharmony_ci#include <asm/bootinfo.h>
1262306a36Sopenharmony_ci#include <linux/platform_device.h>
1362306a36Sopenharmony_ci#include <bcm63xx_cs.h>
1462306a36Sopenharmony_ci#include <bcm63xx_cpu.h>
1562306a36Sopenharmony_ci#include <bcm63xx_dev_pcmcia.h>
1662306a36Sopenharmony_ci#include <bcm63xx_io.h>
1762306a36Sopenharmony_ci#include <bcm63xx_regs.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistatic struct resource pcmcia_resources[] = {
2062306a36Sopenharmony_ci	/* pcmcia registers */
2162306a36Sopenharmony_ci	{
2262306a36Sopenharmony_ci		/* start & end filled at runtime */
2362306a36Sopenharmony_ci		.flags		= IORESOURCE_MEM,
2462306a36Sopenharmony_ci	},
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	/* pcmcia memory zone resources */
2762306a36Sopenharmony_ci	{
2862306a36Sopenharmony_ci		.start		= BCM_PCMCIA_COMMON_BASE_PA,
2962306a36Sopenharmony_ci		.end		= BCM_PCMCIA_COMMON_END_PA,
3062306a36Sopenharmony_ci		.flags		= IORESOURCE_MEM,
3162306a36Sopenharmony_ci	},
3262306a36Sopenharmony_ci	{
3362306a36Sopenharmony_ci		.start		= BCM_PCMCIA_ATTR_BASE_PA,
3462306a36Sopenharmony_ci		.end		= BCM_PCMCIA_ATTR_END_PA,
3562306a36Sopenharmony_ci		.flags		= IORESOURCE_MEM,
3662306a36Sopenharmony_ci	},
3762306a36Sopenharmony_ci	{
3862306a36Sopenharmony_ci		.start		= BCM_PCMCIA_IO_BASE_PA,
3962306a36Sopenharmony_ci		.end		= BCM_PCMCIA_IO_END_PA,
4062306a36Sopenharmony_ci		.flags		= IORESOURCE_MEM,
4162306a36Sopenharmony_ci	},
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	/* PCMCIA irq */
4462306a36Sopenharmony_ci	{
4562306a36Sopenharmony_ci		/* start filled at runtime */
4662306a36Sopenharmony_ci		.flags		= IORESOURCE_IRQ,
4762306a36Sopenharmony_ci	},
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	/* declare PCMCIA IO resource also */
5062306a36Sopenharmony_ci	{
5162306a36Sopenharmony_ci		.start		= BCM_PCMCIA_IO_BASE_PA,
5262306a36Sopenharmony_ci		.end		= BCM_PCMCIA_IO_END_PA,
5362306a36Sopenharmony_ci		.flags		= IORESOURCE_IO,
5462306a36Sopenharmony_ci	},
5562306a36Sopenharmony_ci};
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistatic struct bcm63xx_pcmcia_platform_data pd;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistatic struct platform_device bcm63xx_pcmcia_device = {
6062306a36Sopenharmony_ci	.name		= "bcm63xx_pcmcia",
6162306a36Sopenharmony_ci	.id		= 0,
6262306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(pcmcia_resources),
6362306a36Sopenharmony_ci	.resource	= pcmcia_resources,
6462306a36Sopenharmony_ci	.dev		= {
6562306a36Sopenharmony_ci		.platform_data = &pd,
6662306a36Sopenharmony_ci	},
6762306a36Sopenharmony_ci};
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistatic int __init config_pcmcia_cs(unsigned int cs,
7062306a36Sopenharmony_ci				   u32 base, unsigned int size)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	int ret;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	ret = bcm63xx_set_cs_status(cs, 0);
7562306a36Sopenharmony_ci	if (!ret)
7662306a36Sopenharmony_ci		ret = bcm63xx_set_cs_base(cs, base, size);
7762306a36Sopenharmony_ci	if (!ret)
7862306a36Sopenharmony_ci		ret = bcm63xx_set_cs_status(cs, 1);
7962306a36Sopenharmony_ci	return ret;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic const struct {
8362306a36Sopenharmony_ci	unsigned int	cs;
8462306a36Sopenharmony_ci	unsigned int	base;
8562306a36Sopenharmony_ci	unsigned int	size;
8662306a36Sopenharmony_ci} pcmcia_cs[3] __initconst = {
8762306a36Sopenharmony_ci	{
8862306a36Sopenharmony_ci		.cs	= MPI_CS_PCMCIA_COMMON,
8962306a36Sopenharmony_ci		.base	= BCM_PCMCIA_COMMON_BASE_PA,
9062306a36Sopenharmony_ci		.size	= BCM_PCMCIA_COMMON_SIZE
9162306a36Sopenharmony_ci	},
9262306a36Sopenharmony_ci	{
9362306a36Sopenharmony_ci		.cs	= MPI_CS_PCMCIA_ATTR,
9462306a36Sopenharmony_ci		.base	= BCM_PCMCIA_ATTR_BASE_PA,
9562306a36Sopenharmony_ci		.size	= BCM_PCMCIA_ATTR_SIZE
9662306a36Sopenharmony_ci	},
9762306a36Sopenharmony_ci	{
9862306a36Sopenharmony_ci		.cs	= MPI_CS_PCMCIA_IO,
9962306a36Sopenharmony_ci		.base	= BCM_PCMCIA_IO_BASE_PA,
10062306a36Sopenharmony_ci		.size	= BCM_PCMCIA_IO_SIZE
10162306a36Sopenharmony_ci	},
10262306a36Sopenharmony_ci};
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ciint __init bcm63xx_pcmcia_register(void)
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	int ret, i;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	if (!BCMCPU_IS_6348() && !BCMCPU_IS_6358())
10962306a36Sopenharmony_ci		return 0;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	/* use correct pcmcia ready gpio depending on processor */
11262306a36Sopenharmony_ci	switch (bcm63xx_get_cpu_id()) {
11362306a36Sopenharmony_ci	case BCM6348_CPU_ID:
11462306a36Sopenharmony_ci		pd.ready_gpio = 22;
11562306a36Sopenharmony_ci		break;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	case BCM6358_CPU_ID:
11862306a36Sopenharmony_ci		pd.ready_gpio = 18;
11962306a36Sopenharmony_ci		break;
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	default:
12262306a36Sopenharmony_ci		return -ENODEV;
12362306a36Sopenharmony_ci	}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	pcmcia_resources[0].start = bcm63xx_regset_address(RSET_PCMCIA);
12662306a36Sopenharmony_ci	pcmcia_resources[0].end = pcmcia_resources[0].start +
12762306a36Sopenharmony_ci		RSET_PCMCIA_SIZE - 1;
12862306a36Sopenharmony_ci	pcmcia_resources[4].start = bcm63xx_get_irq_number(IRQ_PCMCIA);
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	/* configure pcmcia chip selects */
13162306a36Sopenharmony_ci	for (i = 0; i < 3; i++) {
13262306a36Sopenharmony_ci		ret = config_pcmcia_cs(pcmcia_cs[i].cs,
13362306a36Sopenharmony_ci				       pcmcia_cs[i].base,
13462306a36Sopenharmony_ci				       pcmcia_cs[i].size);
13562306a36Sopenharmony_ci		if (ret)
13662306a36Sopenharmony_ci			goto out_err;
13762306a36Sopenharmony_ci	}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	return platform_device_register(&bcm63xx_pcmcia_device);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ciout_err:
14262306a36Sopenharmony_ci	pr_err("unable to set pcmcia chip select\n");
14362306a36Sopenharmony_ci	return ret;
14462306a36Sopenharmony_ci}
145