^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * License. See the file "COPYING" in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/bootinfo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <bcm63xx_cs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <bcm63xx_cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <bcm63xx_dev_pcmcia.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <bcm63xx_io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <bcm63xx_regs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static struct resource pcmcia_resources[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* pcmcia registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* start & end filled at runtime */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* pcmcia memory zone resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) .start = BCM_PCMCIA_COMMON_BASE_PA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) .end = BCM_PCMCIA_COMMON_END_PA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) .start = BCM_PCMCIA_ATTR_BASE_PA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) .end = BCM_PCMCIA_ATTR_END_PA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) .start = BCM_PCMCIA_IO_BASE_PA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) .end = BCM_PCMCIA_IO_END_PA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /* PCMCIA irq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* start filled at runtime */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .flags = IORESOURCE_IRQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* declare PCMCIA IO resource also */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .start = BCM_PCMCIA_IO_BASE_PA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .end = BCM_PCMCIA_IO_END_PA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .flags = IORESOURCE_IO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static struct bcm63xx_pcmcia_platform_data pd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static struct platform_device bcm63xx_pcmcia_device = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .name = "bcm63xx_pcmcia",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .id = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .num_resources = ARRAY_SIZE(pcmcia_resources),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) .resource = pcmcia_resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) .dev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) .platform_data = &pd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static int __init config_pcmcia_cs(unsigned int cs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) u32 base, unsigned int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) ret = bcm63xx_set_cs_status(cs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) ret = bcm63xx_set_cs_base(cs, base, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) ret = bcm63xx_set_cs_status(cs, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static const struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) unsigned int cs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) unsigned int base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) unsigned int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) } pcmcia_cs[3] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .cs = MPI_CS_PCMCIA_COMMON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .base = BCM_PCMCIA_COMMON_BASE_PA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .size = BCM_PCMCIA_COMMON_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .cs = MPI_CS_PCMCIA_ATTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .base = BCM_PCMCIA_ATTR_BASE_PA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .size = BCM_PCMCIA_ATTR_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .cs = MPI_CS_PCMCIA_IO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .base = BCM_PCMCIA_IO_BASE_PA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .size = BCM_PCMCIA_IO_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) int __init bcm63xx_pcmcia_register(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (!BCMCPU_IS_6348() && !BCMCPU_IS_6358())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* use correct pcmcia ready gpio depending on processor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) switch (bcm63xx_get_cpu_id()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) case BCM6348_CPU_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) pd.ready_gpio = 22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) case BCM6358_CPU_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) pd.ready_gpio = 18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) pcmcia_resources[0].start = bcm63xx_regset_address(RSET_PCMCIA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) pcmcia_resources[0].end = pcmcia_resources[0].start +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) RSET_PCMCIA_SIZE - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) pcmcia_resources[4].start = bcm63xx_get_irq_number(IRQ_PCMCIA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* configure pcmcia chip selects */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) for (i = 0; i < 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ret = config_pcmcia_cs(pcmcia_cs[i].cs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) pcmcia_cs[i].base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) pcmcia_cs[i].size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return platform_device_register(&bcm63xx_pcmcia_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) pr_err("unable to set pcmcia chip select\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }