Path: blob/master/arch/mips/bcm63xx/boards/board_bcm963xx.c
10821 views
/*1* This file is subject to the terms and conditions of the GNU General Public2* License. See the file "COPYING" in the main directory of this archive3* for more details.4*5* Copyright (C) 2008 Maxime Bizon <[email protected]>6* Copyright (C) 2008 Florian Fainelli <[email protected]>7*/89#include <linux/init.h>10#include <linux/kernel.h>11#include <linux/string.h>12#include <linux/platform_device.h>13#include <linux/mtd/mtd.h>14#include <linux/mtd/partitions.h>15#include <linux/mtd/physmap.h>16#include <linux/ssb/ssb.h>17#include <asm/addrspace.h>18#include <bcm63xx_board.h>19#include <bcm63xx_cpu.h>20#include <bcm63xx_dev_uart.h>21#include <bcm63xx_regs.h>22#include <bcm63xx_io.h>23#include <bcm63xx_dev_pci.h>24#include <bcm63xx_dev_enet.h>25#include <bcm63xx_dev_dsp.h>26#include <bcm63xx_dev_pcmcia.h>27#include <board_bcm963xx.h>2829#define PFX "board_bcm963xx: "3031static struct bcm963xx_nvram nvram;32static unsigned int mac_addr_used;33static struct board_info board;3435/*36* known 6338 boards37*/38#ifdef CONFIG_BCM63XX_CPU_633839static struct board_info __initdata board_96338gw = {40.name = "96338GW",41.expected_cpu_id = 0x6338,4243.has_uart0 = 1,44.has_enet0 = 1,45.enet0 = {46.force_speed_100 = 1,47.force_duplex_full = 1,48},4950.has_ohci0 = 1,5152.leds = {53{54.name = "adsl",55.gpio = 3,56.active_low = 1,57},58{59.name = "ses",60.gpio = 5,61.active_low = 1,62},63{64.name = "ppp-fail",65.gpio = 4,66.active_low = 1,67},68{69.name = "power",70.gpio = 0,71.active_low = 1,72.default_trigger = "default-on",73},74{75.name = "stop",76.gpio = 1,77.active_low = 1,78}79},80};8182static struct board_info __initdata board_96338w = {83.name = "96338W",84.expected_cpu_id = 0x6338,8586.has_uart0 = 1,87.has_enet0 = 1,88.enet0 = {89.force_speed_100 = 1,90.force_duplex_full = 1,91},9293.leds = {94{95.name = "adsl",96.gpio = 3,97.active_low = 1,98},99{100.name = "ses",101.gpio = 5,102.active_low = 1,103},104{105.name = "ppp-fail",106.gpio = 4,107.active_low = 1,108},109{110.name = "power",111.gpio = 0,112.active_low = 1,113.default_trigger = "default-on",114},115{116.name = "stop",117.gpio = 1,118.active_low = 1,119},120},121};122#endif123124/*125* known 6345 boards126*/127#ifdef CONFIG_BCM63XX_CPU_6345128static struct board_info __initdata board_96345gw2 = {129.name = "96345GW2",130.expected_cpu_id = 0x6345,131132.has_uart0 = 1,133};134#endif135136/*137* known 6348 boards138*/139#ifdef CONFIG_BCM63XX_CPU_6348140static struct board_info __initdata board_96348r = {141.name = "96348R",142.expected_cpu_id = 0x6348,143144.has_uart0 = 1,145.has_enet0 = 1,146.has_pci = 1,147148.enet0 = {149.has_phy = 1,150.use_internal_phy = 1,151},152153.leds = {154{155.name = "adsl-fail",156.gpio = 2,157.active_low = 1,158},159{160.name = "ppp",161.gpio = 3,162.active_low = 1,163},164{165.name = "ppp-fail",166.gpio = 4,167.active_low = 1,168},169{170.name = "power",171.gpio = 0,172.active_low = 1,173.default_trigger = "default-on",174175},176{177.name = "stop",178.gpio = 1,179.active_low = 1,180},181},182};183184static struct board_info __initdata board_96348gw_10 = {185.name = "96348GW-10",186.expected_cpu_id = 0x6348,187188.has_uart0 = 1,189.has_enet0 = 1,190.has_enet1 = 1,191.has_pci = 1,192193.enet0 = {194.has_phy = 1,195.use_internal_phy = 1,196},197.enet1 = {198.force_speed_100 = 1,199.force_duplex_full = 1,200},201202.has_ohci0 = 1,203.has_pccard = 1,204.has_ehci0 = 1,205206.has_dsp = 1,207.dsp = {208.gpio_rst = 6,209.gpio_int = 34,210.cs = 2,211.ext_irq = 2,212},213214.leds = {215{216.name = "adsl-fail",217.gpio = 2,218.active_low = 1,219},220{221.name = "ppp",222.gpio = 3,223.active_low = 1,224},225{226.name = "ppp-fail",227.gpio = 4,228.active_low = 1,229},230{231.name = "power",232.gpio = 0,233.active_low = 1,234.default_trigger = "default-on",235},236{237.name = "stop",238.gpio = 1,239.active_low = 1,240},241},242};243244static struct board_info __initdata board_96348gw_11 = {245.name = "96348GW-11",246.expected_cpu_id = 0x6348,247248.has_uart0 = 1,249.has_enet0 = 1,250.has_enet1 = 1,251.has_pci = 1,252253.enet0 = {254.has_phy = 1,255.use_internal_phy = 1,256},257258.enet1 = {259.force_speed_100 = 1,260.force_duplex_full = 1,261},262263264.has_ohci0 = 1,265.has_pccard = 1,266.has_ehci0 = 1,267268.leds = {269{270.name = "adsl-fail",271.gpio = 2,272.active_low = 1,273},274{275.name = "ppp",276.gpio = 3,277.active_low = 1,278},279{280.name = "ppp-fail",281.gpio = 4,282.active_low = 1,283},284{285.name = "power",286.gpio = 0,287.active_low = 1,288.default_trigger = "default-on",289},290{291.name = "stop",292.gpio = 1,293.active_low = 1,294},295},296};297298static struct board_info __initdata board_96348gw = {299.name = "96348GW",300.expected_cpu_id = 0x6348,301302.has_uart0 = 1,303.has_enet0 = 1,304.has_enet1 = 1,305.has_pci = 1,306307.enet0 = {308.has_phy = 1,309.use_internal_phy = 1,310},311.enet1 = {312.force_speed_100 = 1,313.force_duplex_full = 1,314},315316.has_ohci0 = 1,317318.has_dsp = 1,319.dsp = {320.gpio_rst = 6,321.gpio_int = 34,322.ext_irq = 2,323.cs = 2,324},325326.leds = {327{328.name = "adsl-fail",329.gpio = 2,330.active_low = 1,331},332{333.name = "ppp",334.gpio = 3,335.active_low = 1,336},337{338.name = "ppp-fail",339.gpio = 4,340.active_low = 1,341},342{343.name = "power",344.gpio = 0,345.active_low = 1,346.default_trigger = "default-on",347},348{349.name = "stop",350.gpio = 1,351.active_low = 1,352},353},354};355356static struct board_info __initdata board_FAST2404 = {357.name = "F@ST2404",358.expected_cpu_id = 0x6348,359360.has_uart0 = 1,361.has_enet0 = 1,362.has_enet1 = 1,363.has_pci = 1,364365.enet0 = {366.has_phy = 1,367.use_internal_phy = 1,368},369370.enet1 = {371.force_speed_100 = 1,372.force_duplex_full = 1,373},374375.has_ohci0 = 1,376.has_pccard = 1,377.has_ehci0 = 1,378};379380static struct board_info __initdata board_rta1025w_16 = {381.name = "RTA1025W_16",382.expected_cpu_id = 0x6348,383384.has_enet0 = 1,385.has_enet1 = 1,386.has_pci = 1,387388.enet0 = {389.has_phy = 1,390.use_internal_phy = 1,391},392.enet1 = {393.force_speed_100 = 1,394.force_duplex_full = 1,395},396};397398399static struct board_info __initdata board_DV201AMR = {400.name = "DV201AMR",401.expected_cpu_id = 0x6348,402403.has_uart0 = 1,404.has_pci = 1,405.has_ohci0 = 1,406407.has_enet0 = 1,408.has_enet1 = 1,409.enet0 = {410.has_phy = 1,411.use_internal_phy = 1,412},413.enet1 = {414.force_speed_100 = 1,415.force_duplex_full = 1,416},417};418419static struct board_info __initdata board_96348gw_a = {420.name = "96348GW-A",421.expected_cpu_id = 0x6348,422423.has_uart0 = 1,424.has_enet0 = 1,425.has_enet1 = 1,426.has_pci = 1,427428.enet0 = {429.has_phy = 1,430.use_internal_phy = 1,431},432.enet1 = {433.force_speed_100 = 1,434.force_duplex_full = 1,435},436437.has_ohci0 = 1,438};439#endif440441/*442* known 6358 boards443*/444#ifdef CONFIG_BCM63XX_CPU_6358445static struct board_info __initdata board_96358vw = {446.name = "96358VW",447.expected_cpu_id = 0x6358,448449.has_uart0 = 1,450.has_enet0 = 1,451.has_enet1 = 1,452.has_pci = 1,453454.enet0 = {455.has_phy = 1,456.use_internal_phy = 1,457},458459.enet1 = {460.force_speed_100 = 1,461.force_duplex_full = 1,462},463464465.has_ohci0 = 1,466.has_pccard = 1,467.has_ehci0 = 1,468469.leds = {470{471.name = "adsl-fail",472.gpio = 15,473.active_low = 1,474},475{476.name = "ppp",477.gpio = 22,478.active_low = 1,479},480{481.name = "ppp-fail",482.gpio = 23,483.active_low = 1,484},485{486.name = "power",487.gpio = 4,488.default_trigger = "default-on",489},490{491.name = "stop",492.gpio = 5,493},494},495};496497static struct board_info __initdata board_96358vw2 = {498.name = "96358VW2",499.expected_cpu_id = 0x6358,500501.has_uart0 = 1,502.has_enet0 = 1,503.has_enet1 = 1,504.has_pci = 1,505506.enet0 = {507.has_phy = 1,508.use_internal_phy = 1,509},510511.enet1 = {512.force_speed_100 = 1,513.force_duplex_full = 1,514},515516517.has_ohci0 = 1,518.has_pccard = 1,519.has_ehci0 = 1,520521.leds = {522{523.name = "adsl",524.gpio = 22,525.active_low = 1,526},527{528.name = "ppp-fail",529.gpio = 23,530},531{532.name = "power",533.gpio = 5,534.active_low = 1,535.default_trigger = "default-on",536},537{538.name = "stop",539.gpio = 4,540.active_low = 1,541},542},543};544545static struct board_info __initdata board_AGPFS0 = {546.name = "AGPF-S0",547.expected_cpu_id = 0x6358,548549.has_uart0 = 1,550.has_enet0 = 1,551.has_enet1 = 1,552.has_pci = 1,553554.enet0 = {555.has_phy = 1,556.use_internal_phy = 1,557},558559.enet1 = {560.force_speed_100 = 1,561.force_duplex_full = 1,562},563564.has_ohci0 = 1,565.has_ehci0 = 1,566};567568static struct board_info __initdata board_DWVS0 = {569.name = "DWV-S0",570.expected_cpu_id = 0x6358,571572.has_enet0 = 1,573.has_enet1 = 1,574.has_pci = 1,575576.enet0 = {577.has_phy = 1,578.use_internal_phy = 1,579},580581.enet1 = {582.force_speed_100 = 1,583.force_duplex_full = 1,584},585586.has_ohci0 = 1,587};588#endif589590/*591* all boards592*/593static const struct board_info __initdata *bcm963xx_boards[] = {594#ifdef CONFIG_BCM63XX_CPU_6338595&board_96338gw,596&board_96338w,597#endif598#ifdef CONFIG_BCM63XX_CPU_6345599&board_96345gw2,600#endif601#ifdef CONFIG_BCM63XX_CPU_6348602&board_96348r,603&board_96348gw,604&board_96348gw_10,605&board_96348gw_11,606&board_FAST2404,607&board_DV201AMR,608&board_96348gw_a,609&board_rta1025w_16,610#endif611612#ifdef CONFIG_BCM63XX_CPU_6358613&board_96358vw,614&board_96358vw2,615&board_AGPFS0,616&board_DWVS0,617#endif618};619620/*621* Register a sane SPROMv2 to make the on-board622* bcm4318 WLAN work623*/624#ifdef CONFIG_SSB_PCIHOST625static struct ssb_sprom bcm63xx_sprom = {626.revision = 0x02,627.board_rev = 0x17,628.country_code = 0x0,629.ant_available_bg = 0x3,630.pa0b0 = 0x15ae,631.pa0b1 = 0xfa85,632.pa0b2 = 0xfe8d,633.pa1b0 = 0xffff,634.pa1b1 = 0xffff,635.pa1b2 = 0xffff,636.gpio0 = 0xff,637.gpio1 = 0xff,638.gpio2 = 0xff,639.gpio3 = 0xff,640.maxpwr_bg = 0x004c,641.itssi_bg = 0x00,642.boardflags_lo = 0x2848,643.boardflags_hi = 0x0000,644};645646int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)647{648if (bus->bustype == SSB_BUSTYPE_PCI) {649memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));650return 0;651} else {652printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");653return -EINVAL;654}655}656#endif657658/*659* return board name for /proc/cpuinfo660*/661const char *board_get_name(void)662{663return board.name;664}665666/*667* register & return a new board mac address668*/669static int board_get_mac_address(u8 *mac)670{671u8 *p;672int count;673674if (mac_addr_used >= nvram.mac_addr_count) {675printk(KERN_ERR PFX "not enough mac address\n");676return -ENODEV;677}678679memcpy(mac, nvram.mac_addr_base, ETH_ALEN);680p = mac + ETH_ALEN - 1;681count = mac_addr_used;682683while (count--) {684do {685(*p)++;686if (*p != 0)687break;688p--;689} while (p != mac);690}691692if (p == mac) {693printk(KERN_ERR PFX "unable to fetch mac address\n");694return -ENODEV;695}696697mac_addr_used++;698return 0;699}700701/*702* early init callback, read nvram data from flash and checksum it703*/704void __init board_prom_init(void)705{706unsigned int check_len, i;707u8 *boot_addr, *cfe, *p;708char cfe_version[32];709u32 val;710711/* read base address of boot chip select (0)712* 6345 does not have MPI but boots from standard713* MIPS Flash address */714if (BCMCPU_IS_6345())715val = 0x1fc00000;716else {717val = bcm_mpi_readl(MPI_CSBASE_REG(0));718val &= MPI_CSBASE_BASE_MASK;719}720boot_addr = (u8 *)KSEG1ADDR(val);721722/* dump cfe version */723cfe = boot_addr + BCM963XX_CFE_VERSION_OFFSET;724if (!memcmp(cfe, "cfe-v", 5))725snprintf(cfe_version, sizeof(cfe_version), "%u.%u.%u-%u.%u",726cfe[5], cfe[6], cfe[7], cfe[8], cfe[9]);727else728strcpy(cfe_version, "unknown");729printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);730731/* extract nvram data */732memcpy(&nvram, boot_addr + BCM963XX_NVRAM_OFFSET, sizeof(nvram));733734/* check checksum before using data */735if (nvram.version <= 4)736check_len = offsetof(struct bcm963xx_nvram, checksum_old);737else738check_len = sizeof(nvram);739val = 0;740p = (u8 *)&nvram;741while (check_len--)742val += *p;743if (val) {744printk(KERN_ERR PFX "invalid nvram checksum\n");745return;746}747748/* find board by name */749for (i = 0; i < ARRAY_SIZE(bcm963xx_boards); i++) {750if (strncmp(nvram.name, bcm963xx_boards[i]->name,751sizeof(nvram.name)))752continue;753/* copy, board desc array is marked initdata */754memcpy(&board, bcm963xx_boards[i], sizeof(board));755break;756}757758/* bail out if board is not found, will complain later */759if (!board.name[0]) {760char name[17];761memcpy(name, nvram.name, 16);762name[16] = 0;763printk(KERN_ERR PFX "unknown bcm963xx board: %s\n",764name);765return;766}767768/* setup pin multiplexing depending on board enabled device,769* this has to be done this early since PCI init is done770* inside arch_initcall */771val = 0;772773#ifdef CONFIG_PCI774if (board.has_pci) {775bcm63xx_pci_enabled = 1;776if (BCMCPU_IS_6348())777val |= GPIO_MODE_6348_G2_PCI;778}779#endif780781if (board.has_pccard) {782if (BCMCPU_IS_6348())783val |= GPIO_MODE_6348_G1_MII_PCCARD;784}785786if (board.has_enet0 && !board.enet0.use_internal_phy) {787if (BCMCPU_IS_6348())788val |= GPIO_MODE_6348_G3_EXT_MII |789GPIO_MODE_6348_G0_EXT_MII;790}791792if (board.has_enet1 && !board.enet1.use_internal_phy) {793if (BCMCPU_IS_6348())794val |= GPIO_MODE_6348_G3_EXT_MII |795GPIO_MODE_6348_G0_EXT_MII;796}797798bcm_gpio_writel(val, GPIO_MODE_REG);799800/* Generate MAC address for WLAN and801* register our SPROM */802#ifdef CONFIG_SSB_PCIHOST803if (!board_get_mac_address(bcm63xx_sprom.il0mac)) {804memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);805memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);806if (ssb_arch_register_fallback_sprom(807&bcm63xx_get_fallback_sprom) < 0)808printk(KERN_ERR PFX "failed to register fallback SPROM\n");809}810#endif811}812813/*814* second stage init callback, good time to panic if we couldn't815* identify on which board we're running since early printk is working816*/817void __init board_setup(void)818{819if (!board.name[0])820panic("unable to detect bcm963xx board");821printk(KERN_INFO PFX "board name: %s\n", board.name);822823/* make sure we're running on expected cpu */824if (bcm63xx_get_cpu_id() != board.expected_cpu_id)825panic("unexpected CPU for bcm963xx board");826}827828static struct mtd_partition mtd_partitions[] = {829{830.name = "cfe",831.offset = 0x0,832.size = 0x40000,833}834};835836static struct physmap_flash_data flash_data = {837.width = 2,838.nr_parts = ARRAY_SIZE(mtd_partitions),839.parts = mtd_partitions,840};841842static struct resource mtd_resources[] = {843{844.start = 0, /* filled at runtime */845.end = 0, /* filled at runtime */846.flags = IORESOURCE_MEM,847}848};849850static struct platform_device mtd_dev = {851.name = "physmap-flash",852.resource = mtd_resources,853.num_resources = ARRAY_SIZE(mtd_resources),854.dev = {855.platform_data = &flash_data,856},857};858859static struct gpio_led_platform_data bcm63xx_led_data;860861static struct platform_device bcm63xx_gpio_leds = {862.name = "leds-gpio",863.id = 0,864.dev.platform_data = &bcm63xx_led_data,865};866867/*868* third stage init callback, register all board devices.869*/870int __init board_register_devices(void)871{872u32 val;873874if (board.has_uart0)875bcm63xx_uart_register(0);876877if (board.has_uart1)878bcm63xx_uart_register(1);879880if (board.has_pccard)881bcm63xx_pcmcia_register();882883if (board.has_enet0 &&884!board_get_mac_address(board.enet0.mac_addr))885bcm63xx_enet_register(0, &board.enet0);886887if (board.has_enet1 &&888!board_get_mac_address(board.enet1.mac_addr))889bcm63xx_enet_register(1, &board.enet1);890891if (board.has_dsp)892bcm63xx_dsp_register(&board.dsp);893894/* read base address of boot chip select (0) */895if (BCMCPU_IS_6345())896val = 0x1fc00000;897else {898val = bcm_mpi_readl(MPI_CSBASE_REG(0));899val &= MPI_CSBASE_BASE_MASK;900}901mtd_resources[0].start = val;902mtd_resources[0].end = 0x1FFFFFFF;903904platform_device_register(&mtd_dev);905906bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds);907bcm63xx_led_data.leds = board.leds;908909platform_device_register(&bcm63xx_gpio_leds);910911return 0;912}913914915